More resize fixes.

This commit is contained in:
Scott Duensing 2022-08-18 17:00:49 -05:00
parent 74d4e05af9
commit 9433a63c1f
4 changed files with 118 additions and 35 deletions

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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; 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) {
//logWrite("Over %s\n", widget->reg->widgetName);
// Return this widget.
return widget;
}
}
}
*/
return NULL;
}