200 lines
6.2 KiB
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);
|
|
}
|
|
}
|