Code cleanup.

This commit is contained in:
Scott Duensing 2026-03-12 21:16:52 -05:00
parent 2c87f396d3
commit 9fc21c2f83
12 changed files with 137 additions and 332 deletions

View file

@ -1959,13 +1959,7 @@ static void pollKeyboard(AppContextT *ctx) {
win->vScroll->value = virtY + next->h - win->contentH; win->vScroll->value = virtY + next->h - win->contentH;
} }
if (win->vScroll->value < win->vScroll->min) { win->vScroll->value = clampInt(win->vScroll->value, win->vScroll->min, win->vScroll->max);
win->vScroll->value = win->vScroll->min;
}
if (win->vScroll->value > win->vScroll->max) {
win->vScroll->value = win->vScroll->max;
}
} }
if (win->hScroll) { if (win->hScroll) {
@ -1975,13 +1969,7 @@ static void pollKeyboard(AppContextT *ctx) {
win->hScroll->value = virtX + next->w - win->contentW; win->hScroll->value = virtX + next->w - win->contentW;
} }
if (win->hScroll->value < win->hScroll->min) { win->hScroll->value = clampInt(win->hScroll->value, win->hScroll->min, win->hScroll->max);
win->hScroll->value = win->hScroll->min;
}
if (win->hScroll->value > win->hScroll->max) {
win->hScroll->value = win->hScroll->max;
}
} }
wgtInvalidate(win->widgetRoot); wgtInvalidate(win->widgetRoot);

View file

@ -10,7 +10,6 @@
char accelParse(const char *text); char accelParse(const char *text);
static inline void clipRect(const DisplayT *d, int32_t *x, int32_t *y, int32_t *w, int32_t *h); static inline void clipRect(const DisplayT *d, int32_t *x, int32_t *y, int32_t *w, int32_t *h);
void drawFocusRect(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
static inline void putPixel(uint8_t *dst, uint32_t color, int32_t bpp); static inline void putPixel(uint8_t *dst, uint32_t color, int32_t bpp);
static void spanCopy8(uint8_t *dst, const uint8_t *src, int32_t count); static void spanCopy8(uint8_t *dst, const uint8_t *src, int32_t count);
static void spanCopy16(uint8_t *dst, const uint8_t *src, int32_t count); static void spanCopy16(uint8_t *dst, const uint8_t *src, int32_t count);

View file

@ -77,6 +77,11 @@ typedef struct {
int32_t width; // border thickness in pixels (typically 2) int32_t width; // border thickness in pixels (typically 2)
} BevelStyleT; } BevelStyleT;
// Convenience initializers for common bevel styles (C99 compound literals)
#define BEVEL_RAISED(cs, bw) (BevelStyleT){ (cs)->windowHighlight, (cs)->windowShadow, (cs)->windowFace, (bw) }
#define BEVEL_SUNKEN(cs, face, bw) (BevelStyleT){ (cs)->windowShadow, (cs)->windowHighlight, (face), (bw) }
#define BEVEL_TROUGH(cs) (BevelStyleT){ (cs)->windowShadow, (cs)->windowHighlight, (cs)->scrollbarTrough, 1 }
// ============================================================ // ============================================================
// Bitmap font // Bitmap font
// ============================================================ // ============================================================

View file

@ -21,6 +21,7 @@ static int32_t findBestMode(int32_t requestedW, int32_t requestedH, int32_t pref
static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requestedW, int32_t requestedH, int32_t preferredBpp); static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
static int32_t mapLfb(DisplayT *d, uint32_t physAddr); static int32_t mapLfb(DisplayT *d, uint32_t physAddr);
static int32_t setVesaMode(uint16_t mode); static int32_t setVesaMode(uint16_t mode);
static void videoSetPalette(const uint8_t *pal, int32_t firstEntry, int32_t count);
// ============================================================ // ============================================================
@ -160,10 +161,6 @@ static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requ
// Must be a supported bpp // Must be a supported bpp
if (bpp != 8 && bpp != 15 && bpp != 16 && bpp != 32) { if (bpp != 8 && bpp != 15 && bpp != 16 && bpp != 32) {
// Some cards report 24-bit; skip those
if (bpp == 24) {
return;
}
return; return;
} }
@ -220,17 +217,6 @@ static void getModeInfo(uint16_t mode, DisplayT *d, int32_t *score, int32_t requ
d->format.blueBits = blueSize; d->format.blueBits = blueSize;
d->format.blueShift = bluePos; d->format.blueShift = bluePos;
d->format.blueMask = ((1U << blueSize) - 1) << bluePos; d->format.blueMask = ((1U << blueSize) - 1) << bluePos;
} else {
// 8-bit mode — masks not used, packColor returns palette index
d->format.redBits = 0;
d->format.redShift = 0;
d->format.redMask = 0;
d->format.greenBits = 0;
d->format.greenShift = 0;
d->format.greenMask = 0;
d->format.blueBits = 0;
d->format.blueShift = 0;
d->format.blueMask = 0;
} }
// Store physical address in lfb field temporarily (will be remapped) // Store physical address in lfb field temporarily (will be remapped)
@ -404,7 +390,7 @@ int32_t videoInit(DisplayT *d, int32_t requestedW, int32_t requestedH, int32_t p
// videoSetPalette // videoSetPalette
// ============================================================ // ============================================================
void videoSetPalette(const uint8_t *pal, int32_t firstEntry, int32_t count) { static void videoSetPalette(const uint8_t *pal, int32_t firstEntry, int32_t count) {
// Set VGA DAC registers directly via port I/O // Set VGA DAC registers directly via port I/O
// Port 0x3C8 = write index, Port 0x3C9 = data (R, G, B in 6-bit values) // Port 0x3C8 = write index, Port 0x3C9 = data (R, G, B in 6-bit values)
outportb(0x3C8, (uint8_t)firstEntry); outportb(0x3C8, (uint8_t)firstEntry);

View file

@ -22,7 +22,4 @@ void setClipRect(DisplayT *d, int32_t x, int32_t y, int32_t w, int32_t h);
// Reset clip rectangle to full display // Reset clip rectangle to full display
void resetClipRect(DisplayT *d); void resetClipRect(DisplayT *d);
// Set VGA DAC palette (8-bit mode only)
void videoSetPalette(const uint8_t *pal, int32_t firstEntry, int32_t count);
#endif // DVX_VIDEO_H #endif // DVX_VIDEO_H

View file

@ -16,6 +16,35 @@ static void canvasDrawLine(WidgetT *w, int32_t x0, int32_t y0, int32_t x1, int32
static void canvasUnpackColor(const DisplayT *d, uint32_t pixel, uint8_t *r, uint8_t *g, uint8_t *b); static void canvasUnpackColor(const DisplayT *d, uint32_t pixel, uint8_t *r, uint8_t *g, uint8_t *b);
// ============================================================
// canvasPutPixel
// ============================================================
//
// Write a single pixel of the given color at dst, respecting the display's
// bytes-per-pixel depth.
static inline uint32_t canvasGetPixel(const uint8_t *src, int32_t bpp) {
if (bpp == 1) {
return *src;
} else if (bpp == 2) {
return *(const uint16_t *)src;
} else {
return *(const uint32_t *)src;
}
}
static inline void canvasPutPixel(uint8_t *dst, uint32_t color, int32_t bpp) {
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
}
// ============================================================ // ============================================================
// canvasDrawDot // canvasDrawDot
// ============================================================ // ============================================================
@ -36,13 +65,7 @@ static void canvasDrawDot(WidgetT *w, int32_t cx, int32_t cy) {
if (cx >= 0 && cx < cw && cy >= 0 && cy < ch) { if (cx >= 0 && cx < cw && cy >= 0 && cy < ch) {
uint8_t *dst = data + cy * pitch + cx * bpp; uint8_t *dst = data + cy * pitch + cx * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
return; return;
@ -68,13 +91,7 @@ static void canvasDrawDot(WidgetT *w, int32_t cx, int32_t cy) {
if (dx * dx + dy * dy <= r2) { if (dx * dx + dy * dy <= r2) {
uint8_t *dst = data + py * pitch + px * bpp; uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
} }
@ -186,13 +203,7 @@ WidgetT *wgtCanvas(WidgetT *parent, int32_t w, int32_t h) {
for (int32_t x = 0; x < w; x++) { for (int32_t x = 0; x < w; x++) {
uint8_t *dst = data + y * pitch + x * bpp; uint8_t *dst = data + y * pitch + x * bpp;
if (bpp == 1) { canvasPutPixel(dst, white, bpp);
*dst = (uint8_t)white;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)white;
} else {
*(uint32_t *)dst = white;
}
} }
} }
@ -233,13 +244,7 @@ void wgtCanvasClear(WidgetT *w, uint32_t color) {
for (int32_t x = 0; x < cw; x++) { for (int32_t x = 0; x < cw; x++) {
uint8_t *dst = w->as.canvas.data + y * pitch + x * bpp; uint8_t *dst = w->as.canvas.data + y * pitch + x * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
} }
@ -291,13 +296,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (y >= 0 && y < ch) { if (y >= 0 && y < ch) {
uint8_t *dst = data + y * pitch + px * bpp; uint8_t *dst = data + y * pitch + px * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
int32_t by = y + height - 1; int32_t by = y + height - 1;
@ -305,13 +304,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (by >= 0 && by < ch && by != y) { if (by >= 0 && by < ch && by != y) {
uint8_t *dst = data + by * pitch + px * bpp; uint8_t *dst = data + by * pitch + px * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
@ -324,13 +317,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (x >= 0 && x < cw) { if (x >= 0 && x < cw) {
uint8_t *dst = data + py * pitch + x * bpp; uint8_t *dst = data + py * pitch + x * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
int32_t rx = x + width - 1; int32_t rx = x + width - 1;
@ -338,13 +325,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (rx >= 0 && rx < cw && rx != x) { if (rx >= 0 && rx < cw && rx != x) {
uint8_t *dst = data + py * pitch + rx * bpp; uint8_t *dst = data + py * pitch + rx * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
} }
@ -390,13 +371,7 @@ void wgtCanvasFillCircle(WidgetT *w, int32_t cx, int32_t cy, int32_t radius) {
if (dx * dx + dy * dy <= r2) { if (dx * dx + dy * dy <= r2) {
uint8_t *dst = data + py * pitch + px * bpp; uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
} }
@ -435,13 +410,7 @@ void wgtCanvasFillRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
for (int32_t px = x0; px < x1; px++) { for (int32_t px = x0; px < x1; px++) {
uint8_t *dst = data + py * pitch + px * bpp; uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
} }
@ -463,13 +432,7 @@ uint32_t wgtCanvasGetPixel(const WidgetT *w, int32_t x, int32_t y) {
int32_t bpp = w->as.canvas.canvasPitch / w->as.canvas.canvasW; int32_t bpp = w->as.canvas.canvasPitch / w->as.canvas.canvasW;
const uint8_t *src = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp; const uint8_t *src = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp;
if (bpp == 1) { return canvasGetPixel(src, bpp);
return *src;
} else if (bpp == 2) {
return *(const uint16_t *)src;
} else {
return *(const uint32_t *)src;
}
} }
@ -521,13 +484,7 @@ int32_t wgtCanvasLoad(WidgetT *w, const char *path) {
uint32_t color = packColor(d, src[0], src[1], src[2]); uint32_t color = packColor(d, src[0], src[1], src[2]);
uint8_t *dst = data + y * pitch + x * bpp; uint8_t *dst = data + y * pitch + x * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }
} }
@ -581,15 +538,7 @@ int32_t wgtCanvasSave(WidgetT *w, const char *path) {
for (int32_t y = 0; y < ch; y++) { for (int32_t y = 0; y < ch; y++) {
for (int32_t x = 0; x < cw; x++) { for (int32_t x = 0; x < cw; x++) {
const uint8_t *src = w->as.canvas.data + y * pitch + x * bpp; const uint8_t *src = w->as.canvas.data + y * pitch + x * bpp;
uint32_t pixel; uint32_t pixel = canvasGetPixel(src, bpp);
if (bpp == 1) {
pixel = *src;
} else if (bpp == 2) {
pixel = *(const uint16_t *)src;
} else {
pixel = *(const uint32_t *)src;
}
uint8_t *dst = rgb + (y * cw + x) * 3; uint8_t *dst = rgb + (y * cw + x) * 3;
canvasUnpackColor(d, pixel, &dst[0], &dst[1], &dst[2]); canvasUnpackColor(d, pixel, &dst[0], &dst[1], &dst[2]);
@ -641,13 +590,7 @@ void wgtCanvasSetPixel(WidgetT *w, int32_t x, int32_t y, uint32_t color) {
int32_t bpp = w->as.canvas.canvasPitch / w->as.canvas.canvasW; int32_t bpp = w->as.canvas.canvasPitch / w->as.canvas.canvasW;
uint8_t *dst = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp; uint8_t *dst = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp;
if (bpp == 1) { canvasPutPixel(dst, color, bpp);
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
} }

View file

@ -394,9 +394,9 @@ bool widgetIsFocusable(WidgetTypeE type) {
return type == WidgetTextInputE || type == WidgetComboBoxE || return type == WidgetTextInputE || type == WidgetComboBoxE ||
type == WidgetDropdownE || type == WidgetCheckboxE || type == WidgetDropdownE || type == WidgetCheckboxE ||
type == WidgetRadioE || type == WidgetButtonE || type == WidgetRadioE || type == WidgetButtonE ||
type == WidgetSliderE || type == WidgetListBoxE || type == WidgetImageButtonE || type == WidgetSliderE ||
type == WidgetTreeViewE || type == WidgetAnsiTermE || type == WidgetListBoxE || type == WidgetTreeViewE ||
type == WidgetTabControlE; type == WidgetAnsiTermE || type == WidgetTabControlE;
} }
@ -424,6 +424,31 @@ bool widgetIsHorizContainer(WidgetTypeE type) {
} }
// ============================================================
// widgetScrollbarThumb
// ============================================================
void widgetScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t visibleSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize) {
*thumbSize = (trackLen * visibleSize) / totalSize;
if (*thumbSize < SB_MIN_THUMB) {
*thumbSize = SB_MIN_THUMB;
}
if (*thumbSize > trackLen) {
*thumbSize = trackLen;
}
int32_t maxScroll = totalSize - visibleSize;
if (maxScroll > 0) {
*thumbPos = ((trackLen - *thumbSize) * scrollPos) / maxScroll;
} else {
*thumbPos = 0;
}
}
// ============================================================ // ============================================================
// widgetRemoveChild // widgetRemoveChild
// ============================================================ // ============================================================

View file

@ -121,7 +121,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
while (top > 0) { while (top > 0) {
WidgetT *w = stack[--top]; WidgetT *w = stack[--top];
if (w->focused && (w->type == WidgetTextInputE || w->type == WidgetComboBoxE || w->type == WidgetDropdownE || w->type == WidgetAnsiTermE || w->type == WidgetTreeViewE || w->type == WidgetListBoxE || w->type == WidgetButtonE || w->type == WidgetImageButtonE || w->type == WidgetCheckboxE || w->type == WidgetRadioE || w->type == WidgetSliderE || w->type == WidgetTabControlE)) { if (w->focused && widgetIsFocusable(w->type)) {
focus = w; focus = w;
break; break;
} }
@ -302,13 +302,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
} }
// Clamp // Clamp
if (focus->as.slider.value < focus->as.slider.minValue) { focus->as.slider.value = clampInt(focus->as.slider.value, focus->as.slider.minValue, focus->as.slider.maxValue);
focus->as.slider.value = focus->as.slider.minValue;
}
if (focus->as.slider.value > focus->as.slider.maxValue) {
focus->as.slider.value = focus->as.slider.maxValue;
}
if (focus->onChange) { if (focus->onChange) {
focus->onChange(focus); focus->onChange(focus);

View file

@ -39,6 +39,17 @@
#define TREE_BORDER 2 #define TREE_BORDER 2
#define TREE_SB_W 14 #define TREE_SB_W 14
#define TREE_MIN_ROWS 4 #define TREE_MIN_ROWS 4
#define SB_MIN_THUMB 14
// ============================================================
// Inline helpers
// ============================================================
static inline int32_t clampInt(int32_t val, int32_t lo, int32_t hi) {
if (val < lo) { return lo; }
if (val > hi) { return hi; }
return val;
}
// ============================================================ // ============================================================
// Shared state (defined in widgetCore.c) // Shared state (defined in widgetCore.c)
@ -71,6 +82,7 @@ bool widgetIsFocusable(WidgetTypeE type);
bool widgetIsBoxContainer(WidgetTypeE type); bool widgetIsBoxContainer(WidgetTypeE type);
bool widgetIsHorizContainer(WidgetTypeE type); bool widgetIsHorizContainer(WidgetTypeE type);
void widgetRemoveChild(WidgetT *parent, WidgetT *child); void widgetRemoveChild(WidgetT *parent, WidgetT *child);
void widgetScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t visibleSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize);
// ============================================================ // ============================================================
// Layout functions (widgetLayout.c) // Layout functions (widgetLayout.c)

View file

@ -8,38 +8,6 @@
#define LISTBOX_SB_W 14 #define LISTBOX_SB_W 14
// ============================================================
// Prototypes
// ============================================================
static void listBoxScrollbarThumb(int32_t trackLen, int32_t totalItems, int32_t visibleItems, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize);
// ============================================================
// listBoxScrollbarThumb
// ============================================================
static void listBoxScrollbarThumb(int32_t trackLen, int32_t totalItems, int32_t visibleItems, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize) {
*thumbSize = (trackLen * visibleItems) / totalItems;
if (*thumbSize < LISTBOX_SB_W) {
*thumbSize = LISTBOX_SB_W;
}
if (*thumbSize > trackLen) {
*thumbSize = trackLen;
}
int32_t maxScroll = totalItems - visibleItems;
if (maxScroll > 0) {
*thumbPos = ((trackLen - *thumbSize) * scrollPos) / maxScroll;
} else {
*thumbPos = 0;
}
}
// ============================================================ // ============================================================
// wgtListBox // wgtListBox
// ============================================================ // ============================================================
@ -199,13 +167,7 @@ void widgetListBoxOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy) {
maxScroll = 0; maxScroll = 0;
} }
if (hit->as.listBox.scrollPos > maxScroll) { hit->as.listBox.scrollPos = clampInt(hit->as.listBox.scrollPos, 0, maxScroll);
hit->as.listBox.scrollPos = maxScroll;
}
if (hit->as.listBox.scrollPos < 0) {
hit->as.listBox.scrollPos = 0;
}
// Check if click is on the scrollbar // Check if click is on the scrollbar
if (needSb) { if (needSb) {
@ -231,22 +193,16 @@ void widgetListBoxOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy) {
// Track — page up/down // Track — page up/down
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
listBoxScrollbarThumb(trackLen, hit->as.listBox.itemCount, visibleRows, hit->as.listBox.scrollPos, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, hit->as.listBox.itemCount, visibleRows, hit->as.listBox.scrollPos, &thumbPos, &thumbSize);
int32_t trackRelY = relY - LISTBOX_SB_W; int32_t trackRelY = relY - LISTBOX_SB_W;
if (trackRelY < thumbPos) { if (trackRelY < thumbPos) {
hit->as.listBox.scrollPos -= visibleRows; hit->as.listBox.scrollPos -= visibleRows;
hit->as.listBox.scrollPos = clampInt(hit->as.listBox.scrollPos, 0, maxScroll);
if (hit->as.listBox.scrollPos < 0) {
hit->as.listBox.scrollPos = 0;
}
} else if (trackRelY >= thumbPos + thumbSize) { } else if (trackRelY >= thumbPos + thumbSize) {
hit->as.listBox.scrollPos += visibleRows; hit->as.listBox.scrollPos += visibleRows;
hit->as.listBox.scrollPos = clampInt(hit->as.listBox.scrollPos, 0, maxScroll);
if (hit->as.listBox.scrollPos > maxScroll) {
hit->as.listBox.scrollPos = maxScroll;
}
} }
} }
@ -295,11 +251,7 @@ void widgetListBoxPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitm
} }
// Sunken border // Sunken border
BevelStyleT bevel; BevelStyleT bevel = BEVEL_SUNKEN(colors, bg, 2);
bevel.highlight = colors->windowShadow;
bevel.shadow = colors->windowHighlight;
bevel.face = bg;
bevel.width = 2;
drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel); drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel);
// Clamp scroll position // Clamp scroll position
@ -309,13 +261,7 @@ void widgetListBoxPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitm
maxScroll = 0; maxScroll = 0;
} }
if (w->as.listBox.scrollPos > maxScroll) { w->as.listBox.scrollPos = clampInt(w->as.listBox.scrollPos, 0, maxScroll);
w->as.listBox.scrollPos = maxScroll;
}
if (w->as.listBox.scrollPos < 0) {
w->as.listBox.scrollPos = 0;
}
// Draw items // Draw items
int32_t innerX = w->x + LISTBOX_BORDER + LISTBOX_PAD; int32_t innerX = w->x + LISTBOX_BORDER + LISTBOX_PAD;
@ -344,19 +290,11 @@ void widgetListBoxPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitm
int32_t sbH = innerH; int32_t sbH = innerH;
// Trough // Trough
BevelStyleT troughBevel; BevelStyleT troughBevel = BEVEL_TROUGH(colors);
troughBevel.highlight = colors->windowShadow;
troughBevel.shadow = colors->windowHighlight;
troughBevel.face = colors->scrollbarTrough;
troughBevel.width = 1;
drawBevel(d, ops, sbX, sbY, LISTBOX_SB_W, sbH, &troughBevel); drawBevel(d, ops, sbX, sbY, LISTBOX_SB_W, sbH, &troughBevel);
// Up arrow button // Up arrow button
BevelStyleT btnBevel; BevelStyleT btnBevel = BEVEL_RAISED(colors, 1);
btnBevel.highlight = colors->windowHighlight;
btnBevel.shadow = colors->windowShadow;
btnBevel.face = colors->windowFace;
btnBevel.width = 1;
drawBevel(d, ops, sbX, sbY, LISTBOX_SB_W, LISTBOX_SB_W, &btnBevel); drawBevel(d, ops, sbX, sbY, LISTBOX_SB_W, LISTBOX_SB_W, &btnBevel);
// Up arrow triangle // Up arrow triangle
@ -389,7 +327,7 @@ void widgetListBoxPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitm
if (trackLen > 0) { if (trackLen > 0) {
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
listBoxScrollbarThumb(trackLen, w->as.listBox.itemCount, visibleRows, w->as.listBox.scrollPos, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, w->as.listBox.itemCount, visibleRows, w->as.listBox.scrollPos, &thumbPos, &thumbSize);
drawBevel(d, ops, sbX, sbY + LISTBOX_SB_W + thumbPos, LISTBOX_SB_W, thumbSize, &btnBevel); drawBevel(d, ops, sbX, sbY + LISTBOX_SB_W + thumbPos, LISTBOX_SB_W, thumbSize, &btnBevel);
} }

View file

@ -19,8 +19,6 @@ static void treeCalcScrollbarNeeds(WidgetT *w, const BitmapFontT *font, int32_t
static WidgetT *treeItemAtY(WidgetT *parent, int32_t targetY, int32_t *curY, const BitmapFontT *font); static WidgetT *treeItemAtY(WidgetT *parent, int32_t targetY, int32_t *curY, const BitmapFontT *font);
static int32_t treeItemYPos(WidgetT *treeView, WidgetT *target, const BitmapFontT *font); static int32_t treeItemYPos(WidgetT *treeView, WidgetT *target, const BitmapFontT *font);
static int32_t treeItemYPosHelper(WidgetT *parent, WidgetT *target, int32_t *curY, const BitmapFontT *font); static int32_t treeItemYPosHelper(WidgetT *parent, WidgetT *target, int32_t *curY, const BitmapFontT *font);
static void treeScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t innerSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize);
// ============================================================ // ============================================================
// calcTreeItemsHeight // calcTreeItemsHeight
@ -92,19 +90,11 @@ static void drawTreeHScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
} }
// Trough background // Trough background
BevelStyleT troughBevel; BevelStyleT troughBevel = BEVEL_TROUGH(colors);
troughBevel.highlight = colors->windowShadow;
troughBevel.shadow = colors->windowHighlight;
troughBevel.face = colors->scrollbarTrough;
troughBevel.width = 1;
drawBevel(d, ops, sbX, sbY, sbW, TREE_SB_W, &troughBevel); drawBevel(d, ops, sbX, sbY, sbW, TREE_SB_W, &troughBevel);
// Left arrow button // Left arrow button
BevelStyleT btnBevel; BevelStyleT btnBevel = BEVEL_RAISED(colors, 1);
btnBevel.highlight = colors->windowHighlight;
btnBevel.shadow = colors->windowShadow;
btnBevel.face = colors->windowFace;
btnBevel.width = 1;
drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel); drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel);
// Left arrow triangle // Left arrow triangle
@ -139,7 +129,7 @@ static void drawTreeHScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
if (trackLen > 0 && totalW > 0) { if (trackLen > 0 && totalW > 0) {
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
treeScrollbarThumb(trackLen, totalW, innerW, w->as.treeView.scrollPosH, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, totalW, innerW, w->as.treeView.scrollPosH, &thumbPos, &thumbSize);
drawBevel(d, ops, sbX + TREE_SB_W + thumbPos, sbY, thumbSize, TREE_SB_W, &btnBevel); drawBevel(d, ops, sbX + TREE_SB_W + thumbPos, sbY, thumbSize, TREE_SB_W, &btnBevel);
} }
@ -165,19 +155,11 @@ static void drawTreeVScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
} }
// Trough background // Trough background
BevelStyleT troughBevel; BevelStyleT troughBevel = BEVEL_TROUGH(colors);
troughBevel.highlight = colors->windowShadow;
troughBevel.shadow = colors->windowHighlight;
troughBevel.face = colors->scrollbarTrough;
troughBevel.width = 1;
drawBevel(d, ops, sbX, sbY, TREE_SB_W, sbH, &troughBevel); drawBevel(d, ops, sbX, sbY, TREE_SB_W, sbH, &troughBevel);
// Up arrow button // Up arrow button
BevelStyleT btnBevel; BevelStyleT btnBevel = BEVEL_RAISED(colors, 1);
btnBevel.highlight = colors->windowHighlight;
btnBevel.shadow = colors->windowShadow;
btnBevel.face = colors->windowFace;
btnBevel.width = 1;
drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel); drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel);
// Up arrow triangle // Up arrow triangle
@ -212,7 +194,7 @@ static void drawTreeVScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
if (trackLen > 0 && totalH > 0) { if (trackLen > 0 && totalH > 0) {
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
treeScrollbarThumb(trackLen, totalH, innerH, w->as.treeView.scrollPos, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, totalH, innerH, w->as.treeView.scrollPos, &thumbPos, &thumbSize);
drawBevel(d, ops, sbX, sbY + TREE_SB_W + thumbPos, TREE_SB_W, thumbSize, &btnBevel); drawBevel(d, ops, sbX, sbY + TREE_SB_W + thumbPos, TREE_SB_W, thumbSize, &btnBevel);
} }
@ -549,32 +531,6 @@ static int32_t treeItemYPosHelper(WidgetT *parent, WidgetT *target, int32_t *cur
} }
// ============================================================
// treeScrollbarThumb
// ============================================================
static void treeScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t innerSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize) {
// Proportional thumb size
*thumbSize = (trackLen * innerSize) / totalSize;
if (*thumbSize < TREE_SB_W) {
*thumbSize = TREE_SB_W;
}
if (*thumbSize > trackLen) {
*thumbSize = trackLen;
}
// Thumb position
int32_t maxScroll = totalSize - innerSize;
if (maxScroll > 0) {
*thumbPos = ((trackLen - *thumbSize) * scrollPos) / maxScroll;
} else {
*thumbPos = 0;
}
}
// ============================================================ // ============================================================
// wgtTreeItem // wgtTreeItem
@ -808,6 +764,11 @@ void widgetTreeViewOnKey(WidgetT *w, int32_t key) {
// ============================================================ // ============================================================
void widgetTreeViewLayout(WidgetT *w, const BitmapFontT *font) { void widgetTreeViewLayout(WidgetT *w, const BitmapFontT *font) {
// Auto-select first item if nothing is selected
if (!w->as.treeView.selectedItem) {
w->as.treeView.selectedItem = firstVisibleItem(w);
}
int32_t totalH; int32_t totalH;
int32_t totalW; int32_t totalW;
int32_t innerH; int32_t innerH;
@ -854,21 +815,8 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
maxScrollH = 0; maxScrollH = 0;
} }
if (hit->as.treeView.scrollPos > maxScrollV) { hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, maxScrollV);
hit->as.treeView.scrollPos = maxScrollV; hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, maxScrollH);
}
if (hit->as.treeView.scrollPos < 0) {
hit->as.treeView.scrollPos = 0;
}
if (hit->as.treeView.scrollPosH > maxScrollH) {
hit->as.treeView.scrollPosH = maxScrollH;
}
if (hit->as.treeView.scrollPosH < 0) {
hit->as.treeView.scrollPosH = 0;
}
// Check if click is on the vertical scrollbar // Check if click is on the vertical scrollbar
if (needVSb) { if (needVSb) {
@ -895,7 +843,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
// Track area — page up/down based on thumb position // Track area — page up/down based on thumb position
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
treeScrollbarThumb(trackLen, totalH, innerH, hit->as.treeView.scrollPos, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, totalH, innerH, hit->as.treeView.scrollPos, &thumbPos, &thumbSize);
int32_t trackRelY = relY - TREE_SB_W; int32_t trackRelY = relY - TREE_SB_W;
@ -907,14 +855,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
} }
// Clamp after scroll // Clamp after scroll
if (hit->as.treeView.scrollPos < 0) { hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, maxScrollV);
hit->as.treeView.scrollPos = 0;
}
if (hit->as.treeView.scrollPos > maxScrollV) {
hit->as.treeView.scrollPos = maxScrollV;
}
return; return;
} }
} }
@ -944,7 +885,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
// Track area — page left/right based on thumb position // Track area — page left/right based on thumb position
int32_t thumbPos; int32_t thumbPos;
int32_t thumbSize; int32_t thumbSize;
treeScrollbarThumb(trackLen, totalW, innerW, hit->as.treeView.scrollPosH, &thumbPos, &thumbSize); widgetScrollbarThumb(trackLen, totalW, innerW, hit->as.treeView.scrollPosH, &thumbPos, &thumbSize);
int32_t trackRelX = relX - TREE_SB_W; int32_t trackRelX = relX - TREE_SB_W;
@ -956,14 +897,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
} }
// Clamp after scroll // Clamp after scroll
if (hit->as.treeView.scrollPosH < 0) { hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, maxScrollH);
hit->as.treeView.scrollPosH = 0;
}
if (hit->as.treeView.scrollPosH > maxScrollH) {
hit->as.treeView.scrollPosH = maxScrollH;
}
return; return;
} }
} }
@ -1017,27 +951,28 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
// Clamp scroll positions if collapsing reduced content size // Clamp scroll positions if collapsing reduced content size
if (!item->as.treeItem.expanded) { if (!item->as.treeItem.expanded) {
int32_t newTotalH = calcTreeItemsHeight(hit, font); int32_t newTotalH;
int32_t newMaxScrlV = newTotalH - innerH; int32_t newTotalW;
int32_t newInnerH;
int32_t newInnerW;
bool newNeedVSb;
bool newNeedHSb;
treeCalcScrollbarNeeds(hit, font, &newTotalH, &newTotalW, &newInnerH, &newInnerW, &newNeedVSb, &newNeedHSb);
int32_t newMaxScrlV = newTotalH - newInnerH;
int32_t newMaxScrlH = newTotalW - newInnerW;
if (newMaxScrlV < 0) { if (newMaxScrlV < 0) {
newMaxScrlV = 0; newMaxScrlV = 0;
} }
if (hit->as.treeView.scrollPos > newMaxScrlV) {
hit->as.treeView.scrollPos = newMaxScrlV;
}
int32_t newTotalW = calcTreeItemsMaxWidth(hit, font, 0);
int32_t newMaxScrlH = newTotalW - innerW;
if (newMaxScrlH < 0) { if (newMaxScrlH < 0) {
newMaxScrlH = 0; newMaxScrlH = 0;
} }
if (hit->as.treeView.scrollPosH > newMaxScrlH) { hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, newMaxScrlV);
hit->as.treeView.scrollPosH = newMaxScrlH; hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, newMaxScrlH);
}
} }
if (item->onChange) { if (item->onChange) {
@ -1084,28 +1019,11 @@ void widgetTreeViewPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bit
maxScrollH = 0; maxScrollH = 0;
} }
if (w->as.treeView.scrollPos > maxScrollV) { w->as.treeView.scrollPos = clampInt(w->as.treeView.scrollPos, 0, maxScrollV);
w->as.treeView.scrollPos = maxScrollV; w->as.treeView.scrollPosH = clampInt(w->as.treeView.scrollPosH, 0, maxScrollH);
}
if (w->as.treeView.scrollPos < 0) {
w->as.treeView.scrollPos = 0;
}
if (w->as.treeView.scrollPosH > maxScrollH) {
w->as.treeView.scrollPosH = maxScrollH;
}
if (w->as.treeView.scrollPosH < 0) {
w->as.treeView.scrollPosH = 0;
}
// Sunken border // Sunken border
BevelStyleT bevel; BevelStyleT bevel = BEVEL_SUNKEN(colors, bg, 2);
bevel.highlight = colors->windowShadow;
bevel.shadow = colors->windowHighlight;
bevel.face = bg;
bevel.width = 2;
drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel); drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel);
// Set clip rect to inner content area (excludes scrollbars) // Set clip rect to inner content area (excludes scrollbars)

View file

@ -471,7 +471,7 @@ int main(int argc, char *argv[]) {
int rc = secLinkSend(link, clean, cleanLen, CHANNEL_TERMINAL, true, false); int rc = secLinkSend(link, clean, cleanLen, CHANNEL_TERMINAL, true, false);
while (rc != SECLINK_SUCCESS && sRunning) { while (rc != SECLINK_SUCCESS && sRunning) {
secLinkPoll(link); secLinkPoll(link);
usleep(1000); usleep(10000);
rc = secLinkSend(link, clean, cleanLen, CHANNEL_TERMINAL, true, false); rc = secLinkSend(link, clean, cleanLen, CHANNEL_TERMINAL, true, false);
} }
} }