DVX_GUI/dvx/widgets/widgetSlider.c

200 lines
6.2 KiB
C

// 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);
}
}