diff --git a/roo-e/src/gui/widgets/hscroll.c b/roo-e/src/gui/widgets/hscroll.c index 991062b..4cf36a3 100644 --- a/roo-e/src/gui/widgets/hscroll.c +++ b/roo-e/src/gui/widgets/hscroll.c @@ -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); } diff --git a/roo-e/src/gui/widgets/hscroll.h b/roo-e/src/gui/widgets/hscroll.h index 866542f..2e2db3e 100644 --- a/roo-e/src/gui/widgets/hscroll.h +++ b/roo-e/src/gui/widgets/hscroll.h @@ -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; diff --git a/roo-e/src/gui/widgets/scroll.c b/roo-e/src/gui/widgets/scroll.c index abdf3c9..195a390 100644 --- a/roo-e/src/gui/widgets/scroll.c +++ b/roo-e/src/gui/widgets/scroll.c @@ -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); } diff --git a/roo-e/src/gui/widgets/vscroll.c b/roo-e/src/gui/widgets/vscroll.c index 932e6ca..583a1c3 100644 --- a/roo-e/src/gui/widgets/vscroll.c +++ b/roo-e/src/gui/widgets/vscroll.c @@ -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); } diff --git a/roo-e/src/gui/wmwindow.c b/roo-e/src/gui/wmwindow.c index 8c75a5f..a1585cc 100644 --- a/roo-e/src/gui/wmwindow.c +++ b/roo-e/src/gui/wmwindow.c @@ -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?