I think the scrollbars finally work. Now to fix the drag corner to use the newly empty space.
This commit is contained in:
parent
814a9ef705
commit
80802fe53a
5 changed files with 75 additions and 84 deletions
|
@ -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 hscrollDestroy(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) {
|
||||
|
@ -47,7 +48,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
// Move content left.
|
||||
h->value -= SCROLL_SPEED_SLOW;
|
||||
// Clip.
|
||||
if (h->value < h->min) h->value = h->min;
|
||||
if (h->value < 0) h->value = 0;
|
||||
// Update.
|
||||
widgetDirtySet(widget, 1);
|
||||
// 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.
|
||||
h->value += SCROLL_SPEED_SLOW;
|
||||
// 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.
|
||||
widgetDirtySet(widget, 1);
|
||||
// Call the actual click event.
|
||||
|
@ -68,6 +69,7 @@ static void hscrollClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// Clicking left of thumb? Also fakes dragging.
|
||||
if (x < h->thumb.x) {
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,7 +130,6 @@ HscrollT *hscrollCreate(int16_t w, ClickHandlerT handler, void *data, ...) {
|
|||
|
||||
static void hscrollDestroy(struct WidgetS *widget, ...) {
|
||||
HscrollT *h = (HscrollT *)widget;
|
||||
|
||||
DEL(h);
|
||||
}
|
||||
|
||||
|
@ -137,8 +139,6 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
ColorT scrollBackgroundColor;
|
||||
ColorT widgetColor;
|
||||
RectT r;
|
||||
int16_t i;
|
||||
double d;
|
||||
|
||||
if (widgetDirtyGet(widget)) {
|
||||
widgetDirtySet(widget, 0);
|
||||
|
@ -150,7 +150,9 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
scrollBackgroundColor = GUI_LIGHTGRAY;
|
||||
widgetColor = GUI_DARKGRAY;
|
||||
}
|
||||
// Find coordinates.
|
||||
// Do the math.
|
||||
hscrollRecalculate(h);
|
||||
// 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;
|
||||
|
@ -166,17 +168,6 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
|
|||
// Draw arrows.
|
||||
fontRender("\x11", r.x + 7, 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.
|
||||
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);
|
||||
|
@ -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) {
|
||||
static RegisterT reg = {
|
||||
"Hscroll",
|
||||
|
@ -213,25 +244,27 @@ RegisterT *hscrollRegister(uint8_t magic) {
|
|||
|
||||
|
||||
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) {
|
||||
// Clamp.
|
||||
if (value < hscroll->min) value = hscroll->min;
|
||||
if (value > hscroll->max) value = hscroll->max;
|
||||
if (hscroll->value != value) {
|
||||
hscroll->value = value;
|
||||
widgetDirtySet(W(hscroll), 1);
|
||||
}
|
||||
// Internal value is always 0 based, so adjust for min.
|
||||
hscroll->value = value - hscroll->min;
|
||||
hscrollRecalculate(hscroll);
|
||||
widgetDirtySet(W(hscroll), 1);
|
||||
}
|
||||
|
||||
|
||||
void hscrollWidthSet(HscrollT *hscroll, int16_t w) {
|
||||
// Make sure it's at least wide enough to draw.
|
||||
if (w < GADGET_SIZE * 3) w = GADGET_SIZE * 3;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ typedef struct HscrollS {
|
|||
int32_t min;
|
||||
int32_t max;
|
||||
int32_t value;
|
||||
int32_t maxValue;
|
||||
RectT thumb;
|
||||
ClickHandlerT handler; // Actual event handler.
|
||||
} HscrollT;
|
||||
|
|
|
@ -135,7 +135,7 @@ static void scrollableFixupSizes(ScrollableT *s) {
|
|||
// 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 - - (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.
|
||||
widgetMove(W(s->scrollh), s->base.r.x, s->base.r.y + s->position.y);
|
||||
} else {
|
||||
|
@ -146,8 +146,12 @@ static void scrollableFixupSizes(ScrollableT *s) {
|
|||
|
||||
|
||||
void scrollableHeightSet(ScrollableT *scroll, int16_t h) {
|
||||
int32_t in = 0;
|
||||
if (scroll->scrollv) in = vscrollValueGet(scroll->scrollv);
|
||||
scroll->original.y = h;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -190,17 +194,6 @@ 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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -247,8 +240,12 @@ void scrollableValueVSet(ScrollableT *scroll, int32_t value) {
|
|||
|
||||
|
||||
void scrollableWidthSet(ScrollableT *scroll, int16_t w) {
|
||||
int32_t in = 0;
|
||||
if (scroll->scrollh) in = hscrollValueGet(scroll->scrollh);
|
||||
scroll->original.x = w;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ static void vscrollRecalculate(VscrollT *v) {
|
|||
// 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.
|
||||
// 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;
|
||||
|
@ -221,7 +221,7 @@ static void vscrollRecalculate(VscrollT *v) {
|
|||
area = areaBottom - areaTop + 1;
|
||||
|
||||
// Find scale percentage.
|
||||
percent = (float)area / (float)range;
|
||||
percent = (float)v->base.r.h / (float)range;
|
||||
|
||||
// Find thumb position and size.
|
||||
thumbSize = (int16_t)(percent * (float)area);
|
||||
|
@ -232,8 +232,6 @@ static void vscrollRecalculate(VscrollT *v) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -561,11 +561,9 @@ RegisterT *windowRegister(uint8_t magic) {
|
|||
|
||||
void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
||||
|
||||
int16_t delta;
|
||||
int16_t x = 0;
|
||||
int16_t y = 0;
|
||||
int16_t content = 0;
|
||||
int16_t change = 0;
|
||||
PointT 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;
|
||||
|
||||
// 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;
|
||||
// logWrite("Chrome Y: %d Height: %d\n", chrome.y, height);
|
||||
|
||||
/*
|
||||
// Too big? Horizontal.
|
||||
// Get the current view offset.
|
||||
x = scrollableValueHGet(win->scroll);
|
||||
// Width of content area of window.
|
||||
content = win->bounds.x2 - win->bounds.x;
|
||||
if (win->scroll->scrollh) {
|
||||
// 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;
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
content = win->bounds.x2 - win->bounds.x + 1;
|
||||
// Do we need to take the height of the vertical scroll bar into account?
|
||||
if (win->scroll->scrollv) content -= win->scroll->scrollv->base.r.w;
|
||||
// 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 + 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));
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// 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?
|
||||
|
|
Loading…
Add table
Reference in a new issue