Bitmap fonts. Margins. Start of buttons. Many fixes.
This commit is contained in:
parent
7d2d0c2fc3
commit
04cce38be1
19 changed files with 440 additions and 121 deletions
|
@ -43,6 +43,7 @@ INCLUDEPATH += \
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
$$LINUX_HEADERS \
|
$$LINUX_HEADERS \
|
||||||
|
src/gui/button.h \
|
||||||
src/thirdparty/stb_ds.h \
|
src/thirdparty/stb_ds.h \
|
||||||
src/thirdparty/stb_leakcheck.h \
|
src/thirdparty/stb_leakcheck.h \
|
||||||
src/thirdparty/stb_image.h \
|
src/thirdparty/stb_image.h \
|
||||||
|
@ -62,6 +63,7 @@ HEADERS = \
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$$LINUX_SOURCES \
|
$$LINUX_SOURCES \
|
||||||
src/gui/array.c \
|
src/gui/array.c \
|
||||||
|
src/gui/button.c \
|
||||||
src/gui/font.c \
|
src/gui/font.c \
|
||||||
src/gui/desktop.c \
|
src/gui/desktop.c \
|
||||||
src/gui/gui.c \
|
src/gui/gui.c \
|
||||||
|
|
|
@ -802,6 +802,16 @@ void vbeSurfaceDestroy(SurfaceT **surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSurfaceHeightGet(void) {
|
||||||
|
return _activeSurface->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSurfaceWidthGet(void) {
|
||||||
|
return _activeSurface->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void vbeSurfaceSet(SurfaceT *surface) {
|
void vbeSurfaceSet(SurfaceT *surface) {
|
||||||
if (surface) {
|
if (surface) {
|
||||||
_activeSurface = surface;
|
_activeSurface = surface;
|
||||||
|
|
114
client/src/gui/button.c
Normal file
114
client/src/gui/button.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 "button.h"
|
||||||
|
|
||||||
|
|
||||||
|
void buttonDel(WidgetT **widget) {
|
||||||
|
ButtonT *b = (ButtonT *)*widget;
|
||||||
|
|
||||||
|
if (b->title) free(b->title);
|
||||||
|
free(b);
|
||||||
|
b = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WidgetT *buttonInit(WidgetT *button, uint16_t x, uint16_t y, char *title, widgetCallback callback) {
|
||||||
|
ButtonT *b = (ButtonT *)button;
|
||||||
|
|
||||||
|
b->base.magic = MAGIC_BUTTON;
|
||||||
|
b->base.x = x;
|
||||||
|
b->base.y = y;
|
||||||
|
b->base.delMethod = buttonDel;
|
||||||
|
b->base.paintMethod = buttonPaint;
|
||||||
|
b->base.mouseEventMethod = buttonMouseEvent;
|
||||||
|
b->title = NULL;
|
||||||
|
b->clicked = callback;
|
||||||
|
|
||||||
|
buttonSetTitle(b, title);
|
||||||
|
|
||||||
|
// Width is set in buttonSetTitle
|
||||||
|
b->base.h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_MARGIN] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y) {
|
||||||
|
ButtonT *b = (ButtonT *)widget;
|
||||||
|
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
|
||||||
|
// Fire callback on mouse up.
|
||||||
|
if (!mouse->buttonLeft && mouse->buttonLeftWasDown) {
|
||||||
|
if (b->clicked) b->clicked(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback) {
|
||||||
|
ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT));
|
||||||
|
WidgetT *widget = NULL;
|
||||||
|
|
||||||
|
if (!button) return NULL;
|
||||||
|
|
||||||
|
widget = widgetInit((WidgetT *)button);
|
||||||
|
if (!widget) {
|
||||||
|
free(button);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
button = (ButtonT *)buttonInit((WidgetT *)button, x, y, title, callback);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void buttonPaint(WidgetT *button) {
|
||||||
|
ButtonT *b = (ButtonT *)button;
|
||||||
|
int16_t i;
|
||||||
|
uint16_t x1 = b->base.x + b->base.marginX;
|
||||||
|
uint16_t y1 = b->base.y + b->base.marginY;
|
||||||
|
|
||||||
|
if (GUI_GET_FLAG(button, WIDGET_FLAG_DIRTY)) {
|
||||||
|
vbeSurfaceSet(b->base.surface);
|
||||||
|
|
||||||
|
// Draw bezel.
|
||||||
|
for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) {
|
||||||
|
guiDrawHighlightFrame(x1 + i, y1 + i, x1 + b->base.w - i, y1 + b->base.h - i, _guiColor[COLOR_BUTTON_HIGHLIGHT], _guiColor[COLOR_BUTTON_SHADOW]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw background (depends on x from above).
|
||||||
|
guiDrawFilledRectangle(x1 + i, y1 + i, x1 + b->base.w - i, y1 + b->base.h - i, _guiColor[COLOR_BUTTON_BACKGROUND]);
|
||||||
|
|
||||||
|
// Draw title (depends on x from above).
|
||||||
|
fontRender(_guiFont, b->title, _guiColor[COLOR_BUTTON_TEXT], _guiColor[COLOR_BUTTON_BACKGROUND], x1 + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_MARGIN], y1 + i + _guiMetric[METRIC_BUTTON_VERTICAL_MARGIN]);
|
||||||
|
|
||||||
|
GUI_CLEAR_FLAG(button, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void buttonSetTitle(ButtonT *button, char *title) {
|
||||||
|
if (button->title) free(button->title);
|
||||||
|
button->title = strdup(title);
|
||||||
|
button->base.w = (strlen(title) * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_BUTTON_HORIZONTAL_MARGIN] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
|
||||||
|
}
|
44
client/src/gui/button.h
Normal file
44
client/src/gui/button.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Kangaroo Punch Multi Player 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 BUTTON_H
|
||||||
|
#define BUTTON_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ButtonS {
|
||||||
|
WidgetT base; // Must be first in every widget
|
||||||
|
char *title;
|
||||||
|
widgetCallback clicked;
|
||||||
|
} ButtonT;
|
||||||
|
|
||||||
|
|
||||||
|
void buttonDel(WidgetT **widget);
|
||||||
|
WidgetT *buttonInit(WidgetT *button, uint16_t x, uint16_t y, char *title, widgetCallback callback);
|
||||||
|
void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y);
|
||||||
|
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback);
|
||||||
|
void buttonPaint(WidgetT *button);
|
||||||
|
void buttonSetTitle(ButtonT *button, char *title);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BUTTON_H
|
|
@ -42,6 +42,7 @@ WidgetT *desktopInit(WidgetT *desktop) {
|
||||||
d->dragOffsetY = 0;
|
d->dragOffsetY = 0;
|
||||||
d->dragWidget = NULL;
|
d->dragWidget = NULL;
|
||||||
|
|
||||||
|
GUI_SET_FLAG(desktop, WIDGET_FLAG_OWNS_SURFACE);
|
||||||
d->base.surface = vbeSurfaceCreate(d->base.w, d->base.h);
|
d->base.surface = vbeSurfaceCreate(d->base.w, d->base.h);
|
||||||
if (!d->base.surface) {
|
if (!d->base.surface) {
|
||||||
free(d);
|
free(d);
|
||||||
|
@ -73,9 +74,9 @@ DesktopT *desktopNew(void) {
|
||||||
void desktopPaint(WidgetT *desktop) {
|
void desktopPaint(WidgetT *desktop) {
|
||||||
DesktopT *d = (DesktopT *)desktop;
|
DesktopT *d = (DesktopT *)desktop;
|
||||||
|
|
||||||
if (d->base.dirty) {
|
if (GUI_GET_FLAG(desktop, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(d->base.surface);
|
vbeSurfaceSet(d->base.surface);
|
||||||
vbeSurfaceClear(_guiColor[COLOR_DESKTOP]);
|
vbeSurfaceClear(_guiColor[COLOR_DESKTOP]);
|
||||||
d->base.dirty = 0;
|
GUI_CLEAR_FLAG(desktop, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t fontHeightGet(FontT *font) {
|
||||||
|
return font->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FontT *fontLoad(char *filename) {
|
FontT *fontLoad(char *filename) {
|
||||||
FILE *in = NULL;
|
FILE *in = NULL;
|
||||||
uint16_t size = 0;
|
uint16_t size = 0;
|
||||||
|
@ -59,15 +64,20 @@ FontT *fontLoad(char *filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT background, uint16_t x, uint16_t y) {
|
void fontRender(FontT *font, char *string, PixelT foreground, PixelT background, uint16_t x, uint16_t y) {
|
||||||
uint8_t cx;
|
uint8_t cx;
|
||||||
uint8_t cy;
|
uint8_t cy;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
uint8_t yl;
|
uint8_t yl;
|
||||||
uint16_t yp;
|
uint16_t yp;
|
||||||
uint8_t data;
|
uint8_t data;
|
||||||
|
uint8_t character;
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
//***TODO*** This only handles 8x8 fonts.
|
//***TODO*** This only handles 8xY fonts.
|
||||||
|
|
||||||
|
for (c=0; c<strlen(string); c++) {
|
||||||
|
character = string[c];
|
||||||
|
|
||||||
// Find character position in font grid.
|
// Find character position in font grid.
|
||||||
cx = character % font->span;
|
cx = character % font->span;
|
||||||
|
@ -78,7 +88,7 @@ void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT backgr
|
||||||
|
|
||||||
// Draw out 8 lines.
|
// Draw out 8 lines.
|
||||||
yp = y;
|
yp = y;
|
||||||
for (yl=0; yl<8; yl++) {
|
for (yl=0; yl<font->height; yl++) {
|
||||||
// We do 8 pixels unrolled hoping it's fast.
|
// We do 8 pixels unrolled hoping it's fast.
|
||||||
data = font->bits[offset];
|
data = font->bits[offset];
|
||||||
offset += font->span;
|
offset += font->span;
|
||||||
|
@ -92,6 +102,9 @@ void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT backgr
|
||||||
vbePutPixel(x + 7, yp, data & 0x01 ? foreground : background);
|
vbePutPixel(x + 7, yp, data & 0x01 ? foreground : background);
|
||||||
yp++;
|
yp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x += font->width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,3 +115,8 @@ void fontUnload(FontT **font) {
|
||||||
free(f);
|
free(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t fontWidthGet(FontT *font) {
|
||||||
|
return font->width;
|
||||||
|
}
|
||||||
|
|
|
@ -37,9 +37,11 @@ typedef struct FontS {
|
||||||
} FontT;
|
} FontT;
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t fontHeightGet(FontT *font);
|
||||||
FontT *fontLoad(char *filename);
|
FontT *fontLoad(char *filename);
|
||||||
void fontRender(FontT *font, uint8_t character, PixelT foreground, PixelT background, uint16_t x, uint16_t y);
|
void fontRender(FontT *font, char *string, PixelT foreground, PixelT background, uint16_t x, uint16_t y);
|
||||||
void fontUnload(FontT **font);
|
void fontUnload(FontT **font);
|
||||||
|
uint16_t fontWidthGet(FontT *font);
|
||||||
|
|
||||||
|
|
||||||
#endif // FONT_H
|
#endif // FONT_H
|
||||||
|
|
|
@ -26,15 +26,34 @@
|
||||||
|
|
||||||
int16_t _guiMetric[METRIC_COUNT];
|
int16_t _guiMetric[METRIC_COUNT];
|
||||||
PixelT _guiColor[COLOR_COUNT];
|
PixelT _guiColor[COLOR_COUNT];
|
||||||
|
FontT *_guiFont = NULL;
|
||||||
|
|
||||||
|
|
||||||
static DesktopT *_guiDesktop = NULL;
|
static DesktopT *_guiDesktop = NULL;
|
||||||
|
|
||||||
|
|
||||||
void guiAttach(WidgetT *parent, WidgetT *child) {
|
void guiAttach(WidgetT *parent, WidgetT *child) {
|
||||||
|
WidgetT *p = NULL;
|
||||||
|
|
||||||
// Add us to the child list.
|
// Add us to the child list.
|
||||||
child->parent = parent;
|
child->parent = parent;
|
||||||
arrput(parent->children, child);
|
arrput(parent->children, child);
|
||||||
|
|
||||||
|
// If this widget does not own a surface, find one for it to draw on.
|
||||||
|
if (!GUI_GET_FLAG(child, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
|
p = child;
|
||||||
|
while (p != NULL && !GUI_GET_FLAG(p, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
|
// Check parent.
|
||||||
|
p = p->parent;
|
||||||
|
if (p) {
|
||||||
|
// Calculate margins as we go.
|
||||||
|
child->marginX += p->marginX;
|
||||||
|
child->marginY += p->marginY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child->surface = p->surface;
|
||||||
|
}
|
||||||
|
|
||||||
// New windows should be active.
|
// New windows should be active.
|
||||||
if (child->magic == MAGIC_WINDOW) {
|
if (child->magic == MAGIC_WINDOW) {
|
||||||
windowSetActive((WindowT *)child);
|
windowSetActive((WindowT *)child);
|
||||||
|
@ -53,14 +72,16 @@ void guiComposite() {
|
||||||
vbeSurfaceSet(NULL);
|
vbeSurfaceSet(NULL);
|
||||||
|
|
||||||
// Render us?
|
// Render us?
|
||||||
if (widget->surface) {
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
vbeSurfaceBlit(widget->surface, widget->x, widget->y);
|
vbeSurfaceBlit(widget->surface, widget->x, widget->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***TODO*** This is wrong. Should be recursive.
|
||||||
|
|
||||||
// Now render all surface-containing children to the VBE buffer.
|
// Now render all surface-containing children to the VBE buffer.
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (x=0; x<len; x++) {
|
for (x=0; x<len; x++) {
|
||||||
if (widget->children[x]->surface) {
|
if (GUI_GET_FLAG(widget->children[x], WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
vbeSurfaceBlit(widget->children[x]->surface, widget->children[x]->x, widget->children[x]->y);
|
vbeSurfaceBlit(widget->children[x]->surface, widget->children[x]->x, widget->children[x]->y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,6 +190,25 @@ void guiDrawFilledRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, Pixe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiPaint(WidgetT *widget) {
|
||||||
|
size_t len = arrlenu(widget->children);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
// Paint us, if needed.
|
||||||
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY) && widget->paintMethod) {
|
||||||
|
widget->paintMethod(widget);
|
||||||
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paint all children.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
guiPaint(widget->children[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiProcessMouse(MouseT *mouse) {
|
void guiProcessMouse(MouseT *mouse) {
|
||||||
size_t len;
|
size_t len;
|
||||||
int16_t x;
|
int16_t x;
|
||||||
|
@ -179,7 +219,7 @@ void guiProcessMouse(MouseT *mouse) {
|
||||||
|
|
||||||
// Is the left button down?
|
// Is the left button down?
|
||||||
if (mouse->buttonLeft) {
|
if (mouse->buttonLeft) {
|
||||||
// Was it NOT down before?
|
// Was left button NOT down before?
|
||||||
if (!mouse->buttonLeftWasDown) {
|
if (!mouse->buttonLeftWasDown) {
|
||||||
// Initial click. Are we already dragging something?
|
// Initial click. Are we already dragging something?
|
||||||
if (!_guiDesktop->dragWidget) {
|
if (!_guiDesktop->dragWidget) {
|
||||||
|
@ -196,17 +236,21 @@ void guiProcessMouse(MouseT *mouse) {
|
||||||
window = (WindowT *)child;
|
window = (WindowT *)child;
|
||||||
// Is it the active window?
|
// Is it the active window?
|
||||||
if (GUI_GET_FLAG(window, WINDOW_FLAG_ACTIVE)) {
|
if (GUI_GET_FLAG(window, WINDOW_FLAG_ACTIVE)) {
|
||||||
// Start dragging.
|
// Are we on the draggable area of the titlebar / borders?
|
||||||
_guiDesktop->dragOffsetX = mouse->x - window->base.x;
|
_guiDesktop->dragOffsetX = mouse->x - window->base.x;
|
||||||
_guiDesktop->dragOffsetY = mouse->y - window->base.y;
|
_guiDesktop->dragOffsetY = mouse->y - window->base.y;
|
||||||
|
if (_guiDesktop->dragOffsetY < _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT]) {
|
||||||
|
// Start dragging.
|
||||||
_guiDesktop->dragWidget = child;
|
_guiDesktop->dragWidget = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // Was it NOT down before?
|
|
||||||
|
} else { // Was left button NOT down before?
|
||||||
|
|
||||||
// Still holding left button, but not the initial click. Update dragged widget location.
|
// Still holding left button, but not the initial click. Update dragged widget location.
|
||||||
if (_guiDesktop->dragWidget) {
|
if (_guiDesktop->dragWidget) {
|
||||||
|
@ -219,7 +263,7 @@ void guiProcessMouse(MouseT *mouse) {
|
||||||
if (_guiDesktop->dragWidget->y + _guiDesktop->dragWidget->h > vbeDisplayHeightGet()) _guiDesktop->dragWidget->y = vbeDisplayHeightGet() - _guiDesktop->dragWidget->h;
|
if (_guiDesktop->dragWidget->y + _guiDesktop->dragWidget->h > vbeDisplayHeightGet()) _guiDesktop->dragWidget->y = vbeDisplayHeightGet() - _guiDesktop->dragWidget->h;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Was it NOT down before?
|
} // Was left button NOT down before?
|
||||||
|
|
||||||
} else { // Left button down?
|
} else { // Left button down?
|
||||||
|
|
||||||
|
@ -257,39 +301,40 @@ void guiProcessMouse(MouseT *mouse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiPaint(WidgetT *widget) {
|
|
||||||
size_t len = arrlenu(widget->children);
|
|
||||||
size_t x;
|
|
||||||
|
|
||||||
// Paint us, if needed.
|
|
||||||
if (widget->dirty && widget->paintMethod) {
|
|
||||||
widget->paintMethod(widget);
|
|
||||||
widget->dirty = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paint all children, if needed.
|
|
||||||
if (len > 0) {
|
|
||||||
for (x=0; x<len; x++) {
|
|
||||||
if (widget->children[x]->dirty && widget->children[x]->paintMethod) {
|
|
||||||
widget->children[x]->paintMethod(widget->children[x]);
|
|
||||||
widget->children[x]->dirty = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WidgetT *guiRootGet(void) {
|
WidgetT *guiRootGet(void) {
|
||||||
return (WidgetT *)_guiDesktop;
|
return (WidgetT *)_guiDesktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiSetWidgetAndChildrenDirty(WidgetT *widget) {
|
||||||
|
size_t len = arrlenu(widget->children);
|
||||||
|
size_t x;
|
||||||
|
|
||||||
|
// Mark us dirty.
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
|
||||||
|
// Mark all children.
|
||||||
|
if (len > 0) {
|
||||||
|
for (x=0; x<len; x++) {
|
||||||
|
guiSetWidgetAndChildrenDirty(widget->children[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DesktopT *guiStartup(void) {
|
DesktopT *guiStartup(void) {
|
||||||
|
|
||||||
|
_guiMetric[METRIC_BUTTON_BEZEL_SIZE] = 2;
|
||||||
|
_guiMetric[METRIC_BUTTON_HORIZONTAL_MARGIN] = 8;
|
||||||
|
_guiMetric[METRIC_BUTTON_VERTICAL_MARGIN] = 2;
|
||||||
_guiMetric[METRIC_WINDOW_BORDER_WIDTH] = 4; // Does not include highlight or shadow lines.
|
_guiMetric[METRIC_WINDOW_BORDER_WIDTH] = 4; // Does not include highlight or shadow lines.
|
||||||
_guiMetric[METRIC_WINDOW_TITLE_HEIGHT] = 17; // Does not include highlight or shadow lines.
|
_guiMetric[METRIC_WINDOW_TITLE_HEIGHT] = 17; // Does not include highlight or shadow lines.
|
||||||
|
_guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT] = _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 4; // Border, highlights, titlebar.
|
||||||
|
|
||||||
|
_guiColor[COLOR_BUTTON_BACKGROUND] = vbeMakePixel(168, 168, 168);
|
||||||
|
_guiColor[COLOR_BUTTON_HIGHLIGHT] = vbeMakePixel(248, 252, 248);
|
||||||
|
_guiColor[COLOR_BUTTON_SHADOW] = vbeMakePixel( 80, 84, 80);
|
||||||
|
_guiColor[COLOR_BUTTON_TEXT] = vbeMakePixel( 0, 0, 0);
|
||||||
_guiColor[COLOR_DESKTOP] = vbeMakePixel( 51, 153, 255);
|
_guiColor[COLOR_DESKTOP] = vbeMakePixel( 51, 153, 255);
|
||||||
_guiColor[COLOR_WINDOW_BACKGROUND] = vbeMakePixel(168, 168, 168);
|
_guiColor[COLOR_WINDOW_BACKGROUND] = vbeMakePixel(168, 168, 168);
|
||||||
_guiColor[COLOR_WINDOW_HIGHLIGHT] = vbeMakePixel(248, 252, 248);
|
_guiColor[COLOR_WINDOW_HIGHLIGHT] = vbeMakePixel(248, 252, 248);
|
||||||
|
@ -299,6 +344,8 @@ DesktopT *guiStartup(void) {
|
||||||
_guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] = vbeMakePixel(248, 252, 248);
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] = vbeMakePixel(248, 252, 248);
|
||||||
_guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE] = vbeMakePixel( 0, 0, 0);
|
_guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE] = vbeMakePixel( 0, 0, 0);
|
||||||
|
|
||||||
|
_guiFont = fontLoad("vga8x14.dat");
|
||||||
|
|
||||||
// Create desktop and return it. Remember it for later.
|
// Create desktop and return it. Remember it for later.
|
||||||
_guiDesktop = desktopNew();
|
_guiDesktop = desktopNew();
|
||||||
|
|
||||||
|
@ -307,6 +354,18 @@ DesktopT *guiStartup(void) {
|
||||||
|
|
||||||
|
|
||||||
void guiShutdown(void) {
|
void guiShutdown(void) {
|
||||||
|
fontUnload(&_guiFont);
|
||||||
|
|
||||||
// Delete all widgets in GUI tree.
|
// Delete all widgets in GUI tree.
|
||||||
guiDelete((WidgetT **)&_guiDesktop);
|
guiDelete((WidgetT **)&_guiDesktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *guiUserDataGet(WidgetT *widget) {
|
||||||
|
return widget->userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void guiUserDataSet(WidgetT *widget, void *userData) {
|
||||||
|
widget->userData = userData;
|
||||||
|
}
|
||||||
|
|
|
@ -29,11 +29,14 @@
|
||||||
#include "vesa.h"
|
#include "vesa.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
|
||||||
#define GUI_GET_FLAG(w,f) ((w)->flags & (1 << (f)))
|
#define GUI_GET_FLAG(w,f) ((w)->flags & (1 << (f)))
|
||||||
#define GUI_SET_FLAG(w,f) ((w)->flags |= (1 << (f)))
|
#define GUI_SET_FLAG(w,f) (w)->flags |= (1 << (f))
|
||||||
#define GUI_CLEAR_FLAG(w,f) ((w)->flags &= (~(1 << (f))))
|
#define GUI_CLEAR_FLAG(w,f) (w)->flags &= (~(1 << (f)))
|
||||||
|
|
||||||
|
#define W(w) ((WidgetT *)w)
|
||||||
|
|
||||||
|
|
||||||
// Widget Magics
|
// Widget Magics
|
||||||
|
@ -47,14 +50,22 @@ enum MagicE {
|
||||||
|
|
||||||
// Widget Metrics
|
// Widget Metrics
|
||||||
enum MetricE {
|
enum MetricE {
|
||||||
METRIC_WINDOW_BORDER_WIDTH = 0,
|
METRIC_BUTTON_BEZEL_SIZE = 0,
|
||||||
|
METRIC_BUTTON_HORIZONTAL_MARGIN,
|
||||||
|
METRIC_BUTTON_VERTICAL_MARGIN,
|
||||||
|
METRIC_WINDOW_BORDER_WIDTH,
|
||||||
METRIC_WINDOW_TITLE_HEIGHT,
|
METRIC_WINDOW_TITLE_HEIGHT,
|
||||||
|
METRIC_WINDOW_TITLE_GRAB_HEIGHT,
|
||||||
METRIC_COUNT
|
METRIC_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
// Widget Colors
|
// Widget Colors
|
||||||
enum ColorE {
|
enum ColorE {
|
||||||
COLOR_DESKTOP = 0,
|
COLOR_BUTTON_BACKGROUND = 0,
|
||||||
|
COLOR_BUTTON_HIGHLIGHT,
|
||||||
|
COLOR_BUTTON_SHADOW,
|
||||||
|
COLOR_BUTTON_TEXT,
|
||||||
|
COLOR_DESKTOP,
|
||||||
COLOR_WINDOW_BACKGROUND,
|
COLOR_WINDOW_BACKGROUND,
|
||||||
COLOR_WINDOW_HIGHLIGHT,
|
COLOR_WINDOW_HIGHLIGHT,
|
||||||
COLOR_WINDOW_SHADOW,
|
COLOR_WINDOW_SHADOW,
|
||||||
|
@ -72,6 +83,7 @@ typedef struct DesktopS DesktopT;
|
||||||
|
|
||||||
extern int16_t _guiMetric[METRIC_COUNT];
|
extern int16_t _guiMetric[METRIC_COUNT];
|
||||||
extern PixelT _guiColor[COLOR_COUNT];
|
extern PixelT _guiColor[COLOR_COUNT];
|
||||||
|
extern FontT *_guiFont;
|
||||||
|
|
||||||
|
|
||||||
void guiAttach(WidgetT *parent, WidgetT *child);
|
void guiAttach(WidgetT *parent, WidgetT *child);
|
||||||
|
@ -83,8 +95,11 @@ void guiDrawFilledRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2,
|
||||||
void guiPaint(WidgetT *widget);
|
void guiPaint(WidgetT *widget);
|
||||||
void guiProcessMouse(MouseT *mouse);
|
void guiProcessMouse(MouseT *mouse);
|
||||||
WidgetT *guiRootGet(void);
|
WidgetT *guiRootGet(void);
|
||||||
|
void guiSetWidgetAndChildrenDirty(WidgetT *widget);
|
||||||
DesktopT *guiStartup(void);
|
DesktopT *guiStartup(void);
|
||||||
void guiShutdown(void);
|
void guiShutdown(void);
|
||||||
|
void *guiUserDataGet(WidgetT *widget);
|
||||||
|
void guiUserDataSet(WidgetT *widget, void *userData);
|
||||||
|
|
||||||
|
|
||||||
#endif // GUI_H
|
#endif // GUI_H
|
||||||
|
|
|
@ -53,6 +53,8 @@ void vbeSurfaceBlit(SurfaceT *source, uint16_t x, uint16_t y);
|
||||||
void vbeSurfaceClear(PixelT color);
|
void vbeSurfaceClear(PixelT color);
|
||||||
SurfaceT *vbeSurfaceCreate(uint16_t width, uint16_t height);
|
SurfaceT *vbeSurfaceCreate(uint16_t width, uint16_t height);
|
||||||
void vbeSurfaceDestroy(SurfaceT **surface);
|
void vbeSurfaceDestroy(SurfaceT **surface);
|
||||||
|
uint16_t vbeSurfaceHeightGet(void);
|
||||||
|
uint16_t vbeSurfaceWidthGet(void);
|
||||||
void vbeSurfaceSet(SurfaceT *surface);
|
void vbeSurfaceSet(SurfaceT *surface);
|
||||||
void vbeWaitVBlank(void);
|
void vbeWaitVBlank(void);
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,22 @@
|
||||||
|
|
||||||
WidgetT *widgetInit(WidgetT *widget) {
|
WidgetT *widgetInit(WidgetT *widget) {
|
||||||
widget->magic = MAGIC_UNKNOWN;
|
widget->magic = MAGIC_UNKNOWN;
|
||||||
|
widget->flags = 0;
|
||||||
widget->x = 0;
|
widget->x = 0;
|
||||||
widget->y = 0;
|
widget->y = 0;
|
||||||
widget->w = 0;
|
widget->w = 0;
|
||||||
widget->h = 0;
|
widget->h = 0;
|
||||||
widget->dirty = 1; // Force a paint right away
|
widget->marginX = 0;
|
||||||
|
widget->marginY = 0;
|
||||||
widget->surface = NULL;
|
widget->surface = NULL;
|
||||||
widget->children = NULL;
|
widget->children = NULL;
|
||||||
widget->parent = NULL;
|
widget->parent = NULL;
|
||||||
widget->delMethod = NULL;
|
widget->delMethod = NULL;
|
||||||
widget->paintMethod = NULL;
|
widget->paintMethod = NULL;
|
||||||
widget->mouseDownMethod = NULL;
|
widget->mouseEventMethod = NULL;
|
||||||
|
widget->userData = NULL;
|
||||||
|
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,27 +25,37 @@
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum WidgetE {
|
||||||
|
WIDGET_FLAG_DIRTY = 0,
|
||||||
|
WIDGET_FLAG_OWNS_SURFACE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct WidgetS;
|
struct WidgetS;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*widgetCallback)(struct WidgetS *widget);
|
||||||
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
||||||
typedef void (*widgetPaintMethod)(struct WidgetS *widget);
|
typedef void (*widgetPaintMethod)(struct WidgetS *widget);
|
||||||
typedef void (*widgetMouseDownMethod)(struct WidgetS *widget, uint16_t x, uint16_t y);
|
typedef void (*widgetMouseEventMethod)(struct WidgetS *widget, MouseT *mouse, uint16_t x, uint16_t y);
|
||||||
|
|
||||||
|
|
||||||
typedef struct WidgetS {
|
typedef struct WidgetS {
|
||||||
uint8_t magic; // Widget identifier constant
|
uint8_t magic; // Widget identifier constant
|
||||||
uint8_t dirty; // Does this widget need redrawn
|
uint8_t flags; // See above enum
|
||||||
SurfaceT *surface; // Pointer to compositable surface or NULL
|
SurfaceT *surface; // Pointer to compositable surface or NULL
|
||||||
int16_t x; // Position of widget on parent
|
int16_t x; // Position of widget on parent
|
||||||
int16_t y; // Position of widget on parent
|
int16_t y; // Position of widget on parent
|
||||||
uint16_t w; // Width of widget
|
uint16_t w; // Width of widget
|
||||||
uint16_t h; // Height of widget
|
uint16_t h; // Height of widget
|
||||||
|
uint16_t marginX; // Pixels to skip when placing child widgets
|
||||||
|
uint16_t marginY; // Pixels to skip when placing child widgets
|
||||||
struct WidgetS **children; // List of children
|
struct WidgetS **children; // List of children
|
||||||
struct WidgetS *parent; // Parent of this widget
|
struct WidgetS *parent; // Parent of this widget
|
||||||
widgetDelMethod delMethod; // Delete method
|
widgetDelMethod delMethod; // Delete method
|
||||||
widgetPaintMethod paintMethod; // Paint method
|
widgetPaintMethod paintMethod; // Paint method
|
||||||
widgetMouseDownMethod mouseDownMethod; // Mouse button down handler
|
widgetMouseEventMethod mouseEventMethod; // Mouse event handler
|
||||||
|
void *userData; // Anything the user wants to store
|
||||||
} WidgetT;
|
} WidgetT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ static void windowDeactivateAll(WidgetT *widget) {
|
||||||
if (widget->magic == MAGIC_WINDOW) {
|
if (widget->magic == MAGIC_WINDOW) {
|
||||||
// Deactivate it.
|
// Deactivate it.
|
||||||
GUI_CLEAR_FLAG((WindowT *)widget, WINDOW_FLAG_ACTIVE);
|
GUI_CLEAR_FLAG((WindowT *)widget, WINDOW_FLAG_ACTIVE);
|
||||||
widget->dirty = 1;
|
guiSetWidgetAndChildrenDirty(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process any children.
|
// Process any children.
|
||||||
|
@ -64,10 +64,15 @@ WidgetT *windowInit(WidgetT *window, uint16_t x, uint16_t y, uint16_t w, uint16_
|
||||||
win->base.h = h;
|
win->base.h = h;
|
||||||
win->base.delMethod = windowDel;
|
win->base.delMethod = windowDel;
|
||||||
win->base.paintMethod = windowPaint;
|
win->base.paintMethod = windowPaint;
|
||||||
|
win->flags = 0;
|
||||||
win->title = NULL;
|
win->title = NULL;
|
||||||
|
|
||||||
|
win->base.marginX += _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 2;
|
||||||
|
win->base.marginY += _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT];
|
||||||
|
|
||||||
windowSetTitle(win, title);
|
windowSetTitle(win, title);
|
||||||
|
|
||||||
|
GUI_SET_FLAG(window, WIDGET_FLAG_OWNS_SURFACE);
|
||||||
win->base.surface = vbeSurfaceCreate(win->base.w, win->base.h);
|
win->base.surface = vbeSurfaceCreate(win->base.w, win->base.h);
|
||||||
if (!win->base.surface) {
|
if (!win->base.surface) {
|
||||||
free(win->title);
|
free(win->title);
|
||||||
|
@ -102,9 +107,11 @@ void windowPaint(WidgetT *window) {
|
||||||
uint16_t x2 = w->base.w - 1;
|
uint16_t x2 = w->base.w - 1;
|
||||||
uint16_t y2 = w->base.h - 1;
|
uint16_t y2 = w->base.h - 1;
|
||||||
PixelT background = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_INACTIVE];
|
PixelT background = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_INACTIVE];
|
||||||
//PixelT text = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE];
|
PixelT text = GUI_GET_FLAG(w, WINDOW_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE];
|
||||||
|
|
||||||
if (w->base.dirty) {
|
//***NOTE*** This doesn't obey margins since desktops don't have any.
|
||||||
|
|
||||||
|
if (GUI_GET_FLAG(window, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(w->base.surface);
|
vbeSurfaceSet(w->base.surface);
|
||||||
|
|
||||||
// Background.
|
// Background.
|
||||||
|
@ -120,7 +127,9 @@ void windowPaint(WidgetT *window) {
|
||||||
guiDrawHighlightFrame(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 4, _guiColor[COLOR_WINDOW_HIGHLIGHT], _guiColor[COLOR_WINDOW_SHADOW]);
|
guiDrawHighlightFrame(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 3, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 4, _guiColor[COLOR_WINDOW_HIGHLIGHT], _guiColor[COLOR_WINDOW_SHADOW]);
|
||||||
guiDrawFilledRectangle(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 2, background);
|
guiDrawFilledRectangle(_guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, x2 - _guiMetric[METRIC_WINDOW_BORDER_WIDTH] - 4, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + _guiMetric[METRIC_WINDOW_TITLE_HEIGHT] + 2, background);
|
||||||
|
|
||||||
w->base.dirty = 0;
|
fontRender(_guiFont, w->title, text, background, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 16, _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 5);
|
||||||
|
|
||||||
|
GUI_CLEAR_FLAG(window, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ static SurfaceT *_activeSurface = NULL;
|
||||||
static uint16_t _width = 0;
|
static uint16_t _width = 0;
|
||||||
static uint16_t _height = 0;
|
static uint16_t _height = 0;
|
||||||
static MouseT _mouse;
|
static MouseT _mouse;
|
||||||
|
static uint8_t _windowScale = 1;
|
||||||
|
|
||||||
|
|
||||||
void (*vbePutPixel)(uint16_t x, uint16_t y, PixelT pixel);
|
void (*vbePutPixel)(uint16_t x, uint16_t y, PixelT pixel);
|
||||||
|
@ -83,8 +84,8 @@ MouseT *mouseRead(void) {
|
||||||
_mouse.buttonRight = ((buttons & SDL_BUTTON_RMASK) != 0);
|
_mouse.buttonRight = ((buttons & SDL_BUTTON_RMASK) != 0);
|
||||||
_mouse.buttonMiddle = ((buttons & SDL_BUTTON_MMASK) != 0);
|
_mouse.buttonMiddle = ((buttons & SDL_BUTTON_MMASK) != 0);
|
||||||
|
|
||||||
_mouse.x = mouseX;
|
_mouse.x = mouseX / _windowScale;
|
||||||
_mouse.y = mouseY;
|
_mouse.y = mouseY / _windowScale;
|
||||||
|
|
||||||
return &_mouse;
|
return &_mouse;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +163,7 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
|
||||||
(void)bpp;
|
(void)bpp;
|
||||||
|
|
||||||
|
_windowScale = 2;
|
||||||
vbePutPixel = vbePutPixel32;
|
vbePutPixel = vbePutPixel32;
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
@ -169,7 +171,9 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
|
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
|
||||||
_surface = SDL_GetWindowSurface(_window);
|
_surface = SDL_GetWindowSurface(_window);
|
||||||
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
|
||||||
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
|
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
|
||||||
|
SDL_SetWindowSize(_window, xRes * _windowScale, yRes * _windowScale);
|
||||||
|
|
||||||
_offScreenBuffer = vbeSurfaceCreate(xRes, yRes);
|
_offScreenBuffer = vbeSurfaceCreate(xRes, yRes);
|
||||||
|
|
||||||
|
@ -232,6 +236,16 @@ void vbeSurfaceDestroy(SurfaceT **surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSurfaceHeightGet(void) {
|
||||||
|
return _activeSurface->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t vbeSurfaceWidthGet(void) {
|
||||||
|
return _activeSurface->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void vbeSurfaceSet(SurfaceT *surface) {
|
void vbeSurfaceSet(SurfaceT *surface) {
|
||||||
SDL_Texture *texture = NULL;
|
SDL_Texture *texture = NULL;
|
||||||
|
|
||||||
|
|
|
@ -26,18 +26,20 @@
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
#include "button.h"
|
||||||
|
|
||||||
|
|
||||||
void test(void) {
|
void test(void) {
|
||||||
MouseT *mouse = NULL;
|
MouseT *mouse = NULL;
|
||||||
|
ImageT *pointer = NULL;
|
||||||
|
PixelT alpha;
|
||||||
DesktopT *desktop = NULL;
|
DesktopT *desktop = NULL;
|
||||||
WindowT *w1 = NULL;
|
WindowT *w1 = NULL;
|
||||||
WindowT *w2 = NULL;
|
WindowT *w2 = NULL;
|
||||||
WindowT *w3 = NULL;
|
WindowT *w3 = NULL;
|
||||||
ImageT *pointer = NULL;
|
ButtonT *b1 = NULL;
|
||||||
PixelT alpha;
|
|
||||||
|
|
||||||
vbeStartup(800, 600, 8);
|
vbeStartup(800, 600, 16);
|
||||||
mouseStartup();
|
mouseStartup();
|
||||||
desktop = guiStartup();
|
desktop = guiStartup();
|
||||||
|
|
||||||
|
@ -47,9 +49,12 @@ void test(void) {
|
||||||
w1 = windowNew(25, 25, 300, 200, "Window 1");
|
w1 = windowNew(25, 25, 300, 200, "Window 1");
|
||||||
w2 = windowNew(150, 150, 300, 200, "Window 2");
|
w2 = windowNew(150, 150, 300, 200, "Window 2");
|
||||||
w3 = windowNew(300, 300, 300, 200, "Window 3");
|
w3 = windowNew(300, 300, 300, 200, "Window 3");
|
||||||
guiAttach((WidgetT *)desktop, (WidgetT *)w1);
|
guiAttach(W(desktop), W(w1));
|
||||||
guiAttach((WidgetT *)desktop, (WidgetT *)w2);
|
guiAttach(W(desktop), W(w2));
|
||||||
guiAttach((WidgetT *)desktop, (WidgetT *)w3);
|
guiAttach(W(desktop), W(w3));
|
||||||
|
|
||||||
|
b1 = buttonNew(25, 25, "Test Button", NULL);
|
||||||
|
guiAttach(W(w3), W(b1));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
mouse = mouseRead();
|
mouse = mouseRead();
|
||||||
|
@ -76,7 +81,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
logOpen("test.log", 1);
|
logOpen("test.log", 0);
|
||||||
|
|
||||||
test();
|
test();
|
||||||
|
|
||||||
|
|
BIN
font/data/vga8x14.png
(Stored with Git LFS)
Normal file
BIN
font/data/vga8x14.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
font/data/vga8x16.png
(Stored with Git LFS)
Normal file
BIN
font/data/vga8x16.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -23,11 +23,7 @@
|
||||||
#include "stb.h"
|
#include "stb.h"
|
||||||
|
|
||||||
|
|
||||||
#define BITMAP_FILE "/home/scott/code/kpmpgsmkii/font/data/vga8x8.png"
|
void makeFont(char *source, char *target, int pixelsW, int pixelsH, int charsW, int charCount) {
|
||||||
#define FONT_FILE "/home/scott/code/kpmpgsmkii/client/bin/vga8x8.dat"
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
unsigned char *font = NULL;
|
unsigned char *font = NULL;
|
||||||
unsigned char data = 0;
|
unsigned char data = 0;
|
||||||
FILE *out = NULL;
|
FILE *out = NULL;
|
||||||
|
@ -38,25 +34,22 @@ int main(int argc, char *argv[]) {
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
|
|
||||||
(void)argc;
|
// Load font atlas from disk.
|
||||||
(void)argv;
|
font = stbi_load(source, (int *)&w, (int *)&h, (int *)&n, 3);
|
||||||
|
if (!font) return;
|
||||||
// Load 8x8 font from disk. Font is in a 16x16 grid.
|
|
||||||
font = stbi_load(BITMAP_FILE, (int *)&w, (int *)&h, (int *)&n, 3);
|
|
||||||
if (!font) return 1;
|
|
||||||
|
|
||||||
// Create data file for font.
|
// Create data file for font.
|
||||||
out = fopen(FONT_FILE, "wb");
|
out = fopen(target, "wb");
|
||||||
if (!out) {
|
if (!out) {
|
||||||
stbi_image_free(font);
|
stbi_image_free(font);
|
||||||
return 2;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide some metadata for enhancement later.
|
// Provide some metadata for enhancement later.
|
||||||
fputc(8, out); // Width of characters
|
fputc(pixelsW, out); // Width of characters
|
||||||
fputc(8, out); // Height of characters
|
fputc(pixelsH, out); // Height of characters
|
||||||
fputc(16, out); // Number of characters per row
|
fputc(charsW, out); // Number of characters per row
|
||||||
fputc(255, out); // Number of characters - 1
|
fputc(charCount, out); // Number of characters - 1
|
||||||
|
|
||||||
// Convert bitmap to actual bits.
|
// Convert bitmap to actual bits.
|
||||||
for (y=0; y<h; y++) {
|
for (y=0; y<h; y++) {
|
||||||
|
@ -75,6 +68,16 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
// Clean up.
|
// Clean up.
|
||||||
stbi_image_free(font);
|
stbi_image_free(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x8.png", "/home/scott/code/kpmpgsmkii/client/bin/vga8x8.dat", 8, 8, 16, 255);
|
||||||
|
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x14.png", "/home/scott/code/kpmpgsmkii/client/bin/vga8x14.dat", 8, 14, 16, 255);
|
||||||
|
makeFont("/home/scott/code/kpmpgsmkii/font/data/vga8x16.png", "/home/scott/code/kpmpgsmkii/client/bin/vga8x16.dat", 8, 16, 16, 255);
|
||||||
|
|
||||||
// Prove we cleaned up.
|
// Prove we cleaned up.
|
||||||
stb_leakcheck_dumpmem();
|
stb_leakcheck_dumpmem();
|
||||||
|
|
|
@ -16,7 +16,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/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
TEMPLATE = SUBDIRS
|
TEMPLATE = subdirs
|
||||||
CONFIG *= ORDERED
|
CONFIG *= ORDERED
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
|
|
Loading…
Add table
Reference in a new issue