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

View file

@ -10,7 +10,6 @@
char accelParse(const char *text);
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 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);

View file

@ -77,6 +77,11 @@ typedef struct {
int32_t width; // border thickness in pixels (typically 2)
} 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
// ============================================================

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 int32_t mapLfb(DisplayT *d, uint32_t physAddr);
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
if (bpp != 8 && bpp != 15 && bpp != 16 && bpp != 32) {
// Some cards report 24-bit; skip those
if (bpp == 24) {
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.blueShift = 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)
@ -404,7 +390,7 @@ int32_t videoInit(DisplayT *d, int32_t requestedW, int32_t requestedH, int32_t p
// 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
// Port 0x3C8 = write index, Port 0x3C9 = data (R, G, B in 6-bit values)
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
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

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);
// ============================================================
// 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
// ============================================================
@ -36,13 +65,7 @@ static void canvasDrawDot(WidgetT *w, int32_t cx, int32_t cy) {
if (cx >= 0 && cx < cw && cy >= 0 && cy < ch) {
uint8_t *dst = data + cy * pitch + cx * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
return;
@ -68,13 +91,7 @@ static void canvasDrawDot(WidgetT *w, int32_t cx, int32_t cy) {
if (dx * dx + dy * dy <= r2) {
uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
}
@ -186,13 +203,7 @@ WidgetT *wgtCanvas(WidgetT *parent, int32_t w, int32_t h) {
for (int32_t x = 0; x < w; x++) {
uint8_t *dst = data + y * pitch + x * bpp;
if (bpp == 1) {
*dst = (uint8_t)white;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)white;
} else {
*(uint32_t *)dst = white;
}
canvasPutPixel(dst, white, bpp);
}
}
@ -233,13 +244,7 @@ void wgtCanvasClear(WidgetT *w, uint32_t color) {
for (int32_t x = 0; x < cw; x++) {
uint8_t *dst = w->as.canvas.data + y * pitch + x * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
}
@ -291,13 +296,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (y >= 0 && y < ch) {
uint8_t *dst = data + y * pitch + px * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
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) {
uint8_t *dst = data + by * pitch + px * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
@ -324,13 +317,7 @@ void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t
if (x >= 0 && x < cw) {
uint8_t *dst = data + py * pitch + x * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
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) {
uint8_t *dst = data + py * pitch + rx * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
}
@ -390,13 +371,7 @@ void wgtCanvasFillCircle(WidgetT *w, int32_t cx, int32_t cy, int32_t radius) {
if (dx * dx + dy * dy <= r2) {
uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
}
@ -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++) {
uint8_t *dst = data + py * pitch + px * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
}
@ -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;
const uint8_t *src = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp;
if (bpp == 1) {
return *src;
} else if (bpp == 2) {
return *(const uint16_t *)src;
} else {
return *(const uint32_t *)src;
}
return canvasGetPixel(src, bpp);
}
@ -521,13 +484,7 @@ int32_t wgtCanvasLoad(WidgetT *w, const char *path) {
uint32_t color = packColor(d, src[0], src[1], src[2]);
uint8_t *dst = data + y * pitch + x * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}
}
@ -581,15 +538,7 @@ int32_t wgtCanvasSave(WidgetT *w, const char *path) {
for (int32_t y = 0; y < ch; y++) {
for (int32_t x = 0; x < cw; x++) {
const uint8_t *src = w->as.canvas.data + y * pitch + x * bpp;
uint32_t pixel;
if (bpp == 1) {
pixel = *src;
} else if (bpp == 2) {
pixel = *(const uint16_t *)src;
} else {
pixel = *(const uint32_t *)src;
}
uint32_t pixel = canvasGetPixel(src, bpp);
uint8_t *dst = rgb + (y * cw + x) * 3;
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;
uint8_t *dst = w->as.canvas.data + y * w->as.canvas.canvasPitch + x * bpp;
if (bpp == 1) {
*dst = (uint8_t)color;
} else if (bpp == 2) {
*(uint16_t *)dst = (uint16_t)color;
} else {
*(uint32_t *)dst = color;
}
canvasPutPixel(dst, color, bpp);
}

View file

@ -394,9 +394,9 @@ bool widgetIsFocusable(WidgetTypeE type) {
return type == WidgetTextInputE || type == WidgetComboBoxE ||
type == WidgetDropdownE || type == WidgetCheckboxE ||
type == WidgetRadioE || type == WidgetButtonE ||
type == WidgetSliderE || type == WidgetListBoxE ||
type == WidgetTreeViewE || type == WidgetAnsiTermE ||
type == WidgetTabControlE;
type == WidgetImageButtonE || type == WidgetSliderE ||
type == WidgetListBoxE || type == WidgetTreeViewE ||
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
// ============================================================

View file

@ -121,7 +121,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
while (top > 0) {
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;
break;
}
@ -302,13 +302,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
}
// Clamp
if (focus->as.slider.value < focus->as.slider.minValue) {
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;
}
focus->as.slider.value = clampInt(focus->as.slider.value, focus->as.slider.minValue, focus->as.slider.maxValue);
if (focus->onChange) {
focus->onChange(focus);

View file

@ -39,6 +39,17 @@
#define TREE_BORDER 2
#define TREE_SB_W 14
#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)
@ -71,6 +82,7 @@ bool widgetIsFocusable(WidgetTypeE type);
bool widgetIsBoxContainer(WidgetTypeE type);
bool widgetIsHorizContainer(WidgetTypeE type);
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)

View file

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

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 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 void treeScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t innerSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize);
// ============================================================
// calcTreeItemsHeight
@ -92,19 +90,11 @@ static void drawTreeHScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
}
// Trough background
BevelStyleT troughBevel;
troughBevel.highlight = colors->windowShadow;
troughBevel.shadow = colors->windowHighlight;
troughBevel.face = colors->scrollbarTrough;
troughBevel.width = 1;
BevelStyleT troughBevel = BEVEL_TROUGH(colors);
drawBevel(d, ops, sbX, sbY, sbW, TREE_SB_W, &troughBevel);
// Left arrow button
BevelStyleT btnBevel;
btnBevel.highlight = colors->windowHighlight;
btnBevel.shadow = colors->windowShadow;
btnBevel.face = colors->windowFace;
btnBevel.width = 1;
BevelStyleT btnBevel = BEVEL_RAISED(colors, 1);
drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel);
// Left arrow triangle
@ -139,7 +129,7 @@ static void drawTreeHScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
if (trackLen > 0 && totalW > 0) {
int32_t thumbPos;
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);
}
@ -165,19 +155,11 @@ static void drawTreeVScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
}
// Trough background
BevelStyleT troughBevel;
troughBevel.highlight = colors->windowShadow;
troughBevel.shadow = colors->windowHighlight;
troughBevel.face = colors->scrollbarTrough;
troughBevel.width = 1;
BevelStyleT troughBevel = BEVEL_TROUGH(colors);
drawBevel(d, ops, sbX, sbY, TREE_SB_W, sbH, &troughBevel);
// Up arrow button
BevelStyleT btnBevel;
btnBevel.highlight = colors->windowHighlight;
btnBevel.shadow = colors->windowShadow;
btnBevel.face = colors->windowFace;
btnBevel.width = 1;
BevelStyleT btnBevel = BEVEL_RAISED(colors, 1);
drawBevel(d, ops, sbX, sbY, TREE_SB_W, TREE_SB_W, &btnBevel);
// Up arrow triangle
@ -212,7 +194,7 @@ static void drawTreeVScrollbar(WidgetT *w, DisplayT *d, const BlitOpsT *ops, con
if (trackLen > 0 && totalH > 0) {
int32_t thumbPos;
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);
}
@ -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
@ -808,6 +764,11 @@ void widgetTreeViewOnKey(WidgetT *w, int32_t key) {
// ============================================================
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 totalW;
int32_t innerH;
@ -854,21 +815,8 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
maxScrollH = 0;
}
if (hit->as.treeView.scrollPos > maxScrollV) {
hit->as.treeView.scrollPos = maxScrollV;
}
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;
}
hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, maxScrollV);
hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, maxScrollH);
// Check if click is on the vertical scrollbar
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
int32_t thumbPos;
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;
@ -907,14 +855,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
}
// Clamp after scroll
if (hit->as.treeView.scrollPos < 0) {
hit->as.treeView.scrollPos = 0;
}
if (hit->as.treeView.scrollPos > maxScrollV) {
hit->as.treeView.scrollPos = maxScrollV;
}
hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, maxScrollV);
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
int32_t thumbPos;
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;
@ -956,14 +897,7 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
}
// Clamp after scroll
if (hit->as.treeView.scrollPosH < 0) {
hit->as.treeView.scrollPosH = 0;
}
if (hit->as.treeView.scrollPosH > maxScrollH) {
hit->as.treeView.scrollPosH = maxScrollH;
}
hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, maxScrollH);
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
if (!item->as.treeItem.expanded) {
int32_t newTotalH = calcTreeItemsHeight(hit, font);
int32_t newMaxScrlV = newTotalH - innerH;
int32_t newTotalH;
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) {
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) {
newMaxScrlH = 0;
}
if (hit->as.treeView.scrollPosH > newMaxScrlH) {
hit->as.treeView.scrollPosH = newMaxScrlH;
}
hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, newMaxScrlV);
hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, newMaxScrlH);
}
if (item->onChange) {
@ -1084,28 +1019,11 @@ void widgetTreeViewPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bit
maxScrollH = 0;
}
if (w->as.treeView.scrollPos > maxScrollV) {
w->as.treeView.scrollPos = maxScrollV;
}
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;
}
w->as.treeView.scrollPos = clampInt(w->as.treeView.scrollPos, 0, maxScrollV);
w->as.treeView.scrollPosH = clampInt(w->as.treeView.scrollPosH, 0, maxScrollH);
// Sunken border
BevelStyleT bevel;
bevel.highlight = colors->windowShadow;
bevel.shadow = colors->windowHighlight;
bevel.face = bg;
bevel.width = 2;
BevelStyleT bevel = BEVEL_SUNKEN(colors, bg, 2);
drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel);
// 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);
while (rc != SECLINK_SUCCESS && sRunning) {
secLinkPoll(link);
usleep(1000);
usleep(10000);
rc = secLinkSend(link, clean, cleanLen, CHANNEL_TERMINAL, true, false);
}
}