diff --git a/darwin/slider.m b/darwin/slider.m index 6f5c5a76..62fa2177 100644 --- a/darwin/slider.m +++ b/darwin/slider.m @@ -26,8 +26,11 @@ struct uiSlider { NSSlider *slider; void (*onChanged)(uiSlider *, void *); void *onChangedData; + bool hasTooltip; }; +static void _uiSliderUpdateTooltip(uiSlider *s); + @interface sliderDelegateClass : NSObject { uiprivMap *sliders; } @@ -58,6 +61,9 @@ struct uiSlider { s = (uiSlider *) uiprivMapGet(self->sliders, sender); (*(s->onChanged))(s, s->onChangedData); + + if (s->hasTooltip) + _uiSliderUpdateTooltip(s); } - (void)registerSlider:(uiSlider *)s @@ -88,6 +94,26 @@ static void uiSliderDestroy(uiControl *c) uiFreeControl(uiControl(s)); } +static void _uiSliderUpdateTooltip(uiSlider *s) +{ + [s->slider setToolTip:[NSString stringWithFormat:@"%ld", [s->slider integerValue]]]; +} + +int uiSliderHasTooltip(uiSlider *s) +{ + return s->hasTooltip; +} + +void uiSliderSetHasTooltip(uiSlider *s, int hasTooltip) +{ + s->hasTooltip = hasTooltip; + + if (hasTooltip) + _uiSliderUpdateTooltip(s); + else + [s->slider setToolTip:nil]; +} + int uiSliderValue(uiSlider *s) { return [s->slider integerValue]; @@ -143,5 +169,7 @@ uiSlider *uiNewSlider(int min, int max) [sliderDelegate registerSlider:s]; uiSliderOnChanged(s, defaultOnChanged, NULL); + uiSliderSetHasTooltip(s, 1); + return s; } diff --git a/test/page4.c b/test/page4.c index ce4a6afb..7c85b9c1 100644 --- a/test/page4.c +++ b/test/page4.c @@ -4,6 +4,7 @@ static uiSpinbox *spinbox; static uiSlider *slider; static uiProgressBar *pbar; +static uiCheckbox *checkbox; #define CHANGED(what) \ static void on ## what ## Changed(ui ## what *this, void *data) \ @@ -75,6 +76,18 @@ static void selectNone(uiButton *b, void *data) uiRadioButtonsSetSelected(rb, -1); } +static void sliderEnableTooltip(uiButton *b, void *data) +{ + uiSliderSetHasTooltip(uiSlider(data), 1); + uiCheckboxSetChecked(checkbox, uiSliderHasTooltip(uiSlider(data))); +} + +static void sliderDisableTooltip(uiButton *b, void *data) +{ + uiSliderSetHasTooltip(uiSlider(data), 0); + uiCheckboxSetChecked(checkbox, uiSliderHasTooltip(uiSlider(data))); +} + uiBox *makePage4(void) { uiBox *page4; @@ -93,6 +106,21 @@ uiBox *makePage4(void) uiSliderOnChanged(slider, onSliderChanged, NULL); uiBoxAppend(page4, uiControl(slider), 0); + hbox = newHorizontalBox(); + slider = uiNewSlider(0, 100); + uiBoxAppend(hbox, uiControl(slider), 1); + b = uiNewButton("Enable Tooltip"); + uiButtonOnClicked(b, sliderEnableTooltip, slider); + uiBoxAppend(hbox, uiControl(b), 0); + b = uiNewButton("Disable Tooltip"); + uiButtonOnClicked(b, sliderDisableTooltip, slider); + uiBoxAppend(hbox, uiControl(b), 0); + checkbox = uiNewCheckbox("Has Tooltip"); + uiControlDisable(uiControl(checkbox)); + uiCheckboxSetChecked(checkbox, uiSliderHasTooltip(slider)); + uiBoxAppend(hbox, uiControl(checkbox), 0); + uiBoxAppend(page4, uiControl(hbox), 0); + pbar = uiNewProgressBar(); uiBoxAppend(page4, uiControl(pbar), 0); diff --git a/ui.h b/ui.h index 40aea949..d46ba8b8 100644 --- a/ui.h +++ b/ui.h @@ -209,6 +209,8 @@ typedef struct uiSlider uiSlider; #define uiSlider(this) ((uiSlider *) (this)) _UI_EXTERN int uiSliderValue(uiSlider *s); _UI_EXTERN void uiSliderSetValue(uiSlider *s, int value); +_UI_EXTERN int uiSliderHasTooltip(uiSlider *s); +_UI_EXTERN void uiSliderSetHasTooltip(uiSlider *s, int hasTooltip); _UI_EXTERN void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *s, void *data), void *data); _UI_EXTERN uiSlider *uiNewSlider(int min, int max); diff --git a/unix/slider.c b/unix/slider.c index 7f0cc24a..fd0987fe 100644 --- a/unix/slider.c +++ b/unix/slider.c @@ -1,6 +1,12 @@ // 11 june 2015 #include "uipriv_unix.h" +/* Number of digits to represent an n-bit number in decimal: log10(2^n) + * Simplify, truncate & add 1 for full digits, add 1 for negative numbers: + * -> n log10(2) + 2 <= n * 0.302 + 2 + */ +#define MAX_STRLEN_FOR_NBITS_IN_DECIMAL(n) ((int)((n) * 302 / 1000) + 2) + struct uiSlider { uiUnixControl c; GtkWidget *widget; @@ -9,15 +15,25 @@ struct uiSlider { void (*onChanged)(uiSlider *, void *); void *onChangedData; gulong onChangedSignal; + gchar tooltip[MAX_STRLEN_FOR_NBITS_IN_DECIMAL(sizeof(int) * CHAR_BIT) + 1]; }; uiUnixControlAllDefaults(uiSlider) +static void _uiSliderUpdateTooltip(uiSlider *s) +{ + g_snprintf(s->tooltip, sizeof(s->tooltip)/sizeof(s->tooltip[0]), "%d", uiSliderValue(s)); + gtk_widget_set_tooltip_text(s->widget, s->tooltip); +} + static void onChanged(GtkRange *range, gpointer data) { uiSlider *s = uiSlider(data); (*(s->onChanged))(s, s->onChangedData); + + if (uiSliderHasTooltip(s)) + _uiSliderUpdateTooltip(s); } static void defaultOnChanged(uiSlider *s, void *data) @@ -38,6 +54,19 @@ void uiSliderSetValue(uiSlider *s, int value) g_signal_handler_unblock(s->range, s->onChangedSignal); } +int uiSliderHasTooltip(uiSlider *s) +{ + return gtk_widget_get_has_tooltip(s->widget); +} + +void uiSliderSetHasTooltip(uiSlider *s, int hasTooltip) +{ + gtk_widget_set_has_tooltip(s->widget, hasTooltip); + + if (hasTooltip) + _uiSliderUpdateTooltip(s); +} + void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) { s->onChanged = f; @@ -61,6 +90,10 @@ uiSlider *uiNewSlider(int min, int max) s->range = GTK_RANGE(s->widget); s->scale = GTK_SCALE(s->widget); + // do not draw value, show tooltip instead + gtk_scale_set_draw_value(s->scale, 0); + uiSliderSetHasTooltip(s, 1); + // ensure integers, just to be safe gtk_scale_set_digits(s->scale, 0); diff --git a/windows/slider.cpp b/windows/slider.cpp index 5c671dda..5654db3e 100644 --- a/windows/slider.cpp +++ b/windows/slider.cpp @@ -6,6 +6,7 @@ struct uiSlider { HWND hwnd; void (*onChanged)(uiSlider *, void *); void *onChangedData; + HWND hwndTooltip; }; static BOOL onWM_HSCROLL(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) @@ -21,6 +22,9 @@ static void uiSliderDestroy(uiControl *c) { uiSlider *s = uiSlider(c); + // ensure TRACKBAR_CLASSW takes care of destroying the tooltip + uiSliderSetHasTooltip(s, 1); + uiWindowsUnregisterWM_HSCROLLHandler(s->hwnd); uiWindowsEnsureDestroyWindow(s->hwnd); uiFreeControl(uiControl(s)); @@ -46,6 +50,19 @@ static void uiSliderMinimumSize(uiWindowsControl *c, int *width, int *height) *height = y; } +int uiSliderHasTooltip(uiSlider *s) +{ + return ((HWND) SendMessage(s->hwnd, TBM_GETTOOLTIPS, 0, 0) == s->hwndTooltip); +} + +void uiSliderSetHasTooltip(uiSlider *s, int hasTooltip) +{ + if (hasTooltip) + SendMessage(s->hwnd, TBM_SETTOOLTIPS, (WPARAM) s->hwndTooltip, 0); + else + SendMessage(s->hwnd, TBM_SETTOOLTIPS, 0, 0); +} + static void defaultOnChanged(uiSlider *s, void *data) { // do nothing @@ -94,5 +111,7 @@ uiSlider *uiNewSlider(int min, int max) SendMessageW(s->hwnd, TBM_SETRANGEMAX, (WPARAM) TRUE, (LPARAM) max); SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) min); + s->hwndTooltip = (HWND) SendMessage(s->hwnd, TBM_GETTOOLTIPS, 0, 0); + return s; }