Minimizing and restoring works. Start of resizing.

This commit is contained in:
Scott Duensing 2022-06-18 20:04:43 -05:00
parent 96391b499d
commit b6f78593e4
6 changed files with 198 additions and 98 deletions

BIN
client/assets/mouse.png (Stored with Git LFS)

Binary file not shown.

BIN
client/assets/resize.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -18,11 +18,16 @@ FontT *__guiFontVGA8x14 = NULL;
FontT *__guiFontVGA8x16 = NULL;
static uint8_t _magicCount = 0;
static WidgetCatalogT *_widgetCatalog = NULL;
static uint8_t _guiRunning = 1;
static SurfaceT *_mousePointer = NULL;
static ColorT _mouseTransparency;
static uint8_t _magicCount = 0;
static WidgetCatalogT *_widgetCatalog = NULL;
static uint8_t _guiRunning = 1;
static SurfaceT *_mousePointer[MOUSE_COUNT] = { 0 };
static ColorT _mouseTransparency = 0;
static uint8_t _mouseCurrent = MOUSE_POINTER;
static PointT _mouseHotspot[MOUSE_COUNT] = {
{ 0, 0 },
{ 8, 8 }
};
void guiEventsDo(void) {
@ -40,7 +45,7 @@ void guiEventsDo(void) {
// Paint mouse pointer.
surfaceSet(__guiBackBuffer);
surfaceBlitWithTransparency(event.x, event.y, _mousePointer, _mouseTransparency);
surfaceBlitWithTransparency(event.x - _mouseHotspot[_mouseCurrent].x, event.y - _mouseHotspot[_mouseCurrent].y, _mousePointer[_mouseCurrent], _mouseTransparency);
// Copy to screen.
videoBlit(0, 0, __guiBackBuffer);
@ -50,6 +55,16 @@ void guiEventsDo(void) {
}
uint8_t guiMousePointerGet(void) {
return _mouseCurrent;
}
void guiMousePointerSet(uint8_t pointer) {
_mouseCurrent = pointer;
}
void guiRegister(WidgetRegisterT widgetRegister) {
RegisterT *reg = widgetRegister(_magicCount);
hmput(_widgetCatalog, _magicCount, reg);
@ -70,6 +85,8 @@ void guiRun(void) {
void guiShutdown(void) {
uint8_t i;
DEL(__guiBaseColors);
while (hmlen(_widgetCatalog) > 0) {
@ -84,7 +101,7 @@ void guiShutdown(void) {
fontUnload(&__guiFontVGA8x14);
fontUnload(&__guiFontVGA8x8);
surfaceDestroy(&_mousePointer);
for (i=0; i<MOUSE_COUNT; i++) surfaceDestroy(&_mousePointer[i]);
surfaceDestroy(&__guiBackBuffer);
platformShutdown();
@ -119,8 +136,9 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
__guiBaseColors[i] = surfaceColorMake(EGA[i][0], EGA[i][1], EGA[i][2]);
}
_mousePointer = imageLoad("mouse.png");
_mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color.
_mousePointer[MOUSE_POINTER] = imageLoad("mouse.png");
_mousePointer[MOUSE_RESIZE] = imageLoad("resize.png");
_mouseTransparency = surfacePixelGet(_mousePointer[MOUSE_POINTER], surfaceWidthGet(_mousePointer[MOUSE_POINTER]) - 2, 0); // Find our transparency color.
__guiFontVGA8x8 = fontLoad("vga8x8.dat");
__guiFontVGA8x14 = fontLoad("vga8x14.dat");

View file

@ -55,6 +55,11 @@ extern FontT *__guiFontVGA8x14;
extern FontT *__guiFontVGA8x16;
#define MOUSE_POINTER 0
#define MOUSE_RESIZE 1
#define MOUSE_COUNT 2
#define GUI_BLACK __guiBaseColors[0]
#define GUI_BLUE __guiBaseColors[1]
#define GUI_GREEN __guiBaseColors[2]
@ -78,6 +83,8 @@ extern FontT *__guiFontVGA8x16;
void guiEventsDo(void);
uint8_t guiMousePointerGet(void);
void guiMousePointerSet(uint8_t pointer);
void guiRegister(WidgetRegisterT widgetRegister);
void guiRun(void);
void guiShutdown(void);

View file

@ -153,16 +153,21 @@ static void windowCache(WindowT *w) {
// Resize handle.
if (w->flags & WIN_RESIZE) {
x1 = w->base.r.x + w->base.r.w - 2;
x2 = x1 - 3;
y1 = w->base.r.y + w->base.r.h - 21;
surfaceLineH(x1, x2, y1, GUI_BLACK);
surfaceLineH(x1, x2, y1 + 1, GUI_WHITE);
x1 = w->base.r.x + w->base.r.w - 21;
y1 = w->base.r.y + w->base.r.h - 2;
y2 = y1 - 3;
surfaceLineV(x1, y1, y2, GUI_BLACK);
surfaceLineV(x1 + 1, y1, y2, GUI_WHITE);
w->resize1.x2 = w->base.r.x + w->base.r.w - 2;
w->resize1.x = w->resize1.x2 - 3;
w->resize1.y2 = w->base.r.y + w->base.r.h;
w->resize1.y = w->resize1.y2 - 21;
surfaceLineH(w->resize1.x, w->resize1.x2, w->resize1.y, GUI_BLACK);
surfaceLineH(w->resize1.x, w->resize1.x2, w->resize1.y + 1, GUI_WHITE);
w->resize2.x2 = w->base.r.x + w->base.r.w;
w->resize2.x = w->resize2.x2 - 21;
w->resize2.y2 = w->base.r.y + w->base.r.h - 2;
w->resize2.y = w->resize2.y2 - 3;
surfaceLineV(w->resize2.x, w->resize2.y, w->resize2.y2, GUI_BLACK);
surfaceLineV(w->resize2.x + 1, w->resize2.y, w->resize2.y2, GUI_WHITE);
} else {
w->resize1.x = w->resize1.y = w->resize1.x2 = w->resize1.y2 = 0;
w->resize2.x = w->resize2.y = w->resize2.x2 = w->resize2.y2 = 0;
}
// Blit contents.
@ -175,6 +180,7 @@ static void windowCache(WindowT *w) {
}
#include "image.h"
// Passing "flags" as a default int provides proper alignment for the following va_args list.
WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title, int flags, ...) {
int16_t width;
@ -192,10 +198,22 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
win->titlebar.x = win->titlebar.y = win->titlebar.x2 = win->titlebar.y2 = 0;
win->minimize.x = win->minimize.y = win->minimize.x2 = win->minimize.y2 = 0;
win->maximize.x = win->maximize.y = win->maximize.x2 = win->maximize.y2 = 0;
win->resize1.x = win->resize1.y = win->resize1.x2 = win->resize1.y2 = 0;
win->resize2.x = win->resize2.y = win->resize2.x2 = win->resize2.y2 = 0;
win->bounds.x = win->bounds.y = win->bounds.x2 = win->bounds.y2 = 0;
win->cached = NULL;
win->content = NULL;
//***DEBUG*** Hackery to get contents before we have widgets.
static uint8_t image = 1;
static char name[16];
width = 640;
height = 480;
sprintf(name, "back%d.png", image++);
win->content = imageLoad(name);
win->flags |= WIN_RESIZE;
/*
// If the window is resizable, we need to get two more arguments for the content size.
if (win->flags & WIN_RESIZE) {
va_start(args, flags);
@ -214,6 +232,7 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
surfaceSet(win->content);
surfaceClear(GUI_LIGHTGRAY);
surfaceSet(t);
*/
// Do we need scrollbars?
if (width > win->bounds.x2 - win->bounds.x) win->flags |= WIN_SCROLL_H;
@ -338,6 +357,17 @@ void windowMoveTo(WindowT *w, uint16_t x, uint16_t y) {
w->titlebar.y2 += dy;
}
if (w->flags & WIN_RESIZE) {
w->resize1.x += dx;
w->resize1.y += dy;
w->resize1.x2 += dx;
w->resize1.y2 += dy;
w->resize2.x += dx;
w->resize2.y += dy;
w->resize2.x2 += dx;
w->resize2.y2 += dy;
}
w->bounds.x += dx;
w->bounds.y += dy;
w->bounds.x2 += dx;
@ -355,6 +385,8 @@ void windowPaint(struct WidgetS *widget, ...) {
int16_t py;
int16_t xi;
int16_t yi;
int16_t xc;
int16_t yc;
WindowT *w = (WindowT *)widget;
// Do we need redrawn?
@ -365,13 +397,17 @@ void windowPaint(struct WidgetS *widget, ...) {
// Are we minimized?
if (w->flags & WIN_IS_ICON) {
// Draw iconized version of contents.
// Draw iconized version of contents. There are too many counters here but it's the only way it worked reliably.
yi = (surfaceHeightGet(w->content) - 1) / ICON_SIZE;
xi = (surfaceWidthGet(w->content) - 1) / ICON_SIZE;
py = videoDisplayHeightGet() - ICON_SIZE - 2;
for (y=0; y<surfaceHeightGet(w->content) - 1; y+=yi) {
py = videoDisplayHeightGet() - ICON_SIZE;
y = 0;
x = 0;
for (yc=0; yc<ICON_SIZE; yc++) {
y += yi;
px = (ICON_SIZE + 1) * _iconCount;
for (x=0; x<surfaceWidthGet(w->content) - 1; x+=xi) {
for (xc=0; xc<ICON_SIZE; xc++) {
x += xi;
surfacePixelSet(px++, py, surfacePixelGet(w->content, x, y));
}
py++;
@ -416,14 +452,20 @@ void wmUpdate(EventT *event) {
int16_t i;
int16_t x2;
int16_t y2;
uint8_t onResize = 0;
WidgetT *widget;
WindowT *win;
static uint8_t dragging = 0;
static PointT dragOffset = { 0 };
static uint8_t resizing = 0;
static PointT resizeOffset = { 0 };
static uint8_t dragging = 0;
static PointT dragOffset = { 0 };
// Do we have windows?
if (arrlen(_windowList) > 0) {
// Mouse is always the default pointer unless something changes it for this frame.
guiMousePointerSet(MOUSE_POINTER);
// Paint all windows.
_iconCount = 0;
for (i=0; i<arrlen(_windowList); i++) {
@ -441,6 +483,18 @@ void wmUpdate(EventT *event) {
// Wrap left button processing with a 'for' so we can 'break' out of it.
for (;;) {
// Does the topmost window have a resize?
if (win->flags & WIN_RESIZE) {
// Are we over the resize of the topmost window?
if ((event->x <= win->resize1.x2 && event->x >= win->resize1.x && event->y <= win->resize1.y2 && event->y >= win->resize1.y) ||
(event->x <= win->resize2.x2 && event->x >= win->resize2.x && event->y <= win->resize2.y2 && event->y >= win->resize2.y) ||
resizing) {
onResize = 1;
guiMousePointerSet(MOUSE_RESIZE);
}
}
// Is the left mouse button down?
if (event->buttons & BUTTON_LEFT) {
@ -464,88 +518,101 @@ void wmUpdate(EventT *event) {
} else { // Dragging.
// Did the button just go down?
if (event->flags & EVENT_FLAG_LEFT_DOWN) {
if (resizing) {
// Are we on the topmost window?
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
} else { // Resizing
// Are we inside the window content? Most likely, check first.
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
//***TODO*** Send to window for processing.
}
// Did the button just go down?
if (event->flags & EVENT_FLAG_LEFT_DOWN) {
// Are we inside the close button? Does not include button frame on purpose.
if (win->flags & WIN_CLOSE && event->x < win->close.x2 && event->x > win->close.x && event->y < win->close.y2 && event->y > win->close.y) {
//***TODO*** Close.
}
// Are we on the topmost window?
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
// Are we inside the title bar to begin dragging? Does not include titlebar frame on purpose.
if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) {
dragging = 1;
dragOffset.x = event->x - win->base.r.x;
dragOffset.y = event->y - win->base.r.y;
break;
}
// Are we inside the minimize button? Does not include button frame on purpose.
if (win->flags & WIN_MINIMIZE &&event->x < win->minimize.x2 && event->x > win->minimize.x && event->y < win->minimize.y2 && event->y > win->minimize.y) {
win->flags |= WIN_IS_ICON;
}
// Are we inside the maximize button? Does not include button frame on purpose.
if (win->flags & WIN_MAXIMIZE &&event->x < win->maximize.x2 && event->x > win->maximize.x && event->y < win->maximize.y2 && event->y > win->maximize.y) {
//***TODO*** Maximize.
}
} else { // On topmost window.
// Not over topmost window. Search backwards to find first window we're inside.
i = arrlen(_windowList) - 2;
if (i >= 0) {
for (; i>=0; i--) {
win = _windowList[i];
// Get right/bottom of window.
x2 = win->base.r.x + win->base.r.w - 1;
y2 = win->base.r.y + win->base.r.h - 1;
// Inside this window?
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
// Bring this window forward.
windowFocusSet(win);
// If we happened to be in the title bar, go ahead and start dragging. Does not include titlebar frame on purpose.
if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) {
dragging = 1;
dragOffset.x = event->x - win->base.r.x;
dragOffset.y = event->y - win->base.r.y;
}
break;
}
// Are we on the resizing area?
if (onResize) {
resizing = 1;
resizeOffset.x = event->x - win->base.r.x;
resizeOffset.y = event->y - win->base.r.y;
break;
}
}
} // On topmost window.
// Are we inside the window content? Most likely, check first.
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
//***TODO*** Send to window for processing.
}
// Do we have minimized windows?
if (_iconCount > 0) {
// Are we inside the minimized icons area?
if (event->x < (ICON_SIZE + 1) * _iconCount && event->y >= videoDisplayHeightGet() - ICON_SIZE - 1) {
// Figure out which icon we're over.
x2 = 0;
for (i=0; i<arrlen(_windowList); i++) {
if (_windowList[i]->flags & WIN_IS_ICON) {
x2 += ICON_SIZE;
// This window?
if (event->x < x2) {
// Restore it and stop looking for icons.
_windowList[i]->flags &= ~WIN_IS_ICON;
windowFocusSet(_windowList[i]);
// Are we inside the close button? Does not include button frame on purpose.
if (win->flags & WIN_CLOSE && event->x < win->close.x2 && event->x > win->close.x && event->y < win->close.y2 && event->y > win->close.y) {
//***TODO*** Close.
}
// Are we inside the title bar to begin dragging? Does not include titlebar frame on purpose.
if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) {
dragging = 1;
dragOffset.x = event->x - win->base.r.x;
dragOffset.y = event->y - win->base.r.y;
break;
}
// Are we inside the minimize button? Does not include button frame on purpose.
if (win->flags & WIN_MINIMIZE &&event->x < win->minimize.x2 && event->x > win->minimize.x && event->y < win->minimize.y2 && event->y > win->minimize.y) {
win->flags |= WIN_IS_ICON;
}
// Are we inside the maximize button? Does not include button frame on purpose.
if (win->flags & WIN_MAXIMIZE &&event->x < win->maximize.x2 && event->x > win->maximize.x && event->y < win->maximize.y2 && event->y > win->maximize.y) {
//***TODO*** Maximize.
}
} else { // On topmost window.
// Not over topmost window. Search backwards to find first window we're inside.
i = arrlen(_windowList) - 2;
if (i >= 0) {
for (; i>=0; i--) {
win = _windowList[i];
// Get right/bottom of window.
x2 = win->base.r.x + win->base.r.w - 1;
y2 = win->base.r.y + win->base.r.h - 1;
// Inside this window?
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
// Bring this window forward.
windowFocusSet(win);
// If we happened to be in the title bar, go ahead and start dragging. Does not include titlebar frame on purpose.
if (event->x < win->titlebar.x2 && event->x > win->titlebar.x && event->y < win->titlebar.y2 && event->y > win->titlebar.y) {
dragging = 1;
dragOffset.x = event->x - win->base.r.x;
dragOffset.y = event->y - win->base.r.y;
}
break;
}
// Next! (Skips pixel between icons.)
x2++;
}
}
} // Minimized windows?
} // On topmost window.
// Do we have minimized windows?
if (_iconCount > 0) {
// Are we inside the minimized icons area?
if (event->x < (ICON_SIZE + 1) * _iconCount && event->y >= videoDisplayHeightGet() - ICON_SIZE) {
// Figure out which icon we're over.
x2 = 0;
for (i=0; i<arrlen(_windowList); i++) {
if (_windowList[i]->flags & WIN_IS_ICON) {
x2 += ICON_SIZE;
// This window?
if (event->x < x2) {
// Restore it and stop looking for icons.
_windowList[i]->flags &= ~WIN_IS_ICON;
windowFocusSet(_windowList[i]);
break;
}
// Next! (Skips pixel between icons.)
x2++;
}
}
} // Minimized windows?
}
}
} // Button just went down.
@ -558,6 +625,9 @@ void wmUpdate(EventT *event) {
// Can no longer be dragging.
dragging = 0;
// Can no longer be resizing.
resizing = 0;
}
break;

View file

@ -23,6 +23,8 @@ typedef struct WindowS {
RectT titlebar; // Coordinates of title bar, if any.
RectT minimize; // Coordinates of minimize box, if any.
RectT maximize; // Coordinates of maximize box, if any.
RectT resize1; // First resize area.
RectT resize2; // Second resize area.
RectT bounds; // Inside edge of window frame.
SurfaceT *content; // Actual window contents - widgets and such.
SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing.