Frame widget added.
This commit is contained in:
parent
87a69959c7
commit
353ebfb68e
9 changed files with 349 additions and 38 deletions
|
@ -55,6 +55,7 @@ HEADERS += \
|
|||
src/gui/surface.h \
|
||||
src/gui/widgets/button.h \
|
||||
src/gui/widgets/checkbox.h \
|
||||
src/gui/widgets/frame.h \
|
||||
src/gui/widgets/label.h \
|
||||
src/gui/widgets/picture.h \
|
||||
src/gui/widgets/radio.h \
|
||||
|
@ -78,6 +79,7 @@ SOURCES += \
|
|||
src/gui/surface.c \
|
||||
src/gui/widgets/button.c \
|
||||
src/gui/widgets/checkbox.c \
|
||||
src/gui/widgets/frame.c \
|
||||
src/gui/widgets/label.c \
|
||||
src/gui/widgets/picture.c \
|
||||
src/gui/widgets/radio.c \
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "widgets/vscroll.h"
|
||||
#include "widgets/hscroll.h"
|
||||
#include "widgets/scroll.h"
|
||||
#include "widgets/frame.h"
|
||||
|
||||
|
||||
#endif // GUIALL_H
|
||||
|
|
|
@ -202,6 +202,7 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
|
|||
guiRegister(vscrollRegister);
|
||||
guiRegister(hscrollRegister);
|
||||
guiRegister(scrollableRegister); // After hscroll and vscroll.
|
||||
guiRegister(frameRegister);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
266
roo-e/src/gui/widgets/frame.c
Normal file
266
roo-e/src/gui/widgets/frame.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "frame.h"
|
||||
|
||||
#include "array.h"
|
||||
|
||||
|
||||
uint8_t __MAGIC_FRAME = 0;
|
||||
|
||||
|
||||
static void frameDestroy(struct WidgetS *widget, ...);
|
||||
static void framePaint(struct WidgetS *widget, ...);
|
||||
static WidgetT *frameWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY);
|
||||
|
||||
|
||||
// Passing "flags" as a default int provides proper alignment for the following va_args list.
|
||||
FrameT *frameCreate(char *title, int16_t width, int16_t height, int flags, ...) {
|
||||
FrameT *f = NULL;
|
||||
SurfaceT *t = surfaceGet();
|
||||
va_list args;
|
||||
|
||||
NEW(FrameT, f);
|
||||
memset(f, 0, sizeof(FrameT));
|
||||
|
||||
widgetBaseSet(W(f), __MAGIC_FRAME, width, height);
|
||||
|
||||
// Set up desired frame style.
|
||||
f->flags = flags;
|
||||
|
||||
// Set up title.
|
||||
if (title && strlen(title) > 0) {
|
||||
f->title = (char *)malloc(strlen(title) + 3);
|
||||
if (!f->title) {
|
||||
DEL(f);
|
||||
return NULL;
|
||||
}
|
||||
sprintf(f->title, " %s ", title);
|
||||
}
|
||||
|
||||
// Get title and optional font.
|
||||
if (f->flags & FRAME_FONT) {
|
||||
va_start(args, flags);
|
||||
f->font = (FontT *)va_arg(args, void *);
|
||||
va_end(args);
|
||||
} else {
|
||||
f->font = __guiFontVGA8x14;
|
||||
}
|
||||
|
||||
// Surface size is requested size less the font area around it (unless style is FRAME_NONE).
|
||||
if (f->flags & FRAME_NONE) {
|
||||
f->pixels.x = width;
|
||||
f->pixels.y = height;
|
||||
} else {
|
||||
// With a frame, we need to adjust the height/width to be a multiple of the font size.
|
||||
f->chars.x = ((float)f->base.r.w / (float)fontWidthGet(f->font));
|
||||
f->chars.y = ((float)f->base.r.h / (float)fontHeightGet(f->font));
|
||||
f->base.r.w = f->chars.x * fontWidthGet(f->font);
|
||||
f->base.r.h = f->chars.y * fontHeightGet(f->font);
|
||||
f->pixels.x = f->base.r.w - (fontWidthGet(f->font) * 2);
|
||||
f->pixels.y = f->base.r.h - (fontHeightGet(f->font) * 2);;
|
||||
}
|
||||
|
||||
// Create surface.
|
||||
f->surface = surfaceCreate(f->pixels.x, f->pixels.y);
|
||||
if (!f->surface) {
|
||||
if (f->title) free(f->title);
|
||||
DEL(f);
|
||||
return NULL;
|
||||
}
|
||||
surfaceSet(f->surface);
|
||||
surfaceClear(GUI_LIGHTGRAY);
|
||||
surfaceSet(t);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static void frameDestroy(struct WidgetS *widget, ...) {
|
||||
FrameT *f = (FrameT *)widget;
|
||||
uint16_t c;
|
||||
|
||||
// Free children.
|
||||
for (c=0; c<arrlen(f->base.children); c++) widgetDestroy(f->base.children[c]);
|
||||
arrfree(f->base.children);
|
||||
|
||||
if (f->title) free(f->title);
|
||||
if (f->surface) surfaceDestroy(&f->surface);
|
||||
|
||||
DEL(f);
|
||||
}
|
||||
|
||||
|
||||
static void framePaint(struct WidgetS *widget, ...) {
|
||||
FrameT *f = (FrameT *)widget;
|
||||
SurfaceT *t = surfaceGet();
|
||||
PointT o;
|
||||
PointT w;
|
||||
uint16_t x;
|
||||
uint16_t x2;
|
||||
uint16_t y;
|
||||
uint16_t i;
|
||||
unsigned char ul;
|
||||
unsigned char ur;
|
||||
unsigned char ll;
|
||||
unsigned char lr;
|
||||
unsigned char h;
|
||||
unsigned char v;
|
||||
unsigned char s[2];
|
||||
|
||||
if (widgetDirtyGet(widget)) {
|
||||
widgetDirtySet(widget, 0);
|
||||
|
||||
// If we have a frame, draw it.
|
||||
if (f->flags & FRAME_NONE) {
|
||||
w.x = 0;
|
||||
w.y = 0;
|
||||
} else {
|
||||
w.x = fontWidthGet(f->font);
|
||||
w.y = fontHeightGet(f->font);
|
||||
if (f->flags & FRAME_SINGLE) {
|
||||
// Single line frame.
|
||||
ul = 218;
|
||||
ur = 191;
|
||||
ll = 192;
|
||||
lr = 217;
|
||||
h = 196;
|
||||
v = 179;
|
||||
} else {
|
||||
// Double line frame.
|
||||
ul = 201;
|
||||
ur = 187;
|
||||
ll = 200;
|
||||
lr = 188;
|
||||
h = 205;
|
||||
v = 186;
|
||||
}
|
||||
|
||||
fontColorSet(GUI_BLACK, GUI_LIGHTGRAY);
|
||||
fontModsEnabledSet(1);
|
||||
s[1] = 0;
|
||||
|
||||
// Top line.
|
||||
x = f->base.r.x;
|
||||
y = f->base.r.y;
|
||||
s[0] = ul;
|
||||
fontRender((char *)s, x, y);
|
||||
x += w.x;
|
||||
s[0] = h;
|
||||
for (i=0; i<f->chars.x - 2; i++) {
|
||||
fontRender((char *)s, x, y);
|
||||
x += w.x;
|
||||
}
|
||||
x2 = x;
|
||||
s[0] = ur;
|
||||
fontRender((char *)s, x, y);
|
||||
// Title (this incurs some overdraw).
|
||||
if (f->title) {
|
||||
fontRender(f->title, f->base.r.x + (w.x * 2), y);
|
||||
}
|
||||
// Middle lines.
|
||||
x = f->base.r.x;
|
||||
y += w.y;
|
||||
s[0] = v;
|
||||
for (i=0; i<f->chars.y - 2; i++) {
|
||||
fontRender((char *)s, x, y);
|
||||
fontRender((char *)s, x2, y);
|
||||
y += w.y;
|
||||
}
|
||||
// Bottom line.
|
||||
s[0] = ll;
|
||||
fontRender((char *)s, x, y);
|
||||
x += w.x;
|
||||
s[0] = h;
|
||||
for (i=0; i<f->chars.x - 2; i++) {
|
||||
fontRender((char *)s, x, y);
|
||||
x += w.x;
|
||||
}
|
||||
s[0] = lr;
|
||||
fontRender((char *)s, x, y);
|
||||
}
|
||||
|
||||
// Move the contents to 0,0 to draw it into it's own surface.
|
||||
o.x = f->base.r.x;
|
||||
o.y = f->base.r.y;
|
||||
f->base.r.x = 0;
|
||||
f->base.r.y = 0;
|
||||
|
||||
// Draw children onto surface.
|
||||
surfaceSet(f->surface);
|
||||
widgetChildrenPaint(widget);
|
||||
surfaceSet(t);
|
||||
|
||||
// Put us back at the proper coodinates.
|
||||
f->base.r.x = o.x;
|
||||
f->base.r.y = o.y;
|
||||
|
||||
// Blit.
|
||||
surfaceBlit(f->base.r.x + w.x, f->base.r.y + w.y, 0, 0, 0, 0, f->surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RegisterT *frameRegister(uint8_t magic) {
|
||||
static RegisterT reg = {
|
||||
"Frame",
|
||||
NULL, // No default on-click handler.
|
||||
frameDestroy,
|
||||
framePaint,
|
||||
NULL, // No unregister handler.
|
||||
frameWidgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
__MAGIC_FRAME = magic;
|
||||
|
||||
return ®
|
||||
}
|
||||
|
||||
|
||||
static WidgetT *frameWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY) {
|
||||
int16_t i;
|
||||
WidgetT *w;
|
||||
PointT p;
|
||||
FrameT *f = (FrameT *)widget;
|
||||
|
||||
// Widget local mouse position.
|
||||
*localX = x - widget->r.x - (f->flags & FRAME_NONE ? 0 : fontWidthGet(f->font));
|
||||
*localY = y - widget->r.y - (f->flags & FRAME_NONE ? 0 : fontHeightGet(f->font));
|
||||
|
||||
// Find widget under mouse.
|
||||
for (i=0; i<arrlen(widget->children); i++) {
|
||||
w = widget->children[i];
|
||||
if (*localX >= w->r.x && *localX < w->r.x + w->r.w && *localY >= w->r.y && *localY < w->r.y + w->r.h) {
|
||||
// Ask this widget who we're pointing at.
|
||||
p.x = *localX;
|
||||
p.y = *localY;
|
||||
return w->reg->findWidget(w, p.x, p.y, localX, localY);
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find a widget.
|
||||
return NULL;
|
||||
}
|
57
roo-e/src/gui/widgets/frame.h
Normal file
57
roo-e/src/gui/widgets/frame.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FRAME_H
|
||||
#define FRAME_H
|
||||
|
||||
|
||||
#include "../gui.h"
|
||||
|
||||
|
||||
#define FRAME_NONE 0
|
||||
#define FRAME_SINGLE 1
|
||||
#define FRAME_DOUBLE 2
|
||||
#define FRAME_FONT 4 // User will provide font to use.
|
||||
|
||||
|
||||
typedef struct FrameS {
|
||||
WidgetT base; // Required by all widgets.
|
||||
uint8_t flags;
|
||||
SurfaceT *surface;
|
||||
PointT pixels; // Size of surface in pixels.
|
||||
PointT chars; // Size of frame in characters (if there's a border).
|
||||
char *title;
|
||||
FontT *font;
|
||||
} FrameT;
|
||||
|
||||
|
||||
extern uint8_t __MAGIC_FRAME; // Magic ID assigned to us from the GUI.
|
||||
|
||||
|
||||
FrameT *frameCreate(char *title, int16_t width, int16_t height, int flags, ...);
|
||||
RegisterT *frameRegister(uint8_t magic);
|
||||
|
||||
|
||||
#endif // FRAME_H
|
|
@ -69,13 +69,12 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// Clicking left of thumb? Also fakes dragging.
|
||||
if (x < h->thumb.x) {
|
||||
// Move content left.
|
||||
h->value -= SCROLL_SPEED_FAST;
|
||||
// Clip.
|
||||
if (h->value < h->min) h->value = h->min;
|
||||
if (h->value < 0) h->value = 0;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
|
@ -88,14 +87,13 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
// Move content right.
|
||||
h->value += SCROLL_SPEED_FAST;
|
||||
// Clip.
|
||||
if (h->value > h->max - h->base.r.w) h->value = h->max - h->base.r.w;
|
||||
if (h->value > h->maxValue) h->value = h->maxValue;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
if (h->handler) h->handler(widget, x, y, event, h->base.data);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -69,13 +69,12 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// Clicking above thumb? Also fakes dragging.
|
||||
if (y < v->thumb.y) {
|
||||
// Move content up.
|
||||
v->value -= SCROLL_SPEED_FAST;
|
||||
// Clip.
|
||||
if (v->value < v->min) v->value = v->min;
|
||||
if (v->value < 0) v->value = 0;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
|
@ -88,14 +87,13 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
// Move content down.
|
||||
v->value += SCROLL_SPEED_FAST;
|
||||
// Clip.
|
||||
if (v->value > v->max - v->base.r.h) v->value = v->max - v->base.r.h;
|
||||
if (v->value > v->maxValue) v->value = v->maxValue;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
if (v->handler) v->handler(widget, x, y, event, v->base.data);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -639,6 +639,7 @@ static WidgetT *windowWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int1
|
|||
br.x = *localX;
|
||||
br.y = *localY;
|
||||
w = w->reg->findWidget(w, br.x, br.y, localX, localY);
|
||||
if (w) logWrite("Over %s\n", w->reg->widgetName);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
@ -902,10 +903,8 @@ void wmUpdate(EventT *event) {
|
|||
if (widgetDown) {
|
||||
// Are we still inside the window content?
|
||||
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||
// Are we stll over the same widget?
|
||||
widget = windowWidgetFinder(W(win), event->x, event->y, &widgetLocal.x, &widgetLocal.y);
|
||||
// Send to widget for processing or send cancel.
|
||||
if (widgetDown->reg->click) widgetDown->reg->click(widgetDown, widgetLocal.x, widgetLocal.y, (widget == widgetDown) ? CLICK_LEFT_UP : CLICK_LEFT_CANCEL, widgetDown->data);
|
||||
// Are we stll over the same widget? Send to widget for processing or send cancel.
|
||||
if (widgetDown->reg->click) widgetDown->reg->click(widgetDown, widgetLocal.x, widgetLocal.y, (widgetOver == widgetDown) ? CLICK_LEFT_UP : CLICK_LEFT_CANCEL, widgetDown->data);
|
||||
}
|
||||
widgetDown = NULL;
|
||||
} // widgetDown
|
||||
|
|
|
@ -26,16 +26,6 @@
|
|||
#include "gui/gui-all.h"
|
||||
|
||||
|
||||
VscrollT *_v = NULL;
|
||||
HscrollT *_h = NULL;
|
||||
|
||||
|
||||
void clickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
|
||||
(void)widget;
|
||||
logWrite("%d %dx%d %s %d %d\n", event, x, y, data, vscrollValueGet(_v), hscrollValueGet(_h));
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char title[256];
|
||||
uint16_t i;
|
||||
|
@ -44,11 +34,10 @@ int main(int argc, char *argv[]) {
|
|||
ButtonT *b = NULL;
|
||||
CheckboxT *c = NULL;
|
||||
RadioT *r = NULL;
|
||||
ScrollableT *s = NULL;
|
||||
|
||||
FrameT *f = NULL;
|
||||
|
||||
// frame
|
||||
// scrollarea
|
||||
// layout
|
||||
|
||||
// listbox
|
||||
// textbox
|
||||
|
@ -72,15 +61,25 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
l = labelCreate(LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label");
|
||||
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
|
||||
labelClickSet(l, clickHandler, title);
|
||||
widgetAdd(W(w), 20, 10, W(l));
|
||||
|
||||
b = buttonCreate("Button", clickHandler, NULL);
|
||||
b = buttonCreate("Button", NULL, NULL);
|
||||
widgetAdd(W(w), 20, 40, W(b));
|
||||
|
||||
c = checkboxCreate("Checkbox", 0);
|
||||
widgetAdd(W(w), 20, 80, W(c));
|
||||
|
||||
f = frameCreate("Frame", 310, 60, FRAME_SINGLE);
|
||||
widgetAdd(W(w), 20, 110, W(f));
|
||||
|
||||
r = radioCreate("Radio 1", 0, 1);
|
||||
widgetAdd(W(f), 0, 5, W(r));
|
||||
r = radioCreate("Radio 2", 0, 0);
|
||||
widgetAdd(W(f), 100, 5, W(r));
|
||||
r = radioCreate("Radio 3", 0, 0);
|
||||
widgetAdd(W(f), 200, 5, W(r));
|
||||
|
||||
/*
|
||||
r = radioCreate("Radio 1", 0, 1);
|
||||
widgetAdd(W(w), 20, 110, W(r));
|
||||
r = radioCreate("Radio 2", 0, 0);
|
||||
|
@ -94,17 +93,7 @@ int main(int argc, char *argv[]) {
|
|||
widgetAdd(W(w), 120, 140, W(r));
|
||||
r = radioCreate("Radio C", 1, 0);
|
||||
widgetAdd(W(w), 220, 140, W(r));
|
||||
|
||||
_v = vscrollCreate(100, clickHandler, NULL);
|
||||
vscrollRangeSet(_v, 0, 640);
|
||||
widgetAdd(W(w), 200, 5, W(_v));
|
||||
|
||||
_h = hscrollCreate(100, clickHandler, NULL);
|
||||
hscrollRangeSet(_h, 0, 640);
|
||||
widgetAdd(W(w), 100, 5, W(_h));
|
||||
|
||||
s = scrollableCreate(300, 200, 648, 480, SCROLLABLE_STANDARD);
|
||||
widgetAdd(W(w), 20, 170, W(s));
|
||||
*/
|
||||
}
|
||||
guiRun();
|
||||
guiShutdown();
|
||||
|
|
Loading…
Add table
Reference in a new issue