I hate scrollbars.
This commit is contained in:
parent
9433a63c1f
commit
814a9ef705
11 changed files with 149 additions and 97 deletions
|
@ -315,7 +315,7 @@ void widgetMove(WidgetT *widget, int16_t x, int16_t y) {
|
|||
|
||||
|
||||
void widgetPaintManually(WidgetT *widget, int16_t x, int16_t y) {
|
||||
RectT r = widget->r;
|
||||
RectWT r = widget->r;
|
||||
|
||||
widgetDirtySet(widget, 1);
|
||||
widget->r.x = x;
|
||||
|
|
|
@ -57,18 +57,19 @@ typedef struct PointS {
|
|||
} PointT;
|
||||
|
||||
typedef struct RectS {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
union {
|
||||
int16_t w;
|
||||
int16_t x2;
|
||||
};
|
||||
union {
|
||||
int16_t h;
|
||||
int16_t y2;
|
||||
};
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t x2;
|
||||
int16_t y2;
|
||||
} RectT;
|
||||
|
||||
typedef struct RectWS {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t w;
|
||||
int16_t h;
|
||||
} RectWT;
|
||||
|
||||
typedef struct RegisterS {
|
||||
char *widgetName; // Text name of widget.
|
||||
ClickHandlerT click; // Click handler.
|
||||
|
@ -79,7 +80,7 @@ typedef struct RegisterS {
|
|||
|
||||
typedef struct WidgetS {
|
||||
uint8_t magic; // Magic ID of widget. Must be first!
|
||||
RectT r; // Outer bounds of widget. NOTE: USES WIDTH/HEIGHT, NOT X2/Y2!
|
||||
RectWT r; // Outer bounds of widget. NOTE: USES WIDTH/HEIGHT, NOT X2/Y2!
|
||||
RegisterT *reg; // Registration information.
|
||||
void *data; // Pointer to arbitrary data for user.
|
||||
uint16_t flags; // Widget flags (see defines above).
|
||||
|
|
|
@ -109,9 +109,9 @@ static void buttonPaint(struct WidgetS *widget, ...) {
|
|||
if (widgetDirtyGet(widget)) {
|
||||
widgetDirtySet(widget, 0);
|
||||
// Paint button.
|
||||
surfaceBoxHighlight(b->base.r.x, b->base.r.y, b->base.r.x + b->base.r.x2 - 1, b->base.r.y + b->base.r.y2 - 1, h, s);
|
||||
surfaceBoxHighlight(b->base.r.x + 1, b->base.r.y + 1, b->base.r.x + b->base.r.x2 - 2, b->base.r.y + b->base.r.y2 - 2, h, s);
|
||||
surfaceBoxFilled(b->base.r.x + 2, b->base.r.y + 2, b->base.r.x + b->base.r.x2 - 3, b->base.r.y + b->base.r.y2 - 3, GUI_LIGHTGRAY);
|
||||
surfaceBoxHighlight(b->base.r.x, b->base.r.y, b->base.r.x + b->base.r.w - 1, b->base.r.y + b->base.r.h - 1, h, s);
|
||||
surfaceBoxHighlight(b->base.r.x + 1, b->base.r.y + 1, b->base.r.x + b->base.r.w - 2, b->base.r.y + b->base.r.h - 2, h, s);
|
||||
surfaceBoxFilled(b->base.r.x + 2, b->base.r.y + 2, b->base.r.x + b->base.r.w - 3, b->base.r.y + b->base.r.h - 3, GUI_LIGHTGRAY);
|
||||
// Paint label.
|
||||
widgetPaintManually(W(b->label), b->base.r.x + b->offset.x + b->isPressed, b->base.r.y + b->offset.y + b->isPressed);
|
||||
}
|
||||
|
|
|
@ -151,7 +151,8 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
widgetColor = GUI_DARKGRAY;
|
||||
}
|
||||
// Find coordinates.
|
||||
r = h->base.r;
|
||||
r.x = h->base.r.x;
|
||||
r.y = h->base.r.y;
|
||||
r.x2 = r.x + h->base.r.w - 1;
|
||||
r.y2 = r.y + h->base.r.h - 1;
|
||||
// Paint scrollbar.
|
||||
|
@ -162,14 +163,6 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
// Prepare font.
|
||||
fontSet(__guiFontVGA8x8);
|
||||
fontColorSet(widgetColor, scrollBackgroundColor);
|
||||
// ***TODO***
|
||||
/*
|
||||
// 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);
|
||||
}
|
||||
*/
|
||||
// Draw arrows.
|
||||
fontRender("\x11", r.x + 7, r.y + 7);
|
||||
fontRender("\x10", r.x2 - 12, r.y + 7);
|
||||
|
@ -183,7 +176,7 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
h->thumb.y = r.y + 1;
|
||||
h->thumb.y2 = r.y2 - 1;
|
||||
// Clamp overflow due to doubles and my off-by-one brain.
|
||||
if (h->thumb.x2 >= h->thumb.x + i - 1) h->thumb.x2 = h->thumb.x + i - 1;
|
||||
if (h->thumb.x2 >= r.x + GADGET_SIZE + i - 1) h->thumb.x2 = r.x + GADGET_SIZE + i - 1;
|
||||
// Draw thumb.
|
||||
surfaceBoxFilled(h->thumb.x + 1, h->thumb.y + 1, h->thumb.x2 - 1, h->thumb.y2 - 1, GUI_LIGHTGRAY);
|
||||
surfaceBoxHighlight(h->thumb.x, h->thumb.y, h->thumb.x2, h->thumb.y2, GUI_WHITE, GUI_BLACK);
|
||||
|
|
|
@ -53,30 +53,33 @@ static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint
|
|||
|
||||
|
||||
// Passing "flags" as a default int provides proper alignment for the following va_args list.
|
||||
ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, int16_t totalHeight, int flags, ...) {
|
||||
ScrollableT *scrollableCreate(int16_t visibleWidth, int16_t visibleHeight, int16_t totalWidth, int16_t totalHeight, int flags, ...) {
|
||||
ScrollableT *s = NULL;
|
||||
SurfaceT *t = surfaceGet();
|
||||
int16_t w = 0;
|
||||
|
||||
NEW(ScrollableT, s);
|
||||
memset(s, 0, sizeof(ScrollableT));
|
||||
|
||||
widgetBaseSet(W(s), __MAGIC_SCROLLABLE, width, height);
|
||||
widgetBaseSet(W(s), __MAGIC_SCROLLABLE, visibleWidth, visibleHeight);
|
||||
|
||||
s->original.x = width;
|
||||
s->original.y = height;
|
||||
// Remember the original size of the visible area we're painting into because we're going to resize the widget to make room for scroll bars.
|
||||
s->original.x = visibleWidth;
|
||||
s->original.y = visibleHeight;
|
||||
|
||||
logWrite("scrollableCreate: %dx%d\n", s->original.x, s->original.y);
|
||||
|
||||
// Set up desired scroll bars.
|
||||
s->flags = flags;
|
||||
if (s->flags & SCROLLABLE_SCROLL_V) {
|
||||
// Vertical scroll bar.
|
||||
s->flags |= SCROLLABLE_NOT_SETUP;
|
||||
s->scrollv = vscrollCreate(height, scrollableClickHandler, s);
|
||||
s->scrollv = vscrollCreate(visibleHeight, scrollableClickHandler, s);
|
||||
vscrollRangeSet(s->scrollv, 0, totalHeight- 1);
|
||||
w = s->scrollv->base.r.w; // Used when creating horizontal scroll bar below.
|
||||
}
|
||||
if (s->flags & SCROLLABLE_SCROLL_H) {
|
||||
// Horizontal scroll bar.
|
||||
s->flags |= SCROLLABLE_NOT_SETUP;
|
||||
s->scrollh = hscrollCreate(width - w, scrollableClickHandler, s);
|
||||
s->scrollh = hscrollCreate(visibleWidth, scrollableClickHandler, s);
|
||||
hscrollRangeSet(s->scrollh, 0, totalWidth - 1);
|
||||
}
|
||||
|
||||
|
@ -110,38 +113,34 @@ static void scrollableDestroy(struct WidgetS *widget, ...) {
|
|||
|
||||
|
||||
static void scrollableFixupSizes(ScrollableT *s) {
|
||||
int16_t w = 0;
|
||||
|
||||
// Vertical scrollbar.
|
||||
if (s->scrollv) {
|
||||
// Position for vertical scrollbar.
|
||||
s->sizes.x = s->original.x - s->scrollv->base.r.w;
|
||||
// Position for vertical scrollbar. Also used as width of area to blit.
|
||||
s->position.x = s->original.x - s->scrollv->base.r.w + 1;
|
||||
// Make scroll area smaller to make room for scrollbar.
|
||||
s->base.r.w = s->original.x - s->scrollv->base.r.w;
|
||||
// Resize vertical scrollbar.
|
||||
vscrollHeightSet(s->scrollv, s->original.y);
|
||||
vscrollHeightSet(s->scrollv, s->original.y - (s->scrollh ? s->scrollh->base.r.h - 1 : 0));
|
||||
// Position vertical scrollbar.
|
||||
widgetMove(W(s->scrollv), s->base.r.x + s->sizes.x, s->base.r.y);
|
||||
// Used when positioning vertical scrollbar below.
|
||||
w = s->scrollv->base.r.w;
|
||||
widgetMove(W(s->scrollv), s->base.r.x + s->position.x, s->base.r.y);
|
||||
} else {
|
||||
// No vertical scrollbar. Set this to a non-zero value.
|
||||
s->sizes.x = s->base.r.w;
|
||||
// No vertical scrollbar. Set this to width of scroll area.
|
||||
s->position.x = s->base.r.w;
|
||||
}
|
||||
|
||||
// Horizontal scrollbar.
|
||||
if (s->scrollh) {
|
||||
// Position for horizontal scrollbar.
|
||||
s->sizes.y = s->original.y - s->scrollh->base.r.h;
|
||||
// Position for horizontal scrollbar. Also used as height of area to blit.
|
||||
s->position.y = s->original.y - s->scrollh->base.r.h + 1;
|
||||
// Make scroll area smaller to make room for scrollbar.
|
||||
s->base.r.h = s->original.y - s->scrollh->base.r.h;
|
||||
// Resize horizontal scrollbar.
|
||||
hscrollWidthSet(s->scrollh, s->original.x - w);
|
||||
hscrollWidthSet(s->scrollh, s->original.x - - (s->scrollv ? s->scrollv->base.r.w - 1: 0));
|
||||
// Position horizontal scrollbar.
|
||||
widgetMove(W(s->scrollh), s->base.r.x, s->base.r.y + s->sizes.y);
|
||||
widgetMove(W(s->scrollh), s->base.r.x, s->base.r.y + s->position.y);
|
||||
} else {
|
||||
// No horizontal scrollbar. Set this to a non-zero value.
|
||||
s->sizes.y = s->base.r.h;
|
||||
// No horizontal scrollbar. Set this to height of scroll area.
|
||||
s->position.y = s->base.r.h;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,11 +166,11 @@ static void scrollablePaint(struct WidgetS *widget, ...) {
|
|||
scrollableFixupSizes(s);
|
||||
if (s->scrollh) {
|
||||
if (s->base.flags & WIDGET_IS_WINDOW) s->scrollh->base.flags |= WIDGET_IS_WINDOW;
|
||||
widgetAdd(s->base.parent, s->base.r.x, s->base.r.y + s->sizes.y, W(s->scrollh));
|
||||
widgetAdd(s->base.parent, s->base.r.x, s->base.r.y + s->position.y, W(s->scrollh));
|
||||
}
|
||||
if (s->scrollv) {
|
||||
if (s->base.flags & WIDGET_IS_WINDOW) s->scrollv->base.flags |= WIDGET_IS_WINDOW;
|
||||
widgetAdd(s->base.parent, s->base.r.x + s->sizes.x, s->base.r.y, W(s->scrollv));
|
||||
widgetAdd(s->base.parent, s->base.r.x + s->position.x, s->base.r.y, W(s->scrollv));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,6 +190,7 @@ static void scrollablePaint(struct WidgetS *widget, ...) {
|
|||
s->base.r.y = o.y;
|
||||
|
||||
// Blit.
|
||||
/*
|
||||
// if ((s->offset.x + s->sizes.x > surfaceWidthGet(s->area)) || (s->offset.y + s->sizes.y > surfaceHeightGet(s->area))) {
|
||||
logWrite("%dx%d %dx%d-%dx%d %dx%d %dx%d %d %d\n",
|
||||
s->base.r.x, s->base.r.y,
|
||||
|
@ -200,7 +200,8 @@ static void scrollablePaint(struct WidgetS *widget, ...) {
|
|||
s->offset.x + s->sizes.x, s->offset.y + s->sizes.y,
|
||||
hscrollValueGet(s->scrollh), vscrollValueGet(s->scrollv));
|
||||
// }
|
||||
surfaceBlit(s->base.r.x, s->base.r.y, s->offset.x, s->offset.y, s->sizes.x, s->sizes.y, s->area);
|
||||
*/
|
||||
surfaceBlit(s->base.r.x, s->base.r.y, s->offset.x, s->offset.y, s->position.x, s->position.y, s->area);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct ScrollableS {
|
|||
SurfaceT *area; // Scrollable area buffer.
|
||||
HscrollT *scrollh; // Horizontal scroll bar.
|
||||
VscrollT *scrollv; // Vertical scroll bar.
|
||||
PointT sizes; // Scroll bar width and height info.
|
||||
PointT position; // Horizontan and Veritcal Scroll bar X and Y positions. Also used as area to blit.
|
||||
PointT original; // Original size of widget before being resized to make room for scollbars.
|
||||
uint8_t flags; // Flag bits.
|
||||
} ScrollableT;
|
||||
|
@ -55,7 +55,7 @@ typedef struct ScrollableS {
|
|||
extern uint8_t __MAGIC_SCROLLABLE; // Magic ID assigned to us from the GUI.
|
||||
|
||||
|
||||
ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, int16_t totalHeight, int flags, ...);
|
||||
ScrollableT *scrollableCreate(int16_t visibleWidth, int16_t visibleHeight, int16_t totalWidth, int16_t totalHeight, int flags, ...);
|
||||
void scrollableHeightSet(ScrollableT *scroll, int16_t h);
|
||||
RegisterT *scrollableRegister(uint8_t magic);
|
||||
void scrollableWidthSet(ScrollableT *scroll, int16_t w);
|
||||
|
|
|
@ -35,10 +35,11 @@ uint8_t __MAGIC_VSCROLL = 0;
|
|||
static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
|
||||
static void vscrollDestroy(struct WidgetS *widget, ...);
|
||||
static void vscrollPaint(struct WidgetS *widget, ...);
|
||||
static void vscrollRecalculate(VscrollT *v);
|
||||
|
||||
|
||||
static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
|
||||
VscrollT *v = (VscrollT *)widget;
|
||||
VscrollT *v = (VscrollT *)widget;
|
||||
|
||||
(void)data;
|
||||
|
||||
|
@ -47,7 +48,7 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
// Move content up.
|
||||
v->value -= SCROLL_SPEED_SLOW;
|
||||
// Clip.
|
||||
if (v->value < v->min) v->value = v->min;
|
||||
if (v->value < 0) v->value = 0;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
|
@ -60,8 +61,7 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
// Move content down.
|
||||
v->value += SCROLL_SPEED_SLOW;
|
||||
// Clip.
|
||||
logWrite("%d > %d - %d = %d\n", v->value, v->max, v->base.r.h, v->max - v->base.r.h);
|
||||
if (v->value > v->max - v->base.r.h) v->value = v->max - v->base.r.h;
|
||||
if (v->value > v->maxValue) v->value = v->maxValue;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
|
@ -69,6 +69,7 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// Clicking above thumb? Also fakes dragging.
|
||||
if (y < v->thumb.y) {
|
||||
// Move content up.
|
||||
|
@ -94,6 +95,7 @@ static void vscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
if (v->handler) v->handler(widget, x, y, event, v->base.data);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,7 +130,6 @@ VscrollT *vscrollCreate(int16_t h, ClickHandlerT handler, void *data, ...) {
|
|||
|
||||
static void vscrollDestroy(struct WidgetS *widget, ...) {
|
||||
VscrollT *v = (VscrollT *)widget;
|
||||
|
||||
DEL(v);
|
||||
}
|
||||
|
||||
|
@ -136,9 +137,9 @@ static void vscrollDestroy(struct WidgetS *widget, ...) {
|
|||
void vscrollHeightSet(VscrollT *vscroll, int16_t h) {
|
||||
// Make sure it's at least tall enough to draw.
|
||||
if (h < GADGET_SIZE * 3) h = GADGET_SIZE * 3;
|
||||
|
||||
vscroll->base.r.h = h;
|
||||
|
||||
// This doesn't check that you haven't set some insane value for the height. Up to caller.
|
||||
vscrollRecalculate(vscroll);
|
||||
widgetDirtySet(W(vscroll), 1);
|
||||
}
|
||||
|
||||
|
@ -148,8 +149,6 @@ static void vscrollPaint(struct WidgetS *widget, ...) {
|
|||
ColorT scrollBackgroundColor;
|
||||
ColorT widgetColor;
|
||||
RectT r;
|
||||
int16_t i;
|
||||
double d;
|
||||
|
||||
if (widgetDirtyGet(widget)) {
|
||||
widgetDirtySet(widget, 0);
|
||||
|
@ -161,8 +160,11 @@ static void vscrollPaint(struct WidgetS *widget, ...) {
|
|||
scrollBackgroundColor = GUI_LIGHTGRAY;
|
||||
widgetColor = GUI_DARKGRAY;
|
||||
}
|
||||
// Find coordinates.
|
||||
r = v->base.r;
|
||||
// Do the math.
|
||||
vscrollRecalculate(v);
|
||||
// Find coordinates to draw scrollbar.
|
||||
r.x = v->base.r.x;
|
||||
r.y = v->base.r.y;
|
||||
r.x2 = r.x + v->base.r.w - 1;
|
||||
r.y2 = r.y + v->base.r.h - 1;
|
||||
// Paint scrollbar.
|
||||
|
@ -176,17 +178,6 @@ static void vscrollPaint(struct WidgetS *widget, ...) {
|
|||
// Draw arrows.
|
||||
fontRender("\x1e", r.x + 7, r.y + 7);
|
||||
fontRender("\x1f", r.x + 7, r.y2 - 12);
|
||||
// Distance between arrow buttons on scroll bar.
|
||||
i = r.y2 - r.y - (GADGET_SIZE * 2 - 2) - 2;
|
||||
// Percentage to scale content height to scroll bar height.
|
||||
d = (double)i / (double)(v->max - v->min);
|
||||
// Find position and size of thumb.
|
||||
v->thumb.x = r.x + 1;
|
||||
v->thumb.x2 = r.x2 - 1;
|
||||
v->thumb.y = r.y + GADGET_SIZE + (v->value * d);
|
||||
v->thumb.y2 = v->thumb.y + (v->base.r.h * d);
|
||||
// Clamp overflow due to doubles and my off-by-one brain.
|
||||
if (v->thumb.y2 >= v->thumb.y + i - 1) v->thumb.y2 = v->thumb.y + i - 1;
|
||||
// Draw thumb.
|
||||
surfaceBoxFilled(v->thumb.x + 1, v->thumb.y + 1, v->thumb.x2 - 1, v->thumb.y2 - 1, GUI_LIGHTGRAY);
|
||||
surfaceBoxHighlight(v->thumb.x, v->thumb.y, v->thumb.x2, v->thumb.y2, GUI_WHITE, GUI_BLACK);
|
||||
|
@ -206,6 +197,48 @@ void vscrollRangeSet(VscrollT *vscroll, int32_t min, int32_t max) {
|
|||
}
|
||||
|
||||
|
||||
static void vscrollRecalculate(VscrollT *v) {
|
||||
int16_t range;
|
||||
int16_t areaTop;
|
||||
int16_t area;
|
||||
int16_t areaBottom;
|
||||
int16_t thumbSize;
|
||||
float percent;
|
||||
RectT r;
|
||||
|
||||
// Range of scroll.
|
||||
range = v->max - v->min + 1;
|
||||
|
||||
// Find coordinates to draw scrollbar. Setting r to be one smaller than the widget's size makes later math cleaner.
|
||||
r.x = v->base.r.x;
|
||||
r.y = v->base.r.y;
|
||||
r.x2 = r.x + v->base.r.w - 1;
|
||||
r.y2 = r.y + v->base.r.h - 1;
|
||||
|
||||
// Find coordinates of thumb area.
|
||||
areaTop = r.y + GADGET_SIZE + 1;
|
||||
areaBottom = r.y2 - GADGET_SIZE - 1;
|
||||
area = areaBottom - areaTop + 1;
|
||||
|
||||
// Find scale percentage.
|
||||
percent = (float)area / (float)range;
|
||||
|
||||
// Find thumb position and size.
|
||||
thumbSize = (int16_t)(percent * (float)area);
|
||||
v->thumb.x = r.x + 1;
|
||||
v->thumb.x2 = r.x2 - 1;
|
||||
v->thumb.y = (int16_t)((float)v->value * percent) + areaTop;
|
||||
v->thumb.y2 = v->thumb.y + thumbSize;
|
||||
v->maxValue = (area - thumbSize) / percent;
|
||||
|
||||
// Clamp.
|
||||
logWrite("maxValue %d + area %d >= range %d\n", v->maxValue, area, range);
|
||||
//if (v->maxValue + area >= range) v->maxValue = range - area - 1;
|
||||
if (v->maxValue < 0) v->maxValue = 0;
|
||||
if (v->value > v->maxValue) vscrollValueSet(v, v->maxValue);
|
||||
}
|
||||
|
||||
|
||||
RegisterT *vscrollRegister(uint8_t magic) {
|
||||
static RegisterT reg = {
|
||||
"Vscroll",
|
||||
|
@ -223,15 +256,17 @@ RegisterT *vscrollRegister(uint8_t magic) {
|
|||
|
||||
|
||||
int32_t vscrollValueGet(VscrollT *vscroll) {
|
||||
return vscroll->value;
|
||||
// Internal value is always 0 based, so adjust for min.
|
||||
return vscroll->value + vscroll->min;
|
||||
}
|
||||
|
||||
|
||||
void vscrollValueSet(VscrollT *vscroll, int32_t value) {
|
||||
// Clamp.
|
||||
if (value < vscroll->min) value = vscroll->min;
|
||||
if (value > vscroll->max) value = vscroll->max;
|
||||
if (vscroll->value != value) {
|
||||
vscroll->value = value;
|
||||
widgetDirtySet(W(vscroll), 1);
|
||||
}
|
||||
// Internal value is always 0 based, so adjust for min.
|
||||
vscroll->value = value - vscroll->min;
|
||||
vscrollRecalculate(vscroll);
|
||||
widgetDirtySet(W(vscroll), 1);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ typedef struct VscrollS {
|
|||
int32_t min;
|
||||
int32_t max;
|
||||
int32_t value;
|
||||
int32_t maxValue;
|
||||
RectT thumb;
|
||||
ClickHandlerT handler; // Actual event handler.
|
||||
} VscrollT;
|
||||
|
|
|
@ -235,8 +235,8 @@ static void windowCache(WindowT *w, uint8_t redrawWindow) {
|
|||
|
||||
// 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;
|
||||
int16_t height;
|
||||
PointT visibleSize;
|
||||
PointT totalSize;
|
||||
va_list args;
|
||||
WindowT *win = NULL;
|
||||
int8_t sflags = SCROLLABLE_NONE;
|
||||
|
@ -249,24 +249,29 @@ WindowT *windowCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *titl
|
|||
win->title = strdup(title);
|
||||
win->flags = (uint8_t)flags;
|
||||
|
||||
logWrite("windowCreate: %dx%d\n", win->base.r.w, win->base.r.h);
|
||||
|
||||
// Cache the window so we get valid bounds values.
|
||||
windowCache(win, 1);
|
||||
visibleSize.x = win->bounds.x2 - win->bounds.x + 1;
|
||||
visibleSize.y = win->bounds.y2 - win->bounds.y + 1;
|
||||
|
||||
// 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);
|
||||
width = va_arg(args, int);
|
||||
height = va_arg(args, int);
|
||||
totalSize.x = va_arg(args, int);
|
||||
totalSize.y = va_arg(args, int);
|
||||
va_end(args);
|
||||
sflags = SCROLLABLE_STANDARD;
|
||||
} else {
|
||||
// Use whatever the default content area is. This causes an extra draw on create. Oh well.
|
||||
windowCache(win, 1);
|
||||
width = win->bounds.x2 - win->bounds.x;
|
||||
height = win->bounds.y2 - win->bounds.y;
|
||||
totalSize = visibleSize;
|
||||
widgetDirtySet(W(win), 1);
|
||||
if (flags & WIN_SCROLL_H) sflags |= SCROLLABLE_SCROLL_H;
|
||||
if (flags & WIN_SCROLL_V) sflags |= SCROLLABLE_SCROLL_V;
|
||||
}
|
||||
|
||||
win->scroll = scrollableCreate(w, h, width, height, sflags);
|
||||
win->scroll = scrollableCreate(visibleSize.x, visibleSize.y, totalSize.x, totalSize.y, sflags);
|
||||
win->scroll->base.flags |= WIDGET_IS_WINDOW;
|
||||
widgetAdd(W(win), 0, 0, W(win->scroll));
|
||||
|
||||
|
@ -561,11 +566,18 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
int16_t y = 0;
|
||||
int16_t content = 0;
|
||||
int16_t change = 0;
|
||||
PointT chrome;
|
||||
|
||||
// Find size of window chrome.
|
||||
chrome.x = win->base.r.w - (win->bounds.x2 - win->bounds.x) + 1;
|
||||
chrome.y = win->base.r.h - (win->bounds.y2 - win->bounds.y) + 1;
|
||||
|
||||
// Too small?
|
||||
if (width < (GADGET_SIZE * 4) + 15) width = (GADGET_SIZE * 4) + 15;
|
||||
if (height < (GADGET_SIZE * 4) + 15) height = (GADGET_SIZE * 4) + 15;
|
||||
// if (width < (GADGET_SIZE * 4) + 15) width = (GADGET_SIZE * 4) + 15;
|
||||
if (height < (GADGET_SIZE * 4) + chrome.y) height = (GADGET_SIZE * 4) + chrome.y;
|
||||
// logWrite("Chrome Y: %d Height: %d\n", chrome.y, height);
|
||||
|
||||
/*
|
||||
// Too big? Horizontal.
|
||||
// Get the current view offset.
|
||||
x = scrollableValueHGet(win->scroll);
|
||||
|
@ -590,22 +602,28 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
// Clamp.
|
||||
x = win->base.r.w - content + surfaceWidthGet(win->scroll->area);
|
||||
if (width > x) width = x;
|
||||
*/
|
||||
|
||||
// Too big? Vertical.
|
||||
// Get the current view offset.
|
||||
y = scrollableValueVGet(win->scroll);
|
||||
// Height of content area of window.
|
||||
content = win->bounds.y2 - win->bounds.y;
|
||||
content = win->bounds.y2 - win->bounds.y + 1;
|
||||
// Do we have a vertical scroll bar?
|
||||
if (win->scroll->scrollv) {
|
||||
// Do we need to take the height of the horizontal scroll bar into account?
|
||||
if (win->scroll->scrollh) content -= win->scroll->scrollh->base.r.h;
|
||||
// Change in height.
|
||||
change = height - win->base.r.h;
|
||||
// Is the visible content area with this change offset by the scrollbar taller than the total content area?
|
||||
if (content + change + y > surfaceHeightGet(win->scroll->area)) {
|
||||
// Do we have room to scroll content into view?
|
||||
if (y > 0) {
|
||||
// Find out how far we're trying to scroll.
|
||||
delta = height - win->base.r.h;
|
||||
// Clamp to available scroll area.
|
||||
if (delta > y) delta = y;
|
||||
// Scroll.
|
||||
scrollableValueVSet(win->scroll, y - delta);
|
||||
}
|
||||
height = (win->base.r.h - content - y + surfaceHeightGet(win->scroll->area));
|
||||
|
@ -613,6 +631,7 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
}
|
||||
// Clamp.
|
||||
y = win->base.r.h - content + surfaceHeightGet(win->scroll->area);
|
||||
// logWrite("Y Clamp: %d > %d Chrome: %d\n", height, y, win->base.r.h - content);
|
||||
if (height > y) height = y;
|
||||
|
||||
// Did the size change?
|
||||
|
@ -690,7 +709,7 @@ void wmUpdate(EventT *event) {
|
|||
}
|
||||
|
||||
// If we're over a widget that has raw input processing enabled and we haven't started a click on another widget yet, send to target for raw processing.
|
||||
if (widgetOver && !widgetDown && !dragging && (widgetOver->flags & WIDGET_RAW_INPUT) && (event->buttons != 0)) {
|
||||
if (widgetOver && !widgetDown && !dragging && !resizing && (widgetOver->flags & WIDGET_RAW_INPUT) && (event->buttons != 0)) {
|
||||
if (widgetOver->reg->click) {
|
||||
rawEvent.event = event;
|
||||
rawEvent.data = widget->data;
|
||||
|
@ -720,7 +739,7 @@ void wmUpdate(EventT *event) {
|
|||
// 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);
|
||||
surfaceBox(win->bounds.x, win->bounds.y, win->bounds.x2, win->bounds.y2, GUI_YELLOW);
|
||||
surfaceBox(win->close.x, win->close.y, win->close.x2, win->close.y2, GUI_LIGHTBLUE);
|
||||
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);
|
||||
|
@ -916,7 +935,7 @@ static WidgetT *wuWidgetUnderMouseGet(WindowT *win, EventT *event, int16_t *loca
|
|||
// Find widget under mouse.
|
||||
for (i=0; i<arrlen(win->base.children); i++) {
|
||||
widget = win->base.children[i];
|
||||
if (*localX >= widget->r.x && *localX < widget->r.x + widget->r.x2 && *localY >= widget->r.y && *localY < widget->r.y + widget->r.y2) {
|
||||
if (*localX >= widget->r.x && *localX < widget->r.x + widget->r.w && *localY >= widget->r.y && *localY < widget->r.y + widget->r.h) {
|
||||
//logWrite("Over %s\n", widget->reg->widgetName);
|
||||
// Return this widget.
|
||||
return widget;
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef struct WindowS {
|
|||
RectT resize1; // First resize area.
|
||||
RectT resize2; // Second resize area.
|
||||
ScrollableT *scroll; // Window contents and scroll bars.
|
||||
RectT restore; // Size of window if they restore from maximized.
|
||||
RectWT restore; // Size of window if they restore from maximized.
|
||||
PointT restoreOffset; // Scroll position if they restore from maximized.
|
||||
RectT bounds; // Inside edge of window frame.
|
||||
/*
|
||||
|
|
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (guiStartup(800, 600, 16) == SUCCESS) {
|
||||
|
||||
for (i=1; i<4; i++) {
|
||||
for (i=1; i<2; i++) {
|
||||
sprintf(title, "Testing %d", i);
|
||||
w = windowCreate(i * 50, i * 50, 600, 400, title, WIN_STANDARD, 640, 480);
|
||||
|
||||
|
@ -95,6 +95,7 @@ int main(int argc, char *argv[]) {
|
|||
r = radioCreate("Radio C", 1, 0);
|
||||
widgetAdd(W(w), 220, 140, W(r));
|
||||
|
||||
/*
|
||||
_v = vscrollCreate(100, clickHandler, NULL);
|
||||
vscrollRangeSet(_v, 0, 640);
|
||||
widgetAdd(W(w), 200, 5, W(_v));
|
||||
|
@ -105,6 +106,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
s = scrollableCreate(300, 200, 648, 480, SCROLLABLE_STANDARD);
|
||||
widgetAdd(W(w), 20, 170, W(s));
|
||||
*/
|
||||
}
|
||||
guiRun();
|
||||
guiShutdown();
|
||||
|
|
Loading…
Add table
Reference in a new issue