From 9433a63c1ff2d38b419ba944f60fdb1dc88a12e6 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Thu, 18 Aug 2022 17:00:49 -0500 Subject: [PATCH] More resize fixes. --- roo-e/src/gui/widgets/scroll.c | 45 +++++++++++++- roo-e/src/gui/widgets/scroll.h | 4 ++ roo-e/src/gui/widgets/vscroll.c | 1 + roo-e/src/gui/wmwindow.c | 103 ++++++++++++++++++++++---------- 4 files changed, 118 insertions(+), 35 deletions(-) diff --git a/roo-e/src/gui/widgets/scroll.c b/roo-e/src/gui/widgets/scroll.c index f79364b..abcef5a 100644 --- a/roo-e/src/gui/widgets/scroll.c +++ b/roo-e/src/gui/widgets/scroll.c @@ -48,6 +48,7 @@ static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint s->offset.x = hscrollValueGet(s->scrollh); s->offset.y = vscrollValueGet(s->scrollv); + widgetDirtySet(W(s), 1); } @@ -86,7 +87,7 @@ ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, return NULL; } surfaceSet(s->area); - surfaceClear(GUI_LIGHTBLUE); + surfaceClear(GUI_LIGHTGRAY); surfaceSet(t); return s; @@ -159,6 +160,7 @@ static void scrollablePaint(struct WidgetS *widget, ...) { if (widgetDirtyGet(widget)) { widgetDirtySet(widget, 0); + // Finish initializing? if (s->flags & SCROLLABLE_NOT_SETUP) { s->flags &= ~SCROLLABLE_NOT_SETUP; @@ -172,17 +174,32 @@ static void scrollablePaint(struct WidgetS *widget, ...) { widgetAdd(s->base.parent, s->base.r.x + s->sizes.x, s->base.r.y, W(s->scrollv)); } } - // Before painting contents, we need to offset everything by the window borders. + + // Move the contents to 0,0 to draw it into it's own surface. o.x = s->base.r.x; o.y = s->base.r.y; s->base.r.x = 0; s->base.r.y = 0; + + // Draw children onto surface. surfaceSet(s->area); widgetChildrenPaint(widget); surfaceSet(t); + + // Put us back at the proper coodinates. s->base.r.x = o.x; 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->sizes.x, s->sizes.y, s->area); } } @@ -204,6 +221,30 @@ RegisterT *scrollableRegister(uint8_t magic) { } +int32_t scrollableValueHGet(ScrollableT *scroll) { + return hscrollValueGet(scroll->scrollh); +} + + +void scrollableValueHSet(ScrollableT *scroll, int32_t value) { + hscrollValueSet(scroll->scrollh, value); + scroll->offset.x = hscrollValueGet(scroll->scrollh); + widgetDirtySet(W(scroll), 1); +} + + +int32_t scrollableValueVGet(ScrollableT *scroll) { + return vscrollValueGet(scroll->scrollv); +} + + +void scrollableValueVSet(ScrollableT *scroll, int32_t value) { + vscrollValueSet(scroll->scrollv, value); + scroll->offset.y = vscrollValueGet(scroll->scrollv); + widgetDirtySet(W(scroll), 1); +} + + void scrollableWidthSet(ScrollableT *scroll, int16_t w) { scroll->original.x = w; scrollableFixupSizes(scroll); diff --git a/roo-e/src/gui/widgets/scroll.h b/roo-e/src/gui/widgets/scroll.h index 9446dd0..bacf635 100644 --- a/roo-e/src/gui/widgets/scroll.h +++ b/roo-e/src/gui/widgets/scroll.h @@ -59,6 +59,10 @@ ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, void scrollableHeightSet(ScrollableT *scroll, int16_t h); RegisterT *scrollableRegister(uint8_t magic); void scrollableWidthSet(ScrollableT *scroll, int16_t w); +int32_t scrollableValueHGet(ScrollableT *scroll); +void scrollableValueHSet(ScrollableT *scroll, int32_t value); +int32_t scrollableValueVGet(ScrollableT *scroll); +void scrollableValueVSet(ScrollableT *scroll, int32_t value); #endif // SCROLL_H diff --git a/roo-e/src/gui/widgets/vscroll.c b/roo-e/src/gui/widgets/vscroll.c index 64e2330..45afd6a 100644 --- a/roo-e/src/gui/widgets/vscroll.c +++ b/roo-e/src/gui/widgets/vscroll.c @@ -60,6 +60,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; // Update. widgetDirtySet(widget, 1); diff --git a/roo-e/src/gui/wmwindow.c b/roo-e/src/gui/wmwindow.c index 1a33a9c..7c4619c 100644 --- a/roo-e/src/gui/wmwindow.c +++ b/roo-e/src/gui/wmwindow.c @@ -59,12 +59,6 @@ static void windowCache(WindowT *w, uint8_t redrawWindow) { ColorT gadgetColor; SurfaceT *target = surfaceGet(); - // Move the window to 0,0 to draw it into it's own surface. - originalX = w->base.r.x; - originalY = w->base.r.y; - w->base.r.x = 0; - w->base.r.y = 0; - // Do we have a cached surface already? if (w->cached) { // Did the size change? @@ -81,7 +75,14 @@ static void windowCache(WindowT *w, uint8_t redrawWindow) { // Draw into cache. surfaceSet(w->cached); + // Does the window itself need redrawn or just the contents? if (redrawWindow) { + // Move the window to 0,0 to draw it into it's own surface. + originalX = w->base.r.x; + originalY = w->base.r.y; + w->base.r.x = 0; + w->base.r.y = 0; + // Determine some colors. titleBackgroundColor = (w == _windowTop) ? GUI_DARKGRAY : GUI_LIGHTGRAY; gadgetColor = (w == _windowTop) ? GUI_LIGHTGRAY : GUI_DARKGRAY; @@ -220,13 +221,14 @@ static void windowCache(WindowT *w, uint8_t redrawWindow) { scrollableWidthSet(w->scroll, x2 - x1); scrollableHeightSet(w->scroll, y2 - y1); } + + // Fixup all the widget coordinates. + windowMove(w, originalX, originalY); } // Redraw window. + // Draw contents. widgetChildrenPaint(W(w)); - // Fixup all the widget coordinates. - windowMove(w, originalX, originalY); - surfaceSet(target); } @@ -555,40 +557,63 @@ 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 w = 0; + int16_t x = 0; + int16_t y = 0; + int16_t content = 0; + int16_t change = 0; // Too small? if (width < (GADGET_SIZE * 4) + 15) width = (GADGET_SIZE * 4) + 15; if (height < (GADGET_SIZE * 4) + 15) height = (GADGET_SIZE * 4) + 15; - // Too big? + // 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) { - x = hscrollValueGet(win->scroll->scrollh); - if (win->scroll->scrollv) w = win->scroll->scrollv->base.r.w; - if (win->bounds.w - win->bounds.x + (width - win->base.r.w) + x > surfaceWidthGet(win->scroll->area) + w) { + // 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; - hscrollValueSet(win->scroll->scrollh, x - delta); + scrollableValueHSet(win->scroll, x - delta); } - width = (win->base.r.w - (win->bounds.x2 - win->bounds.x) - x + surfaceWidthGet(win->scroll->area) + w); + width = (win->base.r.w - content - x + surfaceWidthGet(win->scroll->area)); } } + // 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; if (win->scroll->scrollv) { - y = vscrollValueGet(win->scroll->scrollv); - if (win->bounds.h - win->bounds.y + (height - win->base.r.h) + 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; + // Change in height. + change = height - win->base.r.h; + if (content + change + y > surfaceHeightGet(win->scroll->area)) { // Do we have room to scroll content into view? if (y > 0) { delta = height - win->base.r.h; if (delta > y) delta = y; - vscrollValueSet(win->scroll->scrollv, y - delta); + scrollableValueVSet(win->scroll, y - delta); } - height = (win->base.r.h - (win->bounds.y2 - win->bounds.y) - y + surfaceHeightGet(win->scroll->area)); + height = (win->base.r.h - content - y + surfaceHeightGet(win->scroll->area)); } } + // Clamp. + y = win->base.r.h - content + surfaceHeightGet(win->scroll->area); + if (height > y) height = y; // Did the size change? if (win->base.r.w != width || win->base.r.h !=height) { @@ -598,7 +623,7 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) { // Do resize. win->base.r.w = width; win->base.r.h =height; - windowCache(win, 1); + widgetDirtySet(W(win), 1); } } @@ -651,23 +676,25 @@ void wmUpdate(EventT *event) { // Get top window. win = _windowTop; - // If we found a window, get right/bottom. + // If we found a window, get right/bottom and widget. if (win) { + // Find window outer bounds. x2 = win->base.r.x + win->base.r.w - 1; y2 = win->base.r.y + win->base.r.h - 1; + // Are we over a widget? + widgetOver = wuWidgetUnderMouseGet(win, event, &windowLocalX, &windowLocalY); } else { x2 = 0; y2 = 0; + widgetOver = NULL; } - // Are we over a widget? - widgetOver = wuWidgetUnderMouseGet(win, event, &windowLocalX, &windowLocalY); - // 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 && (widgetOver->flags & WIDGET_RAW_INPUT) && (event->buttons != 0)) { + if (widgetOver && !widgetDown && !dragging && (widgetOver->flags & WIDGET_RAW_INPUT) && (event->buttons != 0)) { if (widgetOver->reg->click) { rawEvent.event = event; rawEvent.data = widget->data; + //logWrite("Firing raw click for %s\n", widgetOver->reg->widgetName); widgetOver->reg->click(widgetOver, windowLocalX - widgetOver->r.x, windowLocalY - widgetOver->r.y, CLICK_RAW_INPUT, &rawEvent); } return; @@ -868,24 +895,34 @@ void wmUpdate(EventT *event) { static WidgetT *wuWidgetUnderMouseGet(WindowT *win, EventT *event, int16_t *localX, int16_t *localY) { int16_t i; + int16_t x2; + int16_t y2; + PointT offset; WidgetT *widget; - /* + // If we have scrollbars, get the offset for the view. + if (win->scroll->scrollh) offset.x = hscrollValueGet(win->scroll->scrollh); + if (win->scroll->scrollv) offset.y = vscrollValueGet(win->scroll->scrollv); + + // Find window bounds. + x2 = win->base.r.x + win->base.r.w - 1; + y2 = win->base.r.y + win->base.r.h - 1; + // Are we over the provided window? - if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) { + if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) { // Find window-local mouse coordinates. - *localX = event->x - win->bounds.x + win->offset.x; - *localY = event->y - win->bounds.y + win->offset.y; + *localX = event->x - win->base.r.x;// + offset.x; + *localY = event->y - win->base.r.y;// + offset.y; // Find widget under mouse. for (i=0; ibase.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) { + //logWrite("Over %s\n", widget->reg->widgetName); // Return this widget. return widget; } } } - */ return NULL; }