I think the scrollbars finally work. Now to fix the drag corner to use the newly empty space.

This commit is contained in:
Scott Duensing 2022-08-31 18:21:32 -05:00
parent 814a9ef705
commit 80802fe53a
5 changed files with 75 additions and 84 deletions

View file

@ -35,6 +35,7 @@ uint8_t __MAGIC_HSCROLL = 0;
static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data); static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
static void hscrollDestroy(struct WidgetS *widget, ...); static void hscrollDestroy(struct WidgetS *widget, ...);
static void hscrollPaint(struct WidgetS *widget, ...); static void hscrollPaint(struct WidgetS *widget, ...);
static void hscrollRecalculate(HscrollT *h);
static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) { static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
@ -47,7 +48,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
// Move content left. // Move content left.
h->value -= SCROLL_SPEED_SLOW; h->value -= SCROLL_SPEED_SLOW;
// Clip. // Clip.
if (h->value < h->min) h->value = h->min; if (h->value < 0) h->value = 0;
// Update. // Update.
widgetDirtySet(widget, 1); widgetDirtySet(widget, 1);
// Call the actual click event. // Call the actual click event.
@ -60,7 +61,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
// Move content right. // Move content right.
h->value += SCROLL_SPEED_SLOW; h->value += SCROLL_SPEED_SLOW;
// Clip. // Clip.
if (h->value > h->max - h->base.r.w) h->value = h->max - h->base.r.w; if (h->value > h->maxValue) h->value = h->maxValue;
// Update. // Update.
widgetDirtySet(widget, 1); widgetDirtySet(widget, 1);
// Call the actual click event. // Call the actual click event.
@ -68,6 +69,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
return; return;
} }
/*
// Clicking left of thumb? Also fakes dragging. // Clicking left of thumb? Also fakes dragging.
if (x < h->thumb.x) { if (x < h->thumb.x) {
// Move content left. // Move content left.
@ -93,6 +95,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
if (h->handler) h->handler(widget, x, y, event, h->base.data); if (h->handler) h->handler(widget, x, y, event, h->base.data);
return; return;
} }
*/
} }
@ -127,7 +130,6 @@ HscrollT *hscrollCreate(int16_t w, ClickHandlerT handler, void *data, ...) {
static void hscrollDestroy(struct WidgetS *widget, ...) { static void hscrollDestroy(struct WidgetS *widget, ...) {
HscrollT *h = (HscrollT *)widget; HscrollT *h = (HscrollT *)widget;
DEL(h); DEL(h);
} }
@ -137,8 +139,6 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
ColorT scrollBackgroundColor; ColorT scrollBackgroundColor;
ColorT widgetColor; ColorT widgetColor;
RectT r; RectT r;
int16_t i;
double d;
if (widgetDirtyGet(widget)) { if (widgetDirtyGet(widget)) {
widgetDirtySet(widget, 0); widgetDirtySet(widget, 0);
@ -150,7 +150,9 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
scrollBackgroundColor = GUI_LIGHTGRAY; scrollBackgroundColor = GUI_LIGHTGRAY;
widgetColor = GUI_DARKGRAY; widgetColor = GUI_DARKGRAY;
} }
// Find coordinates. // Do the math.
hscrollRecalculate(h);
// Find coordinates to draw scrollbar.
r.x = h->base.r.x; r.x = h->base.r.x;
r.y = h->base.r.y; r.y = h->base.r.y;
r.x2 = r.x + h->base.r.w - 1; r.x2 = r.x + h->base.r.w - 1;
@ -166,17 +168,6 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
// Draw arrows. // Draw arrows.
fontRender("\x11", r.x + 7, r.y + 7); fontRender("\x11", r.x + 7, r.y + 7);
fontRender("\x10", r.x2 - 12, r.y + 7); fontRender("\x10", r.x2 - 12, r.y + 7);
// Distance between arrow buttons on scroll bar.
i = r.x2 - r.x - (GADGET_SIZE * 2 - 2) - 2;
// Percentage to scale content height to scroll bar height.
d = (double)i / (double)(h->max - h->min);
// Find position and size of thumb.
h->thumb.x = r.x + GADGET_SIZE + (h->value * d);
h->thumb.x2 = h->thumb.x + (h->base.r.w * d);
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 >= r.x + GADGET_SIZE + i - 1) h->thumb.x2 = r.x + GADGET_SIZE + i - 1;
// Draw thumb. // Draw thumb.
surfaceBoxFilled(h->thumb.x + 1, h->thumb.y + 1, h->thumb.x2 - 1, h->thumb.y2 - 1, GUI_LIGHTGRAY); 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); surfaceBoxHighlight(h->thumb.x, h->thumb.y, h->thumb.x2, h->thumb.y2, GUI_WHITE, GUI_BLACK);
@ -196,6 +187,46 @@ void hscrollRangeSet(HscrollT *hscroll, int32_t min, int32_t max) {
} }
static void hscrollRecalculate(HscrollT *h) {
int16_t range;
int16_t areaLeft;
int16_t area;
int16_t areaRight;
int16_t thumbSize;
float percent;
RectT r;
// Range of scroll.
range = h->max - h->min + 1;
// Find coordinates to draw scrollbar.
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;
// Find coordinates of thumb area.
areaLeft = r.x + GADGET_SIZE + 1;
areaRight = r.x2 - GADGET_SIZE - 1;
area = areaRight - areaLeft + 1;
// Find scale percentage.
percent = (float)h->base.r.w / (float)range;
// Find thumb position and size.
thumbSize = (int16_t)(percent * (float)area);
h->thumb.y = r.y + 1;
h->thumb.y2 = r.y2 - 1;
h->thumb.x = (int16_t)((float)h->value * percent) + areaLeft;
h->thumb.x2 = h->thumb.x + thumbSize;
h->maxValue = (area - thumbSize) / percent;
// Clamp.
if (h->maxValue < 0) h->maxValue = 0;
if (h->value > h->maxValue) hscrollValueSet(h, h->maxValue);
}
RegisterT *hscrollRegister(uint8_t magic) { RegisterT *hscrollRegister(uint8_t magic) {
static RegisterT reg = { static RegisterT reg = {
"Hscroll", "Hscroll",
@ -213,25 +244,27 @@ RegisterT *hscrollRegister(uint8_t magic) {
int32_t hscrollValueGet(HscrollT *hscroll) { int32_t hscrollValueGet(HscrollT *hscroll) {
return hscroll->value; // Internal value is always 0 based, so adjust for min.
return hscroll->value + hscroll->min;
} }
void hscrollValueSet(HscrollT *hscroll, int32_t value) { void hscrollValueSet(HscrollT *hscroll, int32_t value) {
// Clamp.
if (value < hscroll->min) value = hscroll->min; if (value < hscroll->min) value = hscroll->min;
if (value > hscroll->max) value = hscroll->max; if (value > hscroll->max) value = hscroll->max;
if (hscroll->value != value) { // Internal value is always 0 based, so adjust for min.
hscroll->value = value; hscroll->value = value - hscroll->min;
hscrollRecalculate(hscroll);
widgetDirtySet(W(hscroll), 1); widgetDirtySet(W(hscroll), 1);
} }
}
void hscrollWidthSet(HscrollT *hscroll, int16_t w) { void hscrollWidthSet(HscrollT *hscroll, int16_t w) {
// Make sure it's at least wide enough to draw. // Make sure it's at least wide enough to draw.
if (w < GADGET_SIZE * 3) w = GADGET_SIZE * 3; if (w < GADGET_SIZE * 3) w = GADGET_SIZE * 3;
hscroll->base.r.w = w; hscroll->base.r.w = w;
// This doesn't check that you haven't set some insane value for the width. Up to caller.
hscrollRecalculate(hscroll);
widgetDirtySet(W(hscroll), 1); widgetDirtySet(W(hscroll), 1);
} }

View file

@ -35,6 +35,7 @@ typedef struct HscrollS {
int32_t min; int32_t min;
int32_t max; int32_t max;
int32_t value; int32_t value;
int32_t maxValue;
RectT thumb; RectT thumb;
ClickHandlerT handler; // Actual event handler. ClickHandlerT handler; // Actual event handler.
} HscrollT; } HscrollT;

View file

@ -135,7 +135,7 @@ static void scrollableFixupSizes(ScrollableT *s) {
// Make scroll area smaller to make room for scrollbar. // Make scroll area smaller to make room for scrollbar.
s->base.r.h = s->original.y - s->scrollh->base.r.h; s->base.r.h = s->original.y - s->scrollh->base.r.h;
// Resize horizontal scrollbar. // Resize horizontal scrollbar.
hscrollWidthSet(s->scrollh, s->original.x - - (s->scrollv ? s->scrollv->base.r.w - 1: 0)); hscrollWidthSet(s->scrollh, s->original.x - (s->scrollv ? s->scrollv->base.r.w - 1: 0));
// Position horizontal scrollbar. // Position horizontal scrollbar.
widgetMove(W(s->scrollh), s->base.r.x, s->base.r.y + s->position.y); widgetMove(W(s->scrollh), s->base.r.x, s->base.r.y + s->position.y);
} else { } else {
@ -146,8 +146,12 @@ static void scrollableFixupSizes(ScrollableT *s) {
void scrollableHeightSet(ScrollableT *scroll, int16_t h) { void scrollableHeightSet(ScrollableT *scroll, int16_t h) {
int32_t in = 0;
if (scroll->scrollv) in = vscrollValueGet(scroll->scrollv);
scroll->original.y = h; scroll->original.y = h;
scrollableFixupSizes(scroll); scrollableFixupSizes(scroll);
// If the scrollbar value changed, we need to reposition our view.
if (scroll->scrollv && in != vscrollValueGet(scroll->scrollv)) scrollableValueVSet(scroll, vscrollValueGet(scroll->scrollv));
widgetDirtySet(W(scroll), 1); widgetDirtySet(W(scroll), 1);
} }
@ -190,17 +194,6 @@ static void scrollablePaint(struct WidgetS *widget, ...) {
s->base.r.y = o.y; s->base.r.y = o.y;
// Blit. // 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,
s->offset.x, s->offset.y,
s->sizes.x, s->sizes.y,
surfaceWidthGet(s->area), surfaceHeightGet(s->area),
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->position.x, s->position.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);
} }
} }
@ -247,8 +240,12 @@ void scrollableValueVSet(ScrollableT *scroll, int32_t value) {
void scrollableWidthSet(ScrollableT *scroll, int16_t w) { void scrollableWidthSet(ScrollableT *scroll, int16_t w) {
int32_t in = 0;
if (scroll->scrollh) in = hscrollValueGet(scroll->scrollh);
scroll->original.x = w; scroll->original.x = w;
scrollableFixupSizes(scroll); scrollableFixupSizes(scroll);
// If the scrollbar value changed, we need to reposition our view.
if (scroll->scrollh && in != hscrollValueGet(scroll->scrollh)) scrollableValueHSet(scroll, hscrollValueGet(scroll->scrollh));
widgetDirtySet(W(scroll), 1); widgetDirtySet(W(scroll), 1);
} }

View file

@ -209,7 +209,7 @@ static void vscrollRecalculate(VscrollT *v) {
// Range of scroll. // Range of scroll.
range = v->max - v->min + 1; 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. // Find coordinates to draw scrollbar.
r.x = v->base.r.x; r.x = v->base.r.x;
r.y = v->base.r.y; r.y = v->base.r.y;
r.x2 = r.x + v->base.r.w - 1; r.x2 = r.x + v->base.r.w - 1;
@ -221,7 +221,7 @@ static void vscrollRecalculate(VscrollT *v) {
area = areaBottom - areaTop + 1; area = areaBottom - areaTop + 1;
// Find scale percentage. // Find scale percentage.
percent = (float)area / (float)range; percent = (float)v->base.r.h / (float)range;
// Find thumb position and size. // Find thumb position and size.
thumbSize = (int16_t)(percent * (float)area); thumbSize = (int16_t)(percent * (float)area);
@ -232,8 +232,6 @@ static void vscrollRecalculate(VscrollT *v) {
v->maxValue = (area - thumbSize) / percent; v->maxValue = (area - thumbSize) / percent;
// Clamp. // 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->maxValue < 0) v->maxValue = 0;
if (v->value > v->maxValue) vscrollValueSet(v, v->maxValue); if (v->value > v->maxValue) vscrollValueSet(v, v->maxValue);
} }

View file

@ -561,11 +561,9 @@ RegisterT *windowRegister(uint8_t magic) {
void windowResize(WindowT *win, uint16_t width, uint16_t height) { void windowResize(WindowT *win, uint16_t width, uint16_t height) {
int16_t delta;
int16_t x = 0; int16_t x = 0;
int16_t y = 0; int16_t y = 0;
int16_t content = 0; int16_t content = 0;
int16_t change = 0;
PointT chrome; PointT chrome;
// Find size of window chrome. // Find size of window chrome.
@ -573,65 +571,29 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
chrome.y = win->base.r.h - (win->bounds.y2 - win->bounds.y) + 1; chrome.y = win->base.r.h - (win->bounds.y2 - win->bounds.y) + 1;
// Too small? // Too small?
// if (width < (GADGET_SIZE * 4) + 15) width = (GADGET_SIZE * 4) + 15; if (width < (GADGET_SIZE * 4) + chrome.x) width = (GADGET_SIZE * 4) + chrome.x;
if (height < (GADGET_SIZE * 4) + chrome.y) height = (GADGET_SIZE * 4) + chrome.y; 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. // Too big? Horizontal.
// Get the current view offset. // Get the current view offset.
x = scrollableValueHGet(win->scroll); x = scrollableValueHGet(win->scroll);
// Width of content area of window. // Width of content area of window.
content = win->bounds.x2 - win->bounds.x; content = win->bounds.x2 - win->bounds.x + 1;
if (win->scroll->scrollh) { // Do we need to take the height of the vertical scroll bar into account?
// Do we need to take the width of the vertical scroll bar into account?
if (win->scroll->scrollv) content -= win->scroll->scrollv->base.r.w; if (win->scroll->scrollv) content -= win->scroll->scrollv->base.r.w;
// Change in width.
change = width - win->base.r.w;
// If the new width is going to render content past the right edge of the area, we need to scroll the area.
if (content + change + x > surfaceWidthGet(win->scroll->area)) {
// Do we have room to scroll content into view?
if (x > 0) {
delta = width - win->base.r.w;
if (delta > x) delta = x;
scrollableValueHSet(win->scroll, x - delta);
}
width = (win->base.r.w - content - x + surfaceWidthGet(win->scroll->area));
}
}
// Clamp. // Clamp.
x = win->base.r.w - content + surfaceWidthGet(win->scroll->area); x = win->base.r.w - content + surfaceWidthGet(win->scroll->area);
if (width > x) width = x; if (width > x) width = x;
*/
// Too big? Vertical. // Too big? Vertical.
// Get the current view offset. // Get the current view offset.
y = scrollableValueVGet(win->scroll); y = scrollableValueVGet(win->scroll);
// Height of content area of window. // Height of content area of window.
content = win->bounds.y2 - win->bounds.y + 1; 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? // 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; 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));
}
}
// Clamp. // Clamp.
y = win->base.r.h - content + surfaceHeightGet(win->scroll->area); 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; if (height > y) height = y;
// Did the size change? // Did the size change?