Minimizing and restoring works. Start of resizing.
This commit is contained in:
parent
96391b499d
commit
b6f78593e4
6 changed files with 198 additions and 98 deletions
BIN
client/assets/mouse.png
(Stored with Git LFS)
BIN
client/assets/mouse.png
(Stored with Git LFS)
Binary file not shown.
BIN
client/assets/resize.png
(Stored with Git LFS)
Normal file
BIN
client/assets/resize.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue