Listbox added! Improved keyboard features for Updown and Textbox. Random crash on exit somewhere.
This commit is contained in:
parent
1a5cc62422
commit
71c13fdc71
13 changed files with 696 additions and 51 deletions
|
@ -32,7 +32,7 @@ BINDIR = bin
|
||||||
## CHANGE THIS ##
|
## CHANGE THIS ##
|
||||||
|
|
||||||
# CFLAGS, LDFLAGS, CPPFLAGS, PREFIX can be overriden on CLI
|
# CFLAGS, LDFLAGS, CPPFLAGS, PREFIX can be overriden on CLI
|
||||||
CFLAGS := $(DEBUG) -I$(SRCDIR) -I$(SRCDIR)/dos -I$(SRCDIR)/gui -I$(SRCDIR)/thirdparty
|
CFLAGS := $(DEBUG) -I$(SRCDIR) -I$(SRCDIR)/dos -I$(SRCDIR)/gui -I$(SRCDIR)/thirdparty -I$(SRCDIR)/thirdparty/memwatch
|
||||||
CPPFLAGS :=
|
CPPFLAGS :=
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
PREFIX := /usr/local
|
PREFIX := /usr/local
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
mkdir -p bin obj/dos obj/gui
|
mkdir -p bin obj/dos obj/gui obj/thirdparty/memwatch
|
||||||
source /opt/cross/djgpp/setenv
|
source /opt/cross/djgpp/setenv
|
||||||
make -f Makefile.djgpp
|
make -f Makefile.djgpp
|
||||||
rm bin/client
|
rm bin/client
|
||||||
|
|
|
@ -44,7 +44,9 @@ INCLUDEPATH += \
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
$$LINUX_HEADERS \
|
$$LINUX_HEADERS \
|
||||||
|
src/gui/listbox.h \
|
||||||
src/gui/updown.h \
|
src/gui/updown.h \
|
||||||
|
src/stddclmr.h \
|
||||||
src/thirdparty/stb_ds.h \
|
src/thirdparty/stb_ds.h \
|
||||||
src/thirdparty/stb_image.h \
|
src/thirdparty/stb_image.h \
|
||||||
src/thirdparty/memwatch/memwatch.h \
|
src/thirdparty/memwatch/memwatch.h \
|
||||||
|
@ -74,6 +76,7 @@ HEADERS = \
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$$LINUX_SOURCES \
|
$$LINUX_SOURCES \
|
||||||
|
src/gui/listbox.c \
|
||||||
src/gui/updown.c \
|
src/gui/updown.c \
|
||||||
src/thirdparty/memwatch/memwatch.c \
|
src/thirdparty/memwatch/memwatch.c \
|
||||||
src/gui/memory.c \
|
src/gui/memory.c \
|
||||||
|
|
|
@ -482,45 +482,56 @@ DesktopT *guiStartup(void) {
|
||||||
_guiMetric[METRIC_UPDOWN_VERTICAL_PADDING] = 2;
|
_guiMetric[METRIC_UPDOWN_VERTICAL_PADDING] = 2;
|
||||||
_guiMetric[METRIC_UPDOWN_PADDING] = 6; // Matches other label / widget padding.
|
_guiMetric[METRIC_UPDOWN_PADDING] = 6; // Matches other label / widget padding.
|
||||||
_guiMetric[METRIC_UPDOWN_ARROW_PADDING] = 2;
|
_guiMetric[METRIC_UPDOWN_ARROW_PADDING] = 2;
|
||||||
|
_guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING] = 2;
|
||||||
|
_guiMetric[METRIC_LISTBOX_VERTICAL_PADDING] = 2;
|
||||||
|
|
||||||
_guiColor[COLOR_BUTTON_BACKGROUND] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_BUTTON_BACKGROUND] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_BUTTON_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_BUTTON_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_BUTTON_SHADOW] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_BUTTON_SHADOW] = vbeMakeColor( 80, 84, 80);
|
||||||
_guiColor[COLOR_BUTTON_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_BUTTON_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_DESKTOP] = vbeMakeColor( 51, 153, 255);
|
_guiColor[COLOR_DESKTOP] = vbeMakeColor( 51, 153, 255);
|
||||||
_guiColor[COLOR_WINDOW_BACKGROUND] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_WINDOW_BACKGROUND] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_WINDOW_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_WINDOW_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_WINDOW_SHADOW] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_WINDOW_SHADOW] = vbeMakeColor( 80, 84, 80);
|
||||||
_guiColor[COLOR_WINDOW_TITLE_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_WINDOW_TITLE_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
||||||
_guiColor[COLOR_WINDOW_TITLE_INACTIVE] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_WINDOW_TITLE_INACTIVE] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_LABEL_TEXT_INACTIVE] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_LABEL_TEXT_INACTIVE] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_LABEL_TEXT_INACTIVE] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_LABEL_TEXT_INACTIVE] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_CHECKBOX_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_CHECKBOX_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_CHECKBOX_SHADOW] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_CHECKBOX_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_CHECKBOX_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_CHECKBOX_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
||||||
_guiColor[COLOR_CHECKBOX_INACTIVE] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_CHECKBOX_INACTIVE] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_CHECKBOX_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_CHECKBOX_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_RADIOBUTTON_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_RADIOBUTTON_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_RADIOBUTTON_SHADOW] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_RADIOBUTTON_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_RADIOBUTTON_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_RADIOBUTTON_ACTIVE] = vbeMakeColor( 80, 84, 80);
|
||||||
_guiColor[COLOR_RADIOBUTTON_INACTIVE] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_RADIOBUTTON_INACTIVE] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_RADIOBUTTON_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_RADIOBUTTON_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_FRAME_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_FRAME_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_FRAME_SHADOW] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_FRAME_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_FRAME_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_FRAME_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_TEXTBOX_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_TEXTBOX_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_TEXTBOX_SHADOW] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_TEXTBOX_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_TEXTBOX_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_TEXTBOX_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_TEXTBOX_BACKGROUND] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_TEXTBOX_BACKGROUND] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_UPDOWN_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_UPDOWN_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_UPDOWN_SHADOW] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_UPDOWN_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_UPDOWN_TEXT] = vbeMakeColor( 0, 0, 0);
|
_guiColor[COLOR_UPDOWN_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
_guiColor[COLOR_UPDOWN_BACKGROUND] = vbeMakeColor(248, 252, 248);
|
_guiColor[COLOR_UPDOWN_BACKGROUND] = vbeMakeColor(248, 252, 248);
|
||||||
_guiColor[COLOR_UPDOWN_ARROWS_BACKGROUND] = vbeMakeColor(124, 126, 124);
|
_guiColor[COLOR_UPDOWN_ARROWS_BACKGROUND] = vbeMakeColor(124, 126, 124);
|
||||||
_guiColor[COLOR_UPDOWN_ARROWS_ACTIVE] = vbeMakeColor(168, 168, 168);
|
_guiColor[COLOR_UPDOWN_ARROWS_ACTIVE] = vbeMakeColor(168, 168, 168);
|
||||||
_guiColor[COLOR_UPDOWN_ARROWS_INACTIVE] = vbeMakeColor( 80, 84, 80);
|
_guiColor[COLOR_UPDOWN_ARROWS_INACTIVE] = vbeMakeColor( 80, 84, 80);
|
||||||
|
_guiColor[COLOR_LISTBOX_HIGHLIGHT] = vbeMakeColor(248, 252, 248);
|
||||||
|
_guiColor[COLOR_LISTBOX_SHADOW] = vbeMakeColor( 0, 0, 0);
|
||||||
|
_guiColor[COLOR_LISTBOX_TEXT] = vbeMakeColor( 0, 0, 0);
|
||||||
|
_guiColor[COLOR_LISTBOX_BACKGROUND] = vbeMakeColor(248, 252, 248);
|
||||||
|
_guiColor[COLOR_LISTBOX_SELECTED_TEXT] = vbeMakeColor(248, 252, 248);
|
||||||
|
_guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND] = vbeMakeColor( 0, 0, 0);
|
||||||
|
_guiColor[COLOR_LISTBOX_ARROWS_BACKGROUND] = vbeMakeColor(124, 126, 124);
|
||||||
|
_guiColor[COLOR_LISTBOX_ARROWS_ACTIVE] = vbeMakeColor(168, 168, 168);
|
||||||
|
_guiColor[COLOR_LISTBOX_ARROWS_INACTIVE] = vbeMakeColor( 80, 84, 80);
|
||||||
|
|
||||||
_guiFont = fontLoad("vga8x14.dat");
|
_guiFont = fontLoad("vga8x14.dat");
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ enum MagicE {
|
||||||
MAGIC_FRAME,
|
MAGIC_FRAME,
|
||||||
MAGIC_TEXTBOX,
|
MAGIC_TEXTBOX,
|
||||||
MAGIC_UPDOWN,
|
MAGIC_UPDOWN,
|
||||||
//MAGIC_LISTBOX,
|
MAGIC_LISTBOX,
|
||||||
//MAGIC_TERMINAL,
|
//MAGIC_TERMINAL,
|
||||||
//MAGIC_DROPDOWN,
|
//MAGIC_DROPDOWN,
|
||||||
MAGIC_COUNT
|
MAGIC_COUNT
|
||||||
|
@ -73,6 +73,8 @@ enum MetricE {
|
||||||
METRIC_UPDOWN_ARROW_PADDING,
|
METRIC_UPDOWN_ARROW_PADDING,
|
||||||
METRIC_UPDOWN_HORIZONTAL_PADDING,
|
METRIC_UPDOWN_HORIZONTAL_PADDING,
|
||||||
METRIC_UPDOWN_VERTICAL_PADDING,
|
METRIC_UPDOWN_VERTICAL_PADDING,
|
||||||
|
METRIC_LISTBOX_HORIZONTAL_PADDING,
|
||||||
|
METRIC_LISTBOX_VERTICAL_PADDING,
|
||||||
METRIC_COUNT
|
METRIC_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -116,6 +118,15 @@ enum ColorE {
|
||||||
COLOR_UPDOWN_ARROWS_BACKGROUND,
|
COLOR_UPDOWN_ARROWS_BACKGROUND,
|
||||||
COLOR_UPDOWN_ARROWS_ACTIVE,
|
COLOR_UPDOWN_ARROWS_ACTIVE,
|
||||||
COLOR_UPDOWN_ARROWS_INACTIVE,
|
COLOR_UPDOWN_ARROWS_INACTIVE,
|
||||||
|
COLOR_LISTBOX_HIGHLIGHT,
|
||||||
|
COLOR_LISTBOX_SHADOW,
|
||||||
|
COLOR_LISTBOX_TEXT,
|
||||||
|
COLOR_LISTBOX_BACKGROUND,
|
||||||
|
COLOR_LISTBOX_SELECTED_TEXT,
|
||||||
|
COLOR_LISTBOX_SELECTED_BACKGROUND,
|
||||||
|
COLOR_LISTBOX_ARROWS_BACKGROUND,
|
||||||
|
COLOR_LISTBOX_ARROWS_ACTIVE,
|
||||||
|
COLOR_LISTBOX_ARROWS_INACTIVE,
|
||||||
COLOR_COUNT
|
COLOR_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
402
client/src/gui/listbox.c
Normal file
402
client/src/gui/listbox.c
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch MultiPlayer Game Server Mark II
|
||||||
|
* Copyright (C) 2020-2021 Scott Duensing
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "listbox.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t _halfFont = 0;
|
||||||
|
static uint8_t _visibleX = 0; // How many characters are visible in control
|
||||||
|
static uint8_t _visibleY = 0; // How many characters are visible in control
|
||||||
|
static uint16_t _valueWidth = 0;
|
||||||
|
static uint16_t _valueHeight = 0;
|
||||||
|
static uint16_t _valueTop = 0;
|
||||||
|
static uint16_t _valueBottom = 0;
|
||||||
|
static uint16_t _arrowWidth = 0;
|
||||||
|
static uint16_t _arrowStart = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxDel(WidgetT **widget);
|
||||||
|
static void listboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
|
static void listboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
|
static void listboxPaint(WidgetT *widget, RectT pos);
|
||||||
|
static void listboxScrollUp(ListboxT *listbox);
|
||||||
|
static void listboxScrollDown(ListboxT *listbox);
|
||||||
|
static void listboxSizesRecalculate(ListboxT *listbox);
|
||||||
|
|
||||||
|
|
||||||
|
void listboxAddItem(ListboxT *listbox, char *item) {
|
||||||
|
arrput(listbox->values, strdup(item));
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxDel(WidgetT **widget) {
|
||||||
|
ListboxT *l = (ListboxT *)*widget;
|
||||||
|
size_t len = arrlenu(l->values);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
free(l->values[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->title) free(l->title);
|
||||||
|
free(l);
|
||||||
|
l = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t listboxGetIndex(ListboxT *listbox) {
|
||||||
|
return listbox->selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *listboxGetValue(ListboxT *listbox) {
|
||||||
|
return listbox->values[listbox->selected];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *listboxInit(WidgetT *widget, char *title) {
|
||||||
|
ListboxT *l = (ListboxT *)widget;
|
||||||
|
|
||||||
|
l->base.delMethod = listboxDel;
|
||||||
|
l->base.keyboardEventMethod = listboxKeyboardEvent;
|
||||||
|
l->base.paintMethod = listboxPaint;
|
||||||
|
l->base.mouseEventMethod = listboxMouseEvent;
|
||||||
|
l->title = NULL;
|
||||||
|
l->values = NULL;
|
||||||
|
l->selected = 0;
|
||||||
|
l->step = 1;
|
||||||
|
l->offset = 0;
|
||||||
|
|
||||||
|
// Visibles are set in listboxSetTitle
|
||||||
|
listboxSetTitle(l, title);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
||||||
|
|
||||||
|
ListboxT *l = (ListboxT *)widget;
|
||||||
|
int16_t len = arrlenu(l->values);
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
(void)scancode;
|
||||||
|
(void)shift;
|
||||||
|
(void)control;
|
||||||
|
(void)alt;
|
||||||
|
|
||||||
|
listboxSizesRecalculate(l);
|
||||||
|
|
||||||
|
if (extended) {
|
||||||
|
|
||||||
|
switch (ascii) {
|
||||||
|
case 71: // HOME
|
||||||
|
l->selected = 0;
|
||||||
|
l->offset = 0;
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 79: // END
|
||||||
|
// Are there more items than visible?
|
||||||
|
if (len > _visibleY - 1) {
|
||||||
|
// Yep. Scroll & set selected.
|
||||||
|
l->selected = _visibleY - 2;
|
||||||
|
l->offset = len - _visibleY + 1;
|
||||||
|
} else {
|
||||||
|
// No. Just set selected.
|
||||||
|
l->selected = len - 1;
|
||||||
|
l->offset = 0;
|
||||||
|
}
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 73: // PAGEUP
|
||||||
|
for (i=0; i<l->step; i++) listboxScrollUp(l);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 81: // PAGEDOWN
|
||||||
|
for (i=0; i<l->step; i++) listboxScrollDown(l);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 72: // UP
|
||||||
|
listboxScrollUp(l);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 80: // DOWN
|
||||||
|
listboxScrollDown(l);
|
||||||
|
break;
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
} // extended
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
|
||||||
|
ListboxT *l = (ListboxT *)widget;
|
||||||
|
uint16_t o;
|
||||||
|
uint16_t valueStart;
|
||||||
|
int16_t len;
|
||||||
|
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
(void)mouse;
|
||||||
|
|
||||||
|
if (event == MOUSE_EVENT_LEFT_UP) {
|
||||||
|
listboxSizesRecalculate(l);
|
||||||
|
|
||||||
|
len = arrlenu(l->values);
|
||||||
|
|
||||||
|
// Clicked item in listbox.
|
||||||
|
valueStart = 1 + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING];
|
||||||
|
if (x > valueStart && x < valueStart + _valueWidth - 1 && y > _valueTop + 1 && y < _valueBottom - 1) {
|
||||||
|
o = (y - _valueTop) / fontHeightGet(_guiFont);
|
||||||
|
if (o < len) l->selected = o;
|
||||||
|
if (l->selected > _visibleY - 2) l->selected = _visibleY - 2; // Two because 1 is to correct _visibleY and the other 1 is because selected is zero based.
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
_arrowStart += 1 + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING]; // Left of up arrow
|
||||||
|
o = _valueTop + 1 + _guiMetric[METRIC_LISTBOX_VERTICAL_PADDING]; // Top of arrows
|
||||||
|
|
||||||
|
// Did they click the up arrow?
|
||||||
|
if (x >= _arrowStart && x <= _arrowStart + fontHeightGet(_guiFont) && y >= o && y <= o + fontHeightGet(_guiFont)) {
|
||||||
|
listboxScrollUp(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did they click the down arrow?
|
||||||
|
o = _valueBottom - 1 - _guiMetric[METRIC_LISTBOX_VERTICAL_PADDING]; // Bottom of down arrow
|
||||||
|
if (x >= _arrowStart && x <= _arrowStart + fontHeightGet(_guiFont) && y >= o - fontHeightGet(_guiFont) && y <= o) {
|
||||||
|
listboxScrollDown(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // MOUSE_UP
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ListboxT *listboxNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) {
|
||||||
|
ListboxT *listbox = (ListboxT *)malloc(sizeof(ListboxT));
|
||||||
|
WidgetT *widget = NULL;
|
||||||
|
|
||||||
|
if (!listbox) return NULL;
|
||||||
|
|
||||||
|
widget = widgetInit(W(listbox), MAGIC_LISTBOX, x, y, w, h, 0, 0, 0, 0);
|
||||||
|
if (!widget) {
|
||||||
|
free(listbox);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
listbox = (ListboxT *)listboxInit((WidgetT *)listbox, title);
|
||||||
|
|
||||||
|
return listbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxPaint(WidgetT *widget, RectT pos) {
|
||||||
|
ListboxT *l = (ListboxT *)widget;
|
||||||
|
uint16_t items;
|
||||||
|
uint16_t o;
|
||||||
|
uint16_t i;
|
||||||
|
int16_t len;
|
||||||
|
ColorT color;
|
||||||
|
|
||||||
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
||||||
|
listboxSizesRecalculate(l);
|
||||||
|
|
||||||
|
// Move a few things into screen space, not widget space.
|
||||||
|
_arrowStart += pos.x;
|
||||||
|
_valueTop += pos.y;
|
||||||
|
_valueBottom += pos.y;
|
||||||
|
|
||||||
|
len = arrlenu(l->values);
|
||||||
|
|
||||||
|
// How many items can we draw?
|
||||||
|
items = len - l->offset;
|
||||||
|
if (items > _visibleY - 1) items = _visibleY - 1;
|
||||||
|
|
||||||
|
// Draw title.
|
||||||
|
fontRender(_guiFont, l->title, _guiColor[COLOR_LISTBOX_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], pos.x, pos.y);
|
||||||
|
|
||||||
|
// Draw outline of listbox.
|
||||||
|
guiDrawHighlightFrame(pos.x, _valueTop, pos.x + _valueWidth, _valueBottom, _guiColor[COLOR_LISTBOX_SHADOW], _guiColor[COLOR_LISTBOX_HIGHLIGHT]);
|
||||||
|
|
||||||
|
// Draw background of listbox.
|
||||||
|
guiDrawRectangleFilled(pos.x + 1, _valueTop + 1, pos.x + _valueWidth - 1, _valueBottom - 1, _guiColor[COLOR_LISTBOX_BACKGROUND]);
|
||||||
|
|
||||||
|
// Draw listbox contents.
|
||||||
|
o = _valueTop + 1 + _guiMetric[METRIC_LISTBOX_VERTICAL_PADDING];
|
||||||
|
for (i=0; i<items; i++) {
|
||||||
|
if (i == l->selected) {
|
||||||
|
guiDrawRectangleFilled(pos.x + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o, pos.x + _valueWidth - _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o + fontHeightGet(_guiFont) - 1, _guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND]);
|
||||||
|
fontRender(_guiFont, l->values[l->offset + i], _guiColor[COLOR_LISTBOX_SELECTED_TEXT], _guiColor[COLOR_LISTBOX_SELECTED_BACKGROUND], pos.x + 1 + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o);
|
||||||
|
} else {
|
||||||
|
fontRender(_guiFont, l->values[l->offset + i], _guiColor[COLOR_LISTBOX_TEXT], _guiColor[COLOR_LISTBOX_BACKGROUND], pos.x + 1 + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING], o);
|
||||||
|
}
|
||||||
|
o += fontHeightGet(_guiFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw outline of arrows.
|
||||||
|
guiDrawHighlightFrame(_arrowStart, _valueTop, _arrowStart + _arrowWidth, _valueBottom, _guiColor[COLOR_LISTBOX_SHADOW], _guiColor[COLOR_LISTBOX_HIGHLIGHT]);
|
||||||
|
|
||||||
|
// Draw background of arrows.
|
||||||
|
guiDrawRectangleFilled(_arrowStart + 1, _valueTop + 1, _arrowStart + _arrowWidth - 1, _valueBottom - 1, _guiColor[COLOR_LISTBOX_ARROWS_BACKGROUND]);
|
||||||
|
|
||||||
|
// Draw up arrow
|
||||||
|
_arrowStart += _halfFont + 1 + _guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING]; // Center of up arrow
|
||||||
|
o = _valueTop + 1 + _guiMetric[METRIC_LISTBOX_VERTICAL_PADDING]; // Top of up arrow
|
||||||
|
color = l->offset + l->selected > 0 ? _guiColor[COLOR_LISTBOX_ARROWS_ACTIVE] : _guiColor[COLOR_LISTBOX_ARROWS_INACTIVE];
|
||||||
|
for (i=0; i<=fontHeightGet(_guiFont); i++) {
|
||||||
|
guiDrawLine(_arrowStart - i * 0.5, o + i, _arrowStart + i * 0.5, o + i, color);
|
||||||
|
}
|
||||||
|
guiDrawLine(_arrowStart, o, _arrowStart + _halfFont, o + fontHeightGet(_guiFont), _guiColor[COLOR_LISTBOX_SHADOW]);
|
||||||
|
guiDrawLine(_arrowStart - _halfFont, o + fontHeightGet(_guiFont), _arrowStart + _halfFont, o + fontHeightGet(_guiFont), _guiColor[COLOR_LISTBOX_SHADOW]);
|
||||||
|
guiDrawLine(_arrowStart, o, _arrowStart - _halfFont, o + fontHeightGet(_guiFont), _guiColor[COLOR_LISTBOX_HIGHLIGHT]);
|
||||||
|
|
||||||
|
// Draw down arrow
|
||||||
|
o = _valueBottom - 1 - _guiMetric[METRIC_LISTBOX_VERTICAL_PADDING]; // Bottom of down arrow
|
||||||
|
color = l->offset + l->selected < len - 1 ? _guiColor[COLOR_UPDOWN_ARROWS_ACTIVE] : _guiColor[COLOR_UPDOWN_ARROWS_INACTIVE];
|
||||||
|
for (i=0; i<=fontHeightGet(_guiFont); i++) {
|
||||||
|
guiDrawLine(_arrowStart - i * 0.5, o - i, _arrowStart + i * 0.5, o - i, color);
|
||||||
|
}
|
||||||
|
guiDrawLine(_arrowStart, o, _arrowStart + _halfFont, o - fontHeightGet(_guiFont), _guiColor[COLOR_UPDOWN_SHADOW]);
|
||||||
|
guiDrawLine(_arrowStart - _halfFont, o - fontHeightGet(_guiFont), _arrowStart + _halfFont, o - fontHeightGet(_guiFont), _guiColor[COLOR_UPDOWN_HIGHLIGHT]);
|
||||||
|
guiDrawLine(_arrowStart, o, _arrowStart - _halfFont, o - fontHeightGet(_guiFont), _guiColor[COLOR_UPDOWN_HIGHLIGHT]);
|
||||||
|
|
||||||
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void listboxRemoveItem(ListboxT *listbox, char *item) {
|
||||||
|
size_t len = arrlenu(listbox->values);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
if (strcmp(item, listbox->values[x]) == 0) {
|
||||||
|
arrdel(listbox->values, x);
|
||||||
|
if (listbox->selected > len || listbox->selected > 0) listbox->selected--;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxScrollUp(ListboxT *listbox) {
|
||||||
|
// Can we decrement?
|
||||||
|
if (listbox->selected > 0) {
|
||||||
|
listbox->selected--;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
} else {
|
||||||
|
// Can we scroll the list up?
|
||||||
|
if (listbox->offset > 0) {
|
||||||
|
listbox->offset--;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxScrollDown(ListboxT *listbox) {
|
||||||
|
int16_t len = arrlenu(listbox->values);
|
||||||
|
|
||||||
|
// Can we increment?
|
||||||
|
if (listbox->selected < _visibleY - 2) {
|
||||||
|
// Is it off the end of the list?
|
||||||
|
if (listbox->offset + listbox->selected < len - 1) {
|
||||||
|
listbox->selected++;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Can we scroll the list down?
|
||||||
|
if (listbox->offset + listbox->selected < len - 1) {
|
||||||
|
listbox->offset++;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void listboxSetIndex(ListboxT *listbox, uint16_t index) {
|
||||||
|
if (index < arrlenu(listbox->values)) {
|
||||||
|
listbox->selected = index;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void listboxSetStep(ListboxT *listbox, int32_t step) {
|
||||||
|
listbox->step = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void listboxSetTitle(ListboxT *listbox, char *title) {
|
||||||
|
if (listbox->title) free(listbox->title);
|
||||||
|
listbox->title = strdup(title);
|
||||||
|
listboxSizesRecalculate(listbox);
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void listboxSetValue(ListboxT *listbox, char *value) {
|
||||||
|
size_t len = arrlenu(listbox->values);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
if (strcmp(value, listbox->values[x]) == 0) {
|
||||||
|
listbox->selected = x;
|
||||||
|
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void listboxSizesRecalculate(ListboxT *listbox) {
|
||||||
|
|
||||||
|
// Arrow box width is border + (hpadding*2) + fontHeight
|
||||||
|
// Label is drawn at x,y
|
||||||
|
// One line horizontal gap between label and border
|
||||||
|
// One line vertical gap between value and arrow box
|
||||||
|
// Value border is drawn at x+1, y+2 to x+w-2-arrowWidth, y+h-2
|
||||||
|
// Value is x+1+hpadding, y+2+vpadding to x+w-1-(hpadding*2)-arrowWidth, y+h-2-(vpadding*2)
|
||||||
|
// arrowStart is x+1+valueWidth
|
||||||
|
|
||||||
|
// Set global stuff that isn't actually part of the widget state.
|
||||||
|
_halfFont = fontHeightGet(_guiFont) * 0.5;
|
||||||
|
_arrowWidth = 2 + (_guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING] * 2) + fontHeightGet(_guiFont); // Arrow width = font height
|
||||||
|
_valueWidth = listbox->base.pos.w - 1 - 1 - (_guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING] * 2) - _arrowWidth;
|
||||||
|
_valueHeight = listbox->base.pos.h - 2 - (_guiMetric[METRIC_LISTBOX_VERTICAL_PADDING] * 2);
|
||||||
|
_valueTop = fontHeightGet(_guiFont) + 1;
|
||||||
|
_valueBottom = _valueHeight;
|
||||||
|
_arrowStart = 2 + _valueWidth;
|
||||||
|
|
||||||
|
// Figure out how many characters we have room to display.
|
||||||
|
_visibleX = (_valueWidth - 2 + (_guiMetric[METRIC_LISTBOX_HORIZONTAL_PADDING] * 2)) / fontWidthGet(_guiFont);
|
||||||
|
_visibleY = (_valueHeight - 2 + (_guiMetric[METRIC_LISTBOX_VERTICAL_PADDING] * 2)) / fontHeightGet(_guiFont);
|
||||||
|
|
||||||
|
}
|
51
client/src/gui/listbox.h
Normal file
51
client/src/gui/listbox.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch MultiPlayer Game Server Mark II
|
||||||
|
* Copyright (C) 2020-2021 Scott Duensing
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LISTBOX_H
|
||||||
|
#define LISTBOX_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ListboxS {
|
||||||
|
WidgetT base; // Must be first in every widget
|
||||||
|
char *title;
|
||||||
|
char **values;
|
||||||
|
uint16_t selected; // values[offset + selected]
|
||||||
|
int32_t step;
|
||||||
|
int32_t offset;
|
||||||
|
} ListboxT;
|
||||||
|
|
||||||
|
|
||||||
|
void listboxAddItem(ListboxT *listbox, char *item);
|
||||||
|
uint16_t listboxGetIndex(ListboxT *listbox);
|
||||||
|
char *listboxGetValue(ListboxT *listbox);
|
||||||
|
WidgetT *listboxInit(WidgetT *widget, char *title);
|
||||||
|
ListboxT *listboxNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
|
void listboxRemoveItem(ListboxT *listbox, char *item);
|
||||||
|
void listboxSetIndex(ListboxT *listbox, uint16_t index);
|
||||||
|
void listboxSetStep(ListboxT *listbox, int32_t step);
|
||||||
|
void listboxSetTitle(ListboxT *listbox, char *title);
|
||||||
|
void listboxSetValue(ListboxT *listbox, char *value);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LISTBOX_H
|
|
@ -80,6 +80,7 @@ static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extende
|
||||||
|
|
||||||
TextboxT *t = (TextboxT *)widget;
|
TextboxT *t = (TextboxT *)widget;
|
||||||
uint16_t x;
|
uint16_t x;
|
||||||
|
char *temp;
|
||||||
|
|
||||||
(void)scancode;
|
(void)scancode;
|
||||||
(void)shift;
|
(void)shift;
|
||||||
|
@ -89,6 +90,18 @@ static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extende
|
||||||
if (extended) {
|
if (extended) {
|
||||||
|
|
||||||
switch (ascii) {
|
switch (ascii) {
|
||||||
|
case 71: // HOME
|
||||||
|
t->caret = 0;
|
||||||
|
t->offset = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 79: // END
|
||||||
|
// We cheat and just reset the value. That moves the offset and cursor.
|
||||||
|
temp = strdup(t->value);
|
||||||
|
textboxSetValue(t, temp);
|
||||||
|
free(temp);
|
||||||
|
break;
|
||||||
|
|
||||||
case 75: // LEFT
|
case 75: // LEFT
|
||||||
// Can we move left in the value?
|
// Can we move left in the value?
|
||||||
if (t->caret + t->offset > 0) {
|
if (t->caret + t->offset > 0) {
|
||||||
|
|
|
@ -92,6 +92,7 @@ static void updownKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended
|
||||||
|
|
||||||
UpdownT *u = (UpdownT *)widget;
|
UpdownT *u = (UpdownT *)widget;
|
||||||
int32_t temp;
|
int32_t temp;
|
||||||
|
static uint8_t willBeNegative = 0;
|
||||||
|
|
||||||
(void)scancode;
|
(void)scancode;
|
||||||
(void)shift;
|
(void)shift;
|
||||||
|
@ -101,16 +102,41 @@ static void updownKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended
|
||||||
if (extended) {
|
if (extended) {
|
||||||
|
|
||||||
switch (ascii) {
|
switch (ascii) {
|
||||||
|
case 71: // HOME
|
||||||
|
u->value = u->minimum;
|
||||||
|
willBeNegative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 79: // END
|
||||||
|
u->value = u->maximum;
|
||||||
|
willBeNegative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 73: // PAGEUP
|
||||||
|
u->value += u->step;
|
||||||
|
if (u->value > u->maximum) u->value = u->maximum;
|
||||||
|
willBeNegative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 81: // PAGEDOWN
|
||||||
|
u->value -= u->step;
|
||||||
|
if (u->value < u->minimum) u->value = u->minimum;
|
||||||
|
willBeNegative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 72: // UP
|
case 72: // UP
|
||||||
if (u->value < u->maximum) u->value++;
|
if (u->value < u->maximum) u->value++;
|
||||||
|
willBeNegative = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 80: // DOWN
|
case 80: // DOWN
|
||||||
if (u->value > u->minimum) u->value--;
|
if (u->value > u->minimum) u->value--;
|
||||||
|
willBeNegative = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 83: // DELETE
|
case 83: // DELETE
|
||||||
u->value = (int)(u->value * 0.1);
|
u->value = (int)(u->value * 0.1);
|
||||||
|
willBeNegative = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} // switch
|
} // switch
|
||||||
|
@ -120,13 +146,20 @@ static void updownKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended
|
||||||
switch (ascii) {
|
switch (ascii) {
|
||||||
case 8: // BACKSPACE
|
case 8: // BACKSPACE
|
||||||
u->value = (int)(u->value * 0.1);
|
u->value = (int)(u->value * 0.1);
|
||||||
|
willBeNegative = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-': // Leading Minus
|
||||||
|
if (u->value == 0) willBeNegative = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // Number keys
|
default: // Number keys
|
||||||
if (ascii >= '0' && ascii <= '9') {
|
if (ascii >= '0' && ascii <= '9') {
|
||||||
temp = u->value * 10 + (ascii - '0');
|
temp = u->value * 10 + (ascii - '0');
|
||||||
if (temp <= u->maximum) u->value = temp;
|
if (willBeNegative) u->value = -u->value;
|
||||||
|
if (temp <= u->maximum && temp >= u->minimum) u->value = temp;
|
||||||
}
|
}
|
||||||
|
willBeNegative = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} // switch
|
} // switch
|
||||||
|
@ -159,6 +192,7 @@ static void updownMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_
|
||||||
} else {
|
} else {
|
||||||
u->value += u->step;
|
u->value += u->step;
|
||||||
}
|
}
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +207,10 @@ static void updownMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_
|
||||||
} else {
|
} else {
|
||||||
u->value -= u->step;
|
u->value -= u->step;
|
||||||
}
|
}
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we redraw.
|
|
||||||
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +293,7 @@ static void updownPaint(WidgetT *widget, RectT pos) {
|
||||||
textY = pos.y + 2 + _guiMetric[METRIC_UPDOWN_VERTICAL_PADDING];
|
textY = pos.y + 2 + _guiMetric[METRIC_UPDOWN_VERTICAL_PADDING];
|
||||||
|
|
||||||
// Draw value.
|
// Draw value.
|
||||||
snprintf(draw, UPDOWN_MAX_DIGITS, "%d", u->value);
|
snprintf(draw, UPDOWN_MAX_DIGITS, "%ld", (long)u->value); // Weird typecasting prevents warnings in both DOS and Linux (32 and 64 bit)
|
||||||
textX += (u->visible - strlen(draw)) * fontWidthGet(_guiFont);
|
textX += (u->visible - strlen(draw)) * fontWidthGet(_guiFont);
|
||||||
fontRender(_guiFont, draw, _guiColor[COLOR_UPDOWN_TEXT], _guiColor[COLOR_UPDOWN_BACKGROUND], textX, textY);
|
fontRender(_guiFont, draw, _guiColor[COLOR_UPDOWN_TEXT], _guiColor[COLOR_UPDOWN_BACKGROUND], textX, textY);
|
||||||
|
|
||||||
|
@ -318,8 +351,8 @@ static void updownSetVisible(UpdownT *updown) {
|
||||||
int8_t minWidth;
|
int8_t minWidth;
|
||||||
|
|
||||||
// Calculate how many characters we need to be able to display.
|
// Calculate how many characters we need to be able to display.
|
||||||
maxWidth = snprintf(digits, UPDOWN_MAX_DIGITS, "%d", updown->maximum);
|
maxWidth = snprintf(digits, UPDOWN_MAX_DIGITS, "%ld", (long)updown->maximum); // Weird typecasting prevents warnings in both DOS and Linux (32 and 64 bit)
|
||||||
minWidth = snprintf(digits, UPDOWN_MAX_DIGITS, "%d", updown->minimum);
|
minWidth = snprintf(digits, UPDOWN_MAX_DIGITS, "%ld", (long)updown->minimum); // Weird typecasting prevents warnings in both DOS and Linux (32 and 64 bit)
|
||||||
|
|
||||||
updown->visible = maxWidth > minWidth ? maxWidth : minWidth;
|
updown->visible = maxWidth > minWidth ? maxWidth : minWidth;
|
||||||
|
|
||||||
|
|
|
@ -105,11 +105,15 @@ uint8_t keyHit(void) {
|
||||||
// Fix mappings to match DOS bioskey() call.
|
// Fix mappings to match DOS bioskey() call.
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_ESCAPE) _ASCIIKeep = 27;
|
if (_scanCodeKeep == SDL_SCANCODE_ESCAPE) _ASCIIKeep = 27;
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_BACKSPACE) _ASCIIKeep = 8;
|
if (_scanCodeKeep == SDL_SCANCODE_BACKSPACE) _ASCIIKeep = 8;
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_DELETE) { _extended = 1; _ASCIIKeep = 83; }
|
if (_scanCodeKeep == SDL_SCANCODE_HOME) { _extended = 1; _ASCIIKeep = 71; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_UP) { _extended = 1; _ASCIIKeep = 72; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_PAGEUP) { _extended = 1; _ASCIIKeep = 73; }
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_LEFT) { _extended = 1; _ASCIIKeep = 75; }
|
if (_scanCodeKeep == SDL_SCANCODE_LEFT) { _extended = 1; _ASCIIKeep = 75; }
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_RIGHT) { _extended = 1; _ASCIIKeep = 77; }
|
if (_scanCodeKeep == SDL_SCANCODE_RIGHT) { _extended = 1; _ASCIIKeep = 77; }
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_UP) { _extended = 1; _ASCIIKeep = 72; }
|
if (_scanCodeKeep == SDL_SCANCODE_END) { _extended = 1; _ASCIIKeep = 79; }
|
||||||
if (_scanCodeKeep == SDL_SCANCODE_DOWN) { _extended = 1; _ASCIIKeep = 80; }
|
if (_scanCodeKeep == SDL_SCANCODE_DOWN) { _extended = 1; _ASCIIKeep = 80; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_PAGEDOWN) { _extended = 1; _ASCIIKeep = 81; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_DELETE) { _extended = 1; _ASCIIKeep = 83; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -24,14 +24,21 @@
|
||||||
* - Fix function naming to be classItemVerb (checkboxValueGet instead of checkboxGetValue)
|
* - Fix function naming to be classItemVerb (checkboxValueGet instead of checkboxGetValue)
|
||||||
* - Replace any direct data manipulation from outside a class with methods to handle it
|
* - Replace any direct data manipulation from outside a class with methods to handle it
|
||||||
* - More widget states: Ghosted, hidden
|
* - More widget states: Ghosted, hidden
|
||||||
* - Move setup math for paint events inside the dirty check
|
|
||||||
* - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well
|
* - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well
|
||||||
* - Metrics, colors, etc. should be defined in each widget and not in GUI
|
* - Metrics, colors, etc. should be defined in each widget and not in GUI
|
||||||
* - UpDown is kinda lame
|
* - Widgets should support a "changed" callback that can cancel the change
|
||||||
|
* - Add pgup/pgdn to UpDown
|
||||||
|
* - Add home/end to Textbox
|
||||||
|
* - Move drawing and surface code into it's own file
|
||||||
|
* - Use LabelT in all widgets that have a label
|
||||||
|
* - Find a light grey to replace white widget data areas
|
||||||
|
* - No thumb in listbox scrollbar
|
||||||
*
|
*
|
||||||
|
* - Random crash after adding listbox
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "stddclmr.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "vesa.h"
|
#include "vesa.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
|
@ -53,6 +60,7 @@
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "textbox.h"
|
#include "textbox.h"
|
||||||
#include "updown.h"
|
#include "updown.h"
|
||||||
|
#include "listbox.h"
|
||||||
|
|
||||||
|
|
||||||
void buttonClick(WidgetT *widget) {
|
void buttonClick(WidgetT *widget) {
|
||||||
|
@ -144,6 +152,7 @@ void test(void *data) {
|
||||||
TextboxT *t1 = NULL;
|
TextboxT *t1 = NULL;
|
||||||
TextboxT *t2 = NULL;
|
TextboxT *t2 = NULL;
|
||||||
UpdownT *u1 = NULL;
|
UpdownT *u1 = NULL;
|
||||||
|
ListboxT *lb1 = NULL;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
|
@ -158,6 +167,19 @@ void test(void *data) {
|
||||||
// Window 1
|
// Window 1
|
||||||
p1 = pictureNew(0, 0, "kanga.png");
|
p1 = pictureNew(0, 0, "kanga.png");
|
||||||
guiAttach(W(w1), W(p1));
|
guiAttach(W(w1), W(p1));
|
||||||
|
lb1 = listboxNew(155, 10, 120, 140, "List Box");
|
||||||
|
listboxAddItem(lb1, "One");
|
||||||
|
listboxAddItem(lb1, "Two");
|
||||||
|
listboxAddItem(lb1, "Three");
|
||||||
|
listboxAddItem(lb1, "Four");
|
||||||
|
listboxAddItem(lb1, "Five");
|
||||||
|
listboxAddItem(lb1, "Six");
|
||||||
|
listboxAddItem(lb1, "Seven");
|
||||||
|
listboxAddItem(lb1, "Eight");
|
||||||
|
listboxAddItem(lb1, "Nine");
|
||||||
|
listboxAddItem(lb1, "Ten");
|
||||||
|
listboxSetStep(lb1, 3);
|
||||||
|
guiAttach(W(w1), W(lb1));
|
||||||
|
|
||||||
// Window 2
|
// Window 2
|
||||||
r1a = radioNew(10, 10, "Radio 1a", 1);
|
r1a = radioNew(10, 10, "Radio 1a", 1);
|
||||||
|
|
95
client/src/stddclmr.h
Normal file
95
client/src/stddclmr.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#ifndef STDDCLMR_H
|
||||||
|
#define STDDCLMR_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
Action figures sold separately. Add toner. All models over 18 years of age.
|
||||||
|
All rights reserved. Allow four to six weeks for delivery. An equal
|
||||||
|
opportunity employer. Any resemblance to actual persons, living or dead, is
|
||||||
|
unintentional and purely coincidental. Apply only to affected area. Approved
|
||||||
|
for veterans. As seen on TV. At participating locations only. Avoid contact
|
||||||
|
with mucous membranes. Avoid contact with skin. Avoid extreme temperatures
|
||||||
|
and store in a cool dry place. Batteries not included. Be sure each item is
|
||||||
|
properly endorsed. Beware of dog. Booths for two or more. Breaking seal
|
||||||
|
constitutes acceptance of agreement. Call toll free number before digging.
|
||||||
|
Caveat emptor. Check here if tax deductible. Close cover before striking
|
||||||
|
Colors may fade. Contains a substantial amount of non-tobacco ingredients.
|
||||||
|
Contents may settle during shipment. Contestants have been briefed on some
|
||||||
|
questions before the show. Copyright 1995 Joker's Wild. Disclaimer does
|
||||||
|
not cover hurricane, lightning, tornado, tsunami, volcanic eruption,
|
||||||
|
earthquake, flood, and other Acts of God, misuse, neglect, unauthorized
|
||||||
|
repair, damage from improper installation, broken antenna or marred cabinet,
|
||||||
|
incorrect line voltage, missing or altered serial numbers, sonic boom
|
||||||
|
vibrations, electromagnetic radiation from nuclear blasts, customer
|
||||||
|
adjustments that are not covered in the joke list, and incidents owing to
|
||||||
|
airplane crash, ship sinking, motor vehicle accidents, leaky roof, broken
|
||||||
|
glass, falling rocks, mud slides, forest fire, flying projectiles, or
|
||||||
|
dropping the item. Do not bend, fold, mutilate, or spindle. Do not place
|
||||||
|
near flammable or magnetic source. Do not puncture, incinerate, or store
|
||||||
|
above 120 degrees Fahrenheit. Do not stamp. Use other side for additional
|
||||||
|
listings. Do not use while operating a motor vehicle or heavy equipment. Do
|
||||||
|
not write below this line. Documents are provided "as is" without any
|
||||||
|
warranties expressed or implied. Don't quote me on anything. Don't quote me
|
||||||
|
on that. Driver does not carry cash. Drop in any mailbox. Edited for
|
||||||
|
television. Employees and their families are not eligible. Falling rock.
|
||||||
|
First pull up, then pull down. Flames redirected to /dev/null. For a
|
||||||
|
limited time only. For external use only. For off-road use only. For office
|
||||||
|
use only. For recreational use only. Do not disturb. Freshest if eaten
|
||||||
|
before date on carton. Hand wash only, tumble dry on low heat. If a rash,
|
||||||
|
redness, irritation, or swelling develops, discontinue use. If condition
|
||||||
|
persists, consult your physician. If defects are discovered, do not attempt
|
||||||
|
to fix them yourself, but return to an authorized service center. If
|
||||||
|
ingested, do not induce vomiting, if symptoms persist, consult a doctor.
|
||||||
|
Keep away from open flames and avoid inhaling fumes. Keep away from
|
||||||
|
sunlight, pets, and small children. Keep cool; process promptly. Limit
|
||||||
|
one-per-family please. Limited time offer, call now to ensure prompt
|
||||||
|
delivery. List at least two alternate dates. List each check separately by
|
||||||
|
bank number. List was current at time of printing. Lost ticket pays maximum
|
||||||
|
rate. May be too intense for some viewers. Must be 18 to enter. No Canadian
|
||||||
|
coins. No alcohol, dogs or horses. No anchovies unless otherwise specified.
|
||||||
|
No animals were harmed in the production of these documents. No money down.
|
||||||
|
No other warranty expressed or implied. No passes accepted for this
|
||||||
|
engagement. No postage necessary if mailed in the United States. No
|
||||||
|
preservatives added. No purchase necessary. No salt, MSG, artificial color
|
||||||
|
or flavor added. No shoes, no shirt, no service, no kidding. No solicitors.
|
||||||
|
No substitutions allowed. No transfers issued until the bus comes to a
|
||||||
|
complete stop. No user-serviceable parts inside. Not affiliated with the
|
||||||
|
American Red Cross. Not liable for damages due to use or misuse. Not
|
||||||
|
recommended for children. Not responsible for direct, indirect, incidental
|
||||||
|
or consequential damages resulting from any defect, error or failure to
|
||||||
|
perform. Not the Beatles. Objects in mirror may be closer than they appear.
|
||||||
|
One size fits all. Many suitcases look alike. Other copyright laws for
|
||||||
|
specific entries apply wherever noted. Other restrictions may apply. Package
|
||||||
|
sold by weight, not volume. Parental advisory - explicit lyrics. Penalty for
|
||||||
|
private use. Place stamp here. Please remain seated until the ride has come
|
||||||
|
to a complete stop. Possible penalties for early withdrawal. Post office will
|
||||||
|
not deliver without postage. Postage will be paid by addressee. Prerecorded
|
||||||
|
for this time zone. Price does not include taxes. Processed at location
|
||||||
|
stamped in code at top of carton. Quantities are limited while supplies last.
|
||||||
|
Read at your own risk. Record additional transactions on back of previous
|
||||||
|
stub. Replace with same type. Reproduction strictly prohibited. Restaurant
|
||||||
|
package, not for resale. Return to sender, no forwarding order on file,
|
||||||
|
unable to forward. Safety goggles may be required during use. Sanitized for
|
||||||
|
your protection. Sealed for your protection, do not use if the safety seal is
|
||||||
|
broken. See label for sequence. Shading within a garment may occur. Sign here
|
||||||
|
without admitting guilt. Simulated picture. Slightly enlarged to show detail.
|
||||||
|
Slightly higher west of the Rockies. Slippery when wet. Smoking these may be
|
||||||
|
hazardous to your health. Some assembly required. Some equipment shown is
|
||||||
|
optional. Some of the trademarks mentioned in this product appear for
|
||||||
|
identification purposes only. Subject to FCC approval. Subject to change
|
||||||
|
without notice. Substantial penalty for early withdrawal. Text may contain
|
||||||
|
material some readers may find objectionable, parental guidance is advised.
|
||||||
|
Text used in these documents is made from 100% recycled electrons and magnetic
|
||||||
|
particles. These documents do not reflect the thoughts or opinions of either
|
||||||
|
myself, my company, my friends, or my rabbit. This is not an offer to sell
|
||||||
|
securities. This offer is void where prohibited, taxed, or otherwise
|
||||||
|
restricted. This product is meant for educational purposes only. Times
|
||||||
|
approximate. Unix is a registered trademark of AT&T. Use only as directed. Use
|
||||||
|
only in a well-ventilated are. User assumes full liabilities. Void where
|
||||||
|
prohibited. We have sent the forms which seem right for you. You must be
|
||||||
|
present to win. You need not be present to win. Your canceled check is your
|
||||||
|
receipt. Your mileage may vary. I didn't do it. You can't prove anything.
|
||||||
|
|
||||||
|
This supersedes all previous notices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // STDDCLMR_H
|
Loading…
Add table
Reference in a new issue