From 56e0037d46458a47493b4c9636aefb7fad3cc8d0 Mon Sep 17 00:00:00 2001 From: Angelo Haller Date: Fri, 21 Sep 2018 14:20:30 -0500 Subject: [PATCH 1/2] Make slider tooltip default on all platforms and add enable/disable functions. Introduce two new API functions uiSliderHasTooltip and uiSliderSetHasTooltip to query and set uiSlider tooltip state. Fix inconsistency between windows (tooltip), unix (value over slider) and darwin (no value displayed at all). --- darwin/slider.m | 28 ++++++++++++++++++++++++++++ ui.h | 2 ++ unix/slider.c | 33 +++++++++++++++++++++++++++++++++ windows/slider.cpp | 19 +++++++++++++++++++ 4 files changed, 82 insertions(+) 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/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; } From d7b1ecef0e89944fde52bd391cb483429080a053 Mon Sep 17 00:00:00 2001 From: Angelo Haller Date: Sat, 22 Sep 2018 10:32:30 -0500 Subject: [PATCH 2/2] Add test case for uiSliderHasTooltip and uiSliderSetHasTooltip. --- test/page4.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) 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);