// widgetSlider.c — Slider (trackbar) widget #include "widgetInternal.h" // ============================================================ // wgtSlider // ============================================================ WidgetT *wgtSlider(WidgetT *parent, int32_t minVal, int32_t maxVal) { WidgetT *w = widgetAlloc(parent, WidgetSliderE); if (w) { w->as.slider.value = minVal; w->as.slider.minValue = minVal; w->as.slider.maxValue = maxVal; w->as.slider.vertical = false; w->weight = 100; } return w; } // ============================================================ // wgtSliderGetValue // ============================================================ int32_t wgtSliderGetValue(const WidgetT *w) { if (!w || w->type != WidgetSliderE) { return 0; } return w->as.slider.value; } // ============================================================ // wgtSliderSetValue // ============================================================ void wgtSliderSetValue(WidgetT *w, int32_t value) { if (!w || w->type != WidgetSliderE) { return; } if (value < w->as.slider.minValue) { value = w->as.slider.minValue; } if (value > w->as.slider.maxValue) { value = w->as.slider.maxValue; } w->as.slider.value = value; } // ============================================================ // widgetSliderCalcMinSize // ============================================================ void widgetSliderCalcMinSize(WidgetT *w, const BitmapFontT *font) { (void)font; if (w->as.slider.vertical) { w->calcMinW = SLIDER_THUMB_W + 4; w->calcMinH = SLIDER_THUMB_W * 5; } else { w->calcMinW = SLIDER_THUMB_W * 5; w->calcMinH = SLIDER_THUMB_W + 4; } } // ============================================================ // widgetSliderOnMouse // ============================================================ void widgetSliderOnMouse(WidgetT *hit, int32_t vx, int32_t vy) { int32_t range = hit->as.slider.maxValue - hit->as.slider.minValue; if (range <= 0) { return; } int32_t thumbRange; int32_t thumbPos; int32_t mousePos; if (hit->as.slider.vertical) { thumbRange = hit->h - SLIDER_THUMB_W; thumbPos = ((hit->as.slider.value - hit->as.slider.minValue) * thumbRange) / range; mousePos = vy - hit->y; if (mousePos >= thumbPos && mousePos < thumbPos + SLIDER_THUMB_W) { // Click on thumb — start drag sDragSlider = hit; sDragOffset = mousePos - thumbPos; } else { // Click on track — jump to position int32_t newVal = hit->as.slider.minValue + ((mousePos - SLIDER_THUMB_W / 2) * range) / thumbRange; if (newVal < hit->as.slider.minValue) { newVal = hit->as.slider.minValue; } if (newVal > hit->as.slider.maxValue) { newVal = hit->as.slider.maxValue; } hit->as.slider.value = newVal; if (hit->onChange) { hit->onChange(hit); } } } else { thumbRange = hit->w - SLIDER_THUMB_W; thumbPos = ((hit->as.slider.value - hit->as.slider.minValue) * thumbRange) / range; mousePos = vx - hit->x; if (mousePos >= thumbPos && mousePos < thumbPos + SLIDER_THUMB_W) { // Click on thumb — start drag sDragSlider = hit; sDragOffset = mousePos - thumbPos; } else { // Click on track — jump to position int32_t newVal = hit->as.slider.minValue + ((mousePos - SLIDER_THUMB_W / 2) * range) / thumbRange; if (newVal < hit->as.slider.minValue) { newVal = hit->as.slider.minValue; } if (newVal > hit->as.slider.maxValue) { newVal = hit->as.slider.maxValue; } hit->as.slider.value = newVal; if (hit->onChange) { hit->onChange(hit); } } } } // ============================================================ // widgetSliderPaint // ============================================================ void widgetSliderPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) { (void)font; uint32_t fg = w->fgColor ? w->fgColor : colors->contentFg; int32_t range = w->as.slider.maxValue - w->as.slider.minValue; if (range <= 0) { range = 1; } if (w->as.slider.vertical) { // Track groove int32_t trackX = w->x + (w->w - SLIDER_TRACK_H) / 2; BevelStyleT groove; groove.highlight = colors->windowShadow; groove.shadow = colors->windowHighlight; groove.face = colors->scrollbarTrough; groove.width = 1; drawBevel(d, ops, trackX, w->y, SLIDER_TRACK_H, w->h, &groove); // Thumb int32_t thumbRange = w->h - SLIDER_THUMB_W; int32_t thumbY = w->y + ((w->as.slider.value - w->as.slider.minValue) * thumbRange) / range; BevelStyleT thumb; thumb.highlight = colors->windowHighlight; thumb.shadow = colors->windowShadow; thumb.face = colors->buttonFace; thumb.width = 2; drawBevel(d, ops, w->x, thumbY, w->w, SLIDER_THUMB_W, &thumb); // Center tick on thumb drawHLine(d, ops, w->x + 3, thumbY + SLIDER_THUMB_W / 2, w->w - 6, fg); } else { // Track groove int32_t trackY = w->y + (w->h - SLIDER_TRACK_H) / 2; BevelStyleT groove; groove.highlight = colors->windowShadow; groove.shadow = colors->windowHighlight; groove.face = colors->scrollbarTrough; groove.width = 1; drawBevel(d, ops, w->x, trackY, w->w, SLIDER_TRACK_H, &groove); // Thumb int32_t thumbRange = w->w - SLIDER_THUMB_W; int32_t thumbX = w->x + ((w->as.slider.value - w->as.slider.minValue) * thumbRange) / range; BevelStyleT thumb; thumb.highlight = colors->windowHighlight; thumb.shadow = colors->windowShadow; thumb.face = colors->buttonFace; thumb.width = 2; drawBevel(d, ops, thumbX, w->y, SLIDER_THUMB_W, w->h, &thumb); // Center tick on thumb drawVLine(d, ops, thumbX + SLIDER_THUMB_W / 2, w->y + 3, w->h - 6, fg); } }