Scrollbars work! Thumbs work! Minor DJGPP mouse event issue fixed.
This commit is contained in:
parent
f3cc0d5050
commit
431e4a40eb
6 changed files with 363 additions and 67 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue