Scrollbars work! Thumbs work! Minor DJGPP mouse event issue fixed.

This commit is contained in:
Scott Duensing 2022-06-22 19:08:14 -05:00
parent f3cc0d5050
commit 431e4a40eb
6 changed files with 363 additions and 67 deletions

View file

@ -20,10 +20,10 @@ static void surfacePixelSet16(uint16_t x, uint16_t y, ColorT color);
static void surfacePixelSet32(uint16_t x, uint16_t y, ColorT color);
void surfaceBlit(int16_t targetX1, int16_t targetY1, int16_t width, int16_t height, SurfaceT *source) {
int16_t y;
int16_t x1 = 0;
int16_t y1 = 0;
void surfaceBlit(int16_t targetX, int16_t targetY, int16_t offsetX, int16_t offsetY, int16_t width, int16_t height, SurfaceT *source) {
int16_t i;
int16_t x = 0;
int16_t y = 0;
size_t bytes;
size_t offsetTarget;
size_t offsetSource;
@ -33,25 +33,25 @@ void surfaceBlit(int16_t targetX1, int16_t targetY1, int16_t width, int16_t heig
if (height <= 0 || height > source->height) height = source->height;
// Clip on top and left. x1 & y1 are pixel locations inside the source bitmap.
if (targetX1 < 0) x1 = -targetX1;
if (targetY1 < 0) y1 = -targetY1;
if (targetX < 0) x = -targetX;
if (targetY < 0) y = -targetY;
// Clip on right and bottom.
if (targetX1 + width > __surfaceActive->width) width -= targetX1 + width - __surfaceActive->width;
if (targetY1 + height > __surfaceActive->height) height -= targetY1 + height - __surfaceActive->height;
if (targetX + width - offsetX > __surfaceActive->width) width -= targetX + width - offsetX - __surfaceActive->width;
if (targetY + height - offsetY > __surfaceActive->height) height -= targetY + height - offsetY - __surfaceActive->height;
// Are we still on the screen?
if (x1 < 0 || y1 < 0 || width < x1 || height < y1) return;
if (x < 0 || y < 0 || width < x || height < y) return;
if (targetX1 == 0 && targetY1 == 0 && __surfaceActive->width == source->width && __surfaceActive->height == source->height) {
if (targetX == 0 && targetY == 0 && __surfaceActive->width == source->width && __surfaceActive->height == source->height) {
// Direct blit of entire surface.
memcpy(__surfaceActive->buffer.bits8, source->buffer.bits8, source->bytes);
} else {
// Blit into larger surface.
offsetTarget = (targetY1 + y1) * __surfaceActive->scanline + (targetX1 + x1) * __surfaceBytesPerPixel;
offsetSource = y1 * source->scanline + x1 * __surfaceBytesPerPixel;
bytes = (width - x1) * __surfaceBytesPerPixel;
for (y=y1; y<height; y++) {
offsetTarget = (targetY + y) * __surfaceActive->scanline + (targetX + x) * __surfaceBytesPerPixel;
offsetSource = (y + offsetY) * source->scanline + (x + offsetX) * __surfaceBytesPerPixel;
bytes = (width - x) * __surfaceBytesPerPixel;
for (i=y; i<height; i++) {
memcpy(&__surfaceActive->buffer.bits8[offsetTarget], &source->buffer.bits8[offsetSource], bytes);
offsetTarget += __surfaceActive->scanline;
offsetSource += source->scanline;

View file

@ -45,7 +45,7 @@ extern ColorT (*surfacePixelGet)(SurfaceT *surface, int16_t x, int16_t y);
extern void (*surfacePixelSet)(uint16_t x, uint16_t y, ColorT color);
void surfaceBlit(int16_t targetX1, int16_t targetY1, int16_t width, int16_t height, SurfaceT *source);
void surfaceBlit(int16_t targetX1, int16_t targetY1, int16_t offsetX, int16_t offsetY, int16_t width, int16_t height, SurfaceT *source);
void surfaceBlitWithTransparency(int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent);
void surfaceClear(ColorT color);
ColorT surfaceColorMake(uint8_t r, uint8_t g, uint8_t b);

View file

@ -3,7 +3,10 @@
#include "font.h"
#define ICON_SIZE 32
#define ICON_SIZE 32
#define WIDGET_SIZE 20
#define SCROLL_SPEED_SLOW 5 // ***TODO*** Move into GUI after we get scrollbar widgets.
#define SCROLL_SPEED_FAST 25
uint8_t __MAGIC_WINDOW = 0;
@ -15,6 +18,8 @@ static int16_t _iconCount = 0;
static void windowCache(WindowT *w);
static void windowScrollHorizontalHandler(EventT *e, WindowT *w);
static void windowScrollVerticalHandler(EventT *e, WindowT *w);
static void windowCache(WindowT *w) {
@ -29,6 +34,7 @@ static void windowCache(WindowT *w) {
int16_t ty2;
int16_t originalX;
int16_t originalY;
double d;
ColorT titleBackgroundColor;
ColorT widgetColor;
SurfaceT *target = surfaceGet();
@ -79,11 +85,11 @@ static void windowCache(WindowT *w) {
if (w->title || w->flags & WIN_CLOSE || w->flags & WIN_MAXIMIZE || w->flags & WIN_MINIMIZE) {
tx1 = x1;
tx2 = x2;
ty2 = y1 + 20;
ty2 = y1 + WIDGET_SIZE;
// Close box?
if (w->flags & WIN_CLOSE) {
tx1 += 20;
tx1 += WIDGET_SIZE;
w->close.x = x1;
w->close.y = y1;
w->close.x2 = tx1 - 1;
@ -97,10 +103,10 @@ static void windowCache(WindowT *w) {
// Maximize box?
if (w->flags & WIN_MAXIMIZE) {
tx2 -= 20;
tx2 -= WIDGET_SIZE;
w->maximize.x = tx2 + 1;
w->maximize.y = y1;
w->maximize.x2 = tx2 + 20;
w->maximize.x2 = tx2 + WIDGET_SIZE;
w->maximize.y2 = ty2 - 1;
surfaceBoxFilled(w->maximize.x + 1, w->maximize.y + 1, w->maximize.x2 - 1, w->maximize.y2 - 1, titleBackgroundColor);
surfaceLine(w->maximize.x + 4, w->maximize.y + 10, w->maximize.x + 10, w->maximize.y + 4, GUI_WHITE);
@ -114,10 +120,10 @@ static void windowCache(WindowT *w) {
// Minimize box?
if (w->flags & WIN_MINIMIZE) {
tx2 -= 20;
tx2 -= WIDGET_SIZE;
w->minimize.x = tx2 + 1;
w->minimize.y = y1;
w->minimize.x2 = tx2 + 20;
w->minimize.x2 = tx2 + WIDGET_SIZE;
w->minimize.y2 = ty2 - 1;
surfaceBoxFilled(w->minimize.x + 1, w->minimize.y + 1, w->minimize.x2 - 1, w->minimize.y2 - 1, titleBackgroundColor);
surfaceBoxHighlight(w->minimize.x + 7, w->minimize.y + 7, w->minimize.x2 - 7, w->minimize.y2 - 7, GUI_WHITE, widgetColor);
@ -133,8 +139,10 @@ static void windowCache(WindowT *w) {
w->titlebar.y2 = ty2 - 1;
surfaceBoxFilled(w->titlebar.x + 1, w->titlebar.y + 1, w->titlebar.x2 - 1, w->titlebar.y2 - 1, titleBackgroundColor);
if (w->title) {
// Prepare font. Don't allow color changes in titles.
fontSet(__guiFontVGA8x16);
fontColorSet(GUI_WHITE, titleBackgroundColor);
fontModsEnabledSet(0);
// How many characters do we have room for?
i = ((w->titlebar.x2 - w->titlebar.x) >> 3) - 2;
// Does the title fit?
@ -150,6 +158,8 @@ static void windowCache(WindowT *w) {
}
}
surfaceBoxHighlight(w->titlebar.x, w->titlebar.y, w->titlebar.x2, w->titlebar.y2, GUI_WHITE, GUI_BLACK);
y1 += WIDGET_SIZE;
} else {
w->close.x = w->close.y = w->close.x2 = w->close.y2 = 0;
w->maximize.x = w->maximize.y = w->maximize.x2 = w->maximize.y2 = 0;
@ -157,23 +167,121 @@ static void windowCache(WindowT *w) {
w->titlebar.x = w->titlebar.y = w->titlebar.x2 = w->titlebar.y2 = 0;
}
// Vertical Scroll Bar?
if (w->flags & WIN_SCROLL_V) {
w->scrollv.x2 = x2;
w->scrollv.x = w->scrollv.x2 - (WIDGET_SIZE - 1);
w->scrollv.y = y1;
w->scrollv.y2 = y2;
// Draw scroll bar.
surfaceBoxFilled(w->scrollv.x + 1, w->scrollv.y + 1, w->scrollv.x2 - 1, w->scrollv.y2 - 1, titleBackgroundColor);
surfaceBoxHighlight(w->scrollv.x, w->scrollv.y, w->scrollv.x2, w->scrollv.y2, GUI_WHITE, GUI_BLACK);
surfaceLineH(w->scrollv.x + 1, w->scrollv.x2, w->scrollv.y + (WIDGET_SIZE - 1), GUI_BLACK);
surfaceLineH(w->scrollv.x + 1, w->scrollv.x2, w->scrollv.y2 - (WIDGET_SIZE - 1), GUI_WHITE);
// Prepare font.
fontSet(__guiFontVGA8x8);
fontColorSet(widgetColor, titleBackgroundColor);
// Draw arrows.
fontRender("\x1e", w->scrollv.x + 7, w->scrollv.y + 7);
fontRender("\x1f", w->scrollv.x + 7, w->scrollv.y2 - 12);
x2 -= (WIDGET_SIZE - 1);
} else {
w->scrollv.x = w->scrollv.y = w->scrollv.x2 = w->scrollv.y2 = 0;
}
// Horizontal Scroll Bar?
if (w->flags & WIN_SCROLL_H) {
w->scrollh.x = x1;
w->scrollh.x2 = x2;
w->scrollh.y2 = y2;
w->scrollh.y = w->scrollh.y2 - (WIDGET_SIZE - 1);
// Draw scroll bar.
surfaceBoxFilled(w->scrollh.x + 1, w->scrollh.y + 1, w->scrollh.x2 - 1, w->scrollh.y2 - 1, titleBackgroundColor);
surfaceBoxHighlight(w->scrollh.x, w->scrollh.y, w->scrollh.x2, w->scrollh.y2, GUI_WHITE, GUI_BLACK);
surfaceLineV(w->scrollh.x + (WIDGET_SIZE - 1), w->scrollh.y + 1, w->scrollh.y2, GUI_BLACK);
surfaceLineV(w->scrollh.x2 - (WIDGET_SIZE - 1), w->scrollh.y + 1, w->scrollh.y2, GUI_WHITE);
// If we have both horizontal and vertical scroll bars, we need to fix a shadow.
if (w->flags & WIN_SCROLL_V) {
surfaceLineV(w->scrollh.x2 - 1, w->scrollh.y, w->scrollh.y2, GUI_BLACK);
surfaceLineV(w->scrollh.x2, w->scrollh.y, w->scrollh.y2, GUI_WHITE);
}
// Prepare font.
fontSet(__guiFontVGA8x8);
fontColorSet(widgetColor, titleBackgroundColor);
// Draw arrows.
fontRender("\x11", w->scrollh.x + 7, w->scrollh.y + 7);
fontRender("\x10", w->scrollh.x2 - 12, w->scrollh.y + 7);
y2 -= (WIDGET_SIZE - 1);
} else {
w->scrollh.x = w->scrollh.y = w->scrollh.x2 = w->scrollh.y2 = 0;
}
// Find content area.
y1 += 20;
w->bounds.x = x1;
w->bounds.y = y1;
w->bounds.x2 = x2;
w->bounds.y2 = y2;
// Do we have content yet?
if (w->content) {
// Vertical Scroll Bar Thumb?
if (w->flags & WIN_SCROLL_V) {
// Distance between arrow buttons on scroll bar.
i = w->scrollv.y2 - w->scrollv.y - (WIDGET_SIZE * 2 - 2) - 2;
// Percentage to scale content height to scroll bar height.
d = (double)i / (double)surfaceHeightGet(w->content);
// Find position and size of thumb.
w->thumbv.x = w->scrollv.x + 1;
w->thumbv.x2 = w->scrollv.x2 - 1;
w->thumbv.y = w->scrollv.y + WIDGET_SIZE + (w->offset.y * d);
w->thumbv.y2 = w->thumbv.y + ((w->bounds.y2 - w->bounds.y) * d);
// Clamp overflow due to doubles and my off-by-one brain.
if (w->thumbv.y2 >= w->thumbv.y + i - 1) w->thumbv.y2 = w->thumbv.y + i - 1;
// Draw thumb.
surfaceBoxFilled(w->thumbv.x + 1, w->thumbv.y + 1, w->thumbv.x2 - 1, w->thumbv.y2 - 1, widgetColor);
surfaceBoxHighlight(w->thumbv.x, w->thumbv.y, w->thumbv.x2, w->thumbv.y2, GUI_WHITE, GUI_BLACK);
} else {
w->thumbv.x = w->thumbv.y = w->thumbv.x2 = w->thumbv.y2 = 0;
}
// Horizontal Scroll Bar Thumb?
if (w->flags & WIN_SCROLL_H) {
// Distance between arrow buttons on scroll bar.
i = w->scrollh.x2 - w->scrollh.x - (WIDGET_SIZE * 2 - 2) - 2;
// Percentage to scale content width to scroll bar width.
d = (double)i / (double)surfaceWidthGet(w->content);
// Find position and size of thumb.
w->thumbh.x = w->scrollh.x + WIDGET_SIZE + (w->offset.x * d);
w->thumbh.x2 = w->thumbh.x + ((w->bounds.x2 - w->bounds.x) * d);
w->thumbh.y = w->scrollh.y + 1;
w->thumbh.y2 = w->scrollh.y2 - 1;
// Clamp overflow due to doubles and my off-by-one brain.
if (w->thumbh.x2 >= w->thumbh.x + i - 1) w->thumbh.x2 = w->thumbh.x + i - 1;
// Draw thumb.
surfaceBoxFilled(w->thumbh.x + 1, w->thumbh.y + 1, w->thumbh.x2 - 1, w->thumbh.y2 - 1, widgetColor);
surfaceBoxHighlight(w->thumbh.x, w->thumbh.y, w->thumbh.x2, w->thumbh.y2, GUI_WHITE, GUI_BLACK);
} else {
w->thumbh.x = w->thumbh.y = w->thumbh.x2 = w->thumbh.y2 = 0;
}
} else { // Do we have content yet?
w->thumbv.x = w->thumbv.y = w->thumbv.x2 = w->thumbv.y2 = 0;
w->thumbh.x = w->thumbh.y = w->thumbh.x2 = w->thumbh.y2 = 0;
}
// Resize handle.
if (w->flags & WIN_RESIZE) {
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;
w->resize1.y = w->resize1.y2 - (WIDGET_SIZE + 5);
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.x = w->resize2.x2 - (WIDGET_SIZE + 5);
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);
@ -184,10 +292,10 @@ static void windowCache(WindowT *w) {
}
// Blit contents.
if (w->content) surfaceBlit(w->bounds.x, w->bounds.y, w->bounds.x2 - w->bounds.x, w->bounds.y2 - w->bounds.y, w->content);
if (w->content) surfaceBlit(w->bounds.x, w->bounds.y, w->offset.x, w->offset.y, w->bounds.x2 - w->bounds.x, w->bounds.y2 - w->bounds.y, w->content);
// Fixup all the widget coordinates.
windowMoveTo(w, originalX, originalY);
windowMove(w, originalX, originalY);
surfaceSet(target);
}
@ -212,12 +320,17 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
//***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++);
windowCache(win);
width = win->bounds.x2 - win->bounds.x;
height = win->bounds.y2 - win->bounds.y;
guiWidgetDirtySet(W(win), 1);
sprintf(name, "back%d.png", image);
win->content = imageLoad(name);
win->flags |= WIN_RESIZE;
if (image == 3) {
win->offset.x = 100;//(surfaceWidthGet(win->content) - width) * 0.5;
win->offset.y = 100;//(surfaceHeightGet(win->content) - height) * 0.5;
}
image++;
/*
// If the window is resizable, we need to get two more arguments for the content size.
if (win->flags & WIN_RESIZE) {
@ -239,10 +352,6 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
surfaceSet(t);
*/
// Do we need scrollbars?
if (width > win->bounds.x2 - win->bounds.x) win->flags |= WIN_SCROLL_H;
if (height > win->bounds.y2 - win->bounds.y) win->flags |= WIN_SCROLL_V;
// Add to window list.
arrput(_windowList, win);
@ -350,6 +459,7 @@ void windowMaximizeRestore(WindowT *win) {
// Restore to previous size.
win->flags &= ~WIN_IS_MAX;
win->base.r = win->restore;
win->offset = win->restoreOffset;
} else { // Maximized?
@ -357,7 +467,12 @@ void windowMaximizeRestore(WindowT *win) {
win->flags |= WIN_IS_MAX;
// Remember current size and position.
win->restore = win->base.r;
win->restore = win->base.r;
win->restoreOffset = win->offset;
// Scroll contents to home.
win->offset.x = 0;
win->offset.y = 0;
// Expand to full contents.
win->base.r.w = (win->base.r.w - (win->bounds.x2 - win->bounds.x) + surfaceWidthGet(win->content));
@ -406,7 +521,7 @@ void windowMinimize(WindowT *win) {
}
void windowMoveTo(WindowT *w, uint16_t x, uint16_t y) {
void windowMove(WindowT *w, uint16_t x, uint16_t y) {
int16_t dx = x - w->base.r.x;
int16_t dy = y - w->base.r.y;
@ -442,6 +557,28 @@ void windowMoveTo(WindowT *w, uint16_t x, uint16_t y) {
w->titlebar.y2 += dy;
}
if (w->flags & WIN_SCROLL_V) {
w->scrollv.x += dx;
w->scrollv.y += dy;
w->scrollv.x2 += dx;
w->scrollv.y2 += dy;
w->thumbv.x += dx;
w->thumbv.y += dy;
w->thumbv.x2 += dx;
w->thumbv.y2 += dy;
}
if (w->flags & WIN_SCROLL_H) {
w->scrollh.x += dx;
w->scrollh.y += dy;
w->scrollh.x2 += dx;
w->scrollh.y2 += dy;
w->thumbh.x += dx;
w->thumbh.y += dy;
w->thumbh.x2 += dx;
w->thumbh.y2 += dy;
}
if (w->flags & WIN_RESIZE) {
w->resize1.x += dx;
w->resize1.y += dy;
@ -500,7 +637,7 @@ void windowPaint(struct WidgetS *widget, ...) {
_iconCount++;
} else {
// By now we have a valid cached window. Blit it.
surfaceBlit(w->base.r.x, w->base.r.y, 0, 0, w->cached);
surfaceBlit(w->base.r.x, w->base.r.y, 0, 0, 0, 0, w->cached);
}
}
@ -520,15 +657,33 @@ RegisterT *windowRegister(uint8_t magic) {
}
void windowResizeTo(WindowT *win, uint16_t width, uint16_t height) {
void windowResize(WindowT *win, uint16_t width, uint16_t height) {
int16_t delta;
// Too small?
if (width < 95) width = 95;
if (height < 80) height = 80;
if (width < (WIDGET_SIZE * 4) + 15) width = (WIDGET_SIZE * 4) + 15;
if (height < (WIDGET_SIZE * 4) + 15) height = (WIDGET_SIZE * 4) + 15;
// Too big?
if (win->bounds.w - win->bounds.x + (width - win->base.r.w) > surfaceWidthGet(win->content)) width = (win->base.r.w - (win->bounds.x2 - win->bounds.x) + surfaceWidthGet(win->content));
if (win->bounds.h - win->bounds.y + (height - win->base.r.h) > surfaceHeightGet(win->content)) height = (win->base.r.h - (win->bounds.y2 - win->bounds.y) + surfaceHeightGet(win->content));
if (win->bounds.w - win->bounds.x + (width - win->base.r.w) + win->offset.x > surfaceWidthGet(win->content)) {
// Do we have room to scroll content into view?
if (win->offset.x > 0) {
delta = width - win->base.r.w;
if (delta > win->offset.x) delta = win->offset.x;
win->offset.x -= delta;
}
width = (win->base.r.w - (win->bounds.x2 - win->bounds.x) - win->offset.x + surfaceWidthGet(win->content));
}
if (win->bounds.h - win->bounds.y + (height - win->base.r.h) + win->offset.y > surfaceHeightGet(win->content)) {
// Do we have room to scroll content into view?
if (win->offset.y > 0) {
delta = height - win->base.r.h;
if (delta > win->offset.y) delta = win->offset.y;
win->offset.y -= delta;
}
height = (win->base.r.h - (win->bounds.y2 - win->bounds.y) - win->offset.y + surfaceHeightGet(win->content));
}
// Did the size change?
if (win->base.r.w != width || win->base.r.h !=height) {
@ -543,6 +698,102 @@ void windowResizeTo(WindowT *win, uint16_t width, uint16_t height) {
}
static void windowScrollHorizontalHandler(EventT *e, WindowT *w) {
// Clicking in left arrow?
if (e->x <= w->scrollh.x + WIDGET_SIZE) {
// Move content left.
w->offset.x -= SCROLL_SPEED_SLOW;
// Clip.
if (w->offset.x < 0) w->offset.x = 0;
// Update.
windowCache(w);
return;
}
// Clicking in right arrow?
if (e->x >= w->scrollh.x2 - WIDGET_SIZE) {
// Move content right.
w->offset.x += SCROLL_SPEED_SLOW;
// Clip.
if (w->offset.x > surfaceWidthGet(w->content) - (w->bounds.x2 - w->bounds.x)) w->offset.x = surfaceWidthGet(w->content) - (w->bounds.x2 - w->bounds.x);
// Update.
windowCache(w);
return;
}
// Clicking left of thumb? Also fakes dragging.
if (e->x < w->thumbh.x) {
// Move content left.
w->offset.x -= SCROLL_SPEED_FAST;
// Clip.
if (w->offset.x < 0) w->offset.x = 0;
// Update.
windowCache(w);
return;
}
// Clicking right of thumb? Also fakes dragging.
if (e->x > w->thumbh.x2) {
// Move content right.
w->offset.x += SCROLL_SPEED_FAST;
// Clip.
if (w->offset.x > surfaceWidthGet(w->content) - (w->bounds.x2 - w->bounds.x)) w->offset.x = surfaceWidthGet(w->content) - (w->bounds.x2 - w->bounds.x);
// Update.
windowCache(w);
return;
}
}
static void windowScrollVerticalHandler(EventT *e, WindowT *w) {
// Clicking in up arrow?
if (e->y <= w->scrollv.y + WIDGET_SIZE) {
// Move content up.
w->offset.y -= SCROLL_SPEED_SLOW;
// Clip.
if (w->offset.y < 0) w->offset.y = 0;
// Update.
windowCache(w);
return;
}
// Clicking in down arrow?
if (e->y >= w->scrollv.y2 - WIDGET_SIZE) {
// Move content down.
w->offset.y += SCROLL_SPEED_SLOW;
// Clip.
if (w->offset.y > surfaceHeightGet(w->content) - (w->bounds.y2 - w->bounds.y)) w->offset.y = surfaceHeightGet(w->content) - (w->bounds.y2 - w->bounds.y);
// Update.
windowCache(w);
return;
}
// Clicking above thumb? Also fakes dragging.
if (e->y < w->thumbv.y) {
// Move content up.
w->offset.y -= SCROLL_SPEED_FAST;
// Clip.
if (w->offset.y < 0) w->offset.y = 0;
// Update.
windowCache(w);
return;
}
// Clicking below thumb? Also fakes dragging.
if (e->y > w->thumbv.y2) {
// Move content down.
w->offset.y += SCROLL_SPEED_FAST;
// Clip.
if (w->offset.y > surfaceHeightGet(w->content) - (w->bounds.y2 - w->bounds.y)) w->offset.y = surfaceHeightGet(w->content) - (w->bounds.y2 - w->bounds.y);
// Update.
windowCache(w);
return;
}
}
void wmShutdown(void) {
while (arrlen(_windowList) > 0) {
windowDestroy((WidgetT *)_windowList[0]);
@ -589,6 +840,9 @@ void wmUpdate(EventT *event) {
if (win) {
x2 = win->base.r.x + win->base.r.w - 1;
y2 = win->base.r.y + win->base.r.h - 1;
} else {
x2 = 0;
y2 = 0;
}
// Wrap left button processing with a 'for' so we can 'break' out of it.
@ -609,7 +863,7 @@ void wmUpdate(EventT *event) {
if (event->buttons & BUTTON_LEFT) {
/*
// DEBUG - draw active regions. ***TODO*** No resize grabber here.
// DEBUG - draw active regions.
surfaceSet(__guiBackBuffer);
surfaceBox(win->base.r.x, win->base.r.y, x2, y2, GUI_YELLOW);
surfaceBox(win->bounds.x, win->bounds.y, win->bounds.x2, win->bounds.y2, GUI_CYAN);
@ -617,13 +871,15 @@ void wmUpdate(EventT *event) {
surfaceBox(win->titlebar.x, win->titlebar.y, win->titlebar.x2, win->titlebar.y2, GUI_LIGHTCYAN);
surfaceBox(win->minimize.x, win->minimize.y, win->minimize.x2, win->minimize.y2, GUI_LIGHTGREEN);
surfaceBox(win->maximize.x, win->maximize.y, win->maximize.x2, win->maximize.y2, GUI_RED);
surfaceBox(win->scrollv.x, win->scrollv.y, win->scrollv.x2, win->scrollv.y2, GUI_BLUE);
surfaceBox(win->scrollh.x, win->scrollh.y, win->scrollh.x2, win->scrollh.y2, GUI_BROWN);
*/
// Are we currently dragging?
if (dragging) {
// Move window to new mouse location.
windowMoveTo(win, event->x - dragOffset.x, event->y - dragOffset.y);
windowMove(win, event->x - dragOffset.x, event->y - dragOffset.y);
break;
} else { // Dragging.
@ -632,7 +888,7 @@ void wmUpdate(EventT *event) {
// If they try to resize outside the window bounds, cancel it.
if (event->x < win->base.r.x || event->y < win->base.r.y) break;
// Resize it.
windowResizeTo(win, event->x - resizeOffset.x, event->y - resizeOffset.y);
windowResize(win, event->x - resizeOffset.x, event->y - resizeOffset.y);
break;
} else { // Resizing.
@ -681,6 +937,18 @@ void wmUpdate(EventT *event) {
break;
}
// Are we inside the vertical scroll bar? Does not include frame on purpose.
if (win->flags & WIN_SCROLL_V &&event->x < win->scrollv.x2 && event->x > win->scrollv.x && event->y < win->scrollv.y2 && event->y > win->scrollv.y) {
windowScrollVerticalHandler(event, win);
break;
}
// Are we inside the horizontal scroll bar? Does not include frame on purpose.
if (win->flags & WIN_SCROLL_H &&event->x < win->scrollh.x2 && event->x > win->scrollh.x && event->y < win->scrollh.y2 && event->y > win->scrollh.y) {
windowScrollHorizontalHandler(event, win);
break;
}
} else { // On topmost window.
// Not over topmost window. Search backwards to find first window we're inside.
@ -734,9 +1002,24 @@ void wmUpdate(EventT *event) {
}
} // Minimized windows?
}
}
} // Button just went down.
} else { // Button just went down / button being held down.
// Are we inside the vertical scroll bar? Does not include frame on purpose.
if (win->flags & WIN_SCROLL_V &&event->x < win->scrollv.x2 && event->x > win->scrollv.x && event->y < win->scrollv.y2 && event->y > win->scrollv.y) {
windowScrollVerticalHandler(event, win);
break;
}
// Are we inside the horizontal scroll bar? Does not include frame on purpose.
if (win->flags & WIN_SCROLL_H &&event->x < win->scrollh.x2 && event->x > win->scrollh.x && event->y < win->scrollh.y2 && event->y > win->scrollh.y) {
windowScrollHorizontalHandler(event, win);
break;
}
} // Left button held down.
} // Resizing.
} // Dragging.

View file

@ -15,21 +15,29 @@
#define WIN_IS_ICON 64
#define WIN_IS_MAX 128
#define WIN_STANDARD (WIN_CLOSE | WIN_MAXIMIZE | WIN_MINIMIZE | WIN_RESIZE | WIN_SCROLL_V | WIN_SCROLL_H)
typedef struct WindowS {
WidgetT base; // Required by all widgets.
char *title; // Title of window.
uint8_t flags; // Window flags (see defines above).
RectT close; // Coordinates of close box, if any.
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.
RectT restore; // Size of window if they restore from maximized.
SurfaceT *content; // Actual window contents - widgets and such.
SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing.
WidgetT base; // Required by all widgets.
char *title; // Title of window.
uint8_t flags; // Window flags (see defines above).
RectT close; // Coordinates of close box, if any.
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 scrollv; // Vertical scroll bar.
RectT scrollh; // Horizontal scroll bar.
RectT thumbv; // Vertical scroll bar thumb.
RectT thumbh; // Horizontal scroll bar thumb.
RectT bounds; // Inside edge of window frame.
RectT restore; // Size of window if they restore from maximized.
PointT restoreOffset; // Scroll position if they restore from maximized.
PointT offset; // Content scroll offset in window.
SurfaceT *content; // Actual window contents - widgets and such.
SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing.
} WindowT;
@ -41,10 +49,10 @@ void windowDestroy(struct WidgetS *widget, ...);
void windowFocusSet(WindowT *win);
void windowMaximizeRestore(WindowT *win);
void windowMinimize(WindowT *win);
void windowMoveTo(WindowT *win, uint16_t x, uint16_t y);
void windowMove(WindowT *win, uint16_t x, uint16_t y);
void windowPaint(struct WidgetS *widget, ...);
RegisterT *windowRegister(uint8_t magic);
void windowResizeTo(WindowT *win, uint16_t width, uint16_t height);
void windowResize(WindowT *win, uint16_t width, uint16_t height);
void wmShutdown(void);

View file

@ -14,7 +14,7 @@ int main(int argc, char *argv[]) {
if (guiStartup(800, 600, 16) == SUCCESS) {
for (i=1; i<4; i++) {
sprintf(title, "Testing %d", i);
windowCreate(i * 50, i * 50, 300, 200, title, WIN_CLOSE | WIN_MAXIMIZE | WIN_MINIMIZE);
windowCreate(i * 50, i * 50, 300, 200, title, WIN_STANDARD);
}
guiRun();
guiShutdown();

View file

@ -187,8 +187,11 @@ void platformEventGet(EventT *event) {
int16_t meta = bioskey(KEYBOARD_META_EXTENDED);
int16_t key = 0;
union REGS regs;
static int32_t lastX = 0;
static int32_t lastY = 0;
static int32_t lastX = 0;
static int32_t lastY = 0;
static int32_t lastButtons = 0;
event->buttons = lastButtons;
// Read mouse motion.
regs.x.ax = MOUSE_GETMOTION;
@ -273,6 +276,8 @@ void platformEventGet(EventT *event) {
if ((meta & (1 << KEY_META_CONTROL)) + (meta & (1 << KEY_META_CONTROL_LEFT)) + (meta & (1 << KEY_META_CONTROL_RIGHT))) event->kbstat |= META_CTRL;
if ((meta & (1 << KEY_META_SHIFT_LEFT)) + (meta & (1 << KEY_META_SHIFT_RIGHT))) event->kbstat |= META_SHIFT;
}
lastButtons = event->buttons;
}