Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions demo/common/overview.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,10 @@ overview(struct nk_context *ctx)
const struct nk_input *in = &ctx->input;
struct nk_rect bounds;

/* seconds */
static float delay_timer = 0.0;
static nk_bool clicked = nk_false;

/* menu contextual */
nk_layout_row_static(ctx, 30, 160, 1);
bounds = nk_widget_bounds(ctx);
Expand Down Expand Up @@ -846,6 +850,24 @@ overview(struct nk_context *ctx)
if (nk_input_is_mouse_hovering_rect(in, bounds)) {
nk_tooltip(ctx, "This is a default tooltip");
}

bounds = nk_widget_bounds(ctx);
nk_label(ctx, "Hover motionless for a default delayed tooltip", NK_TEXT_LEFT);
nk_do_tooltip_delay(ctx, "This is a delayed tooltip", bounds, &delay_timer);

bounds = nk_widget_bounds(ctx);
nk_label(ctx, "Hover motionless longer a custom delayed tooltip", NK_TEXT_LEFT);
if (nk_input_is_mouse_hovering_still_delay_rect(ctx, bounds, &delay_timer, 1.5)) {
nk_tooltip(ctx, "This is a custom delayed tooltip");
}

bounds = nk_widget_bounds(ctx);
if (nk_button_label(ctx, "Delayed tooltip with click sensitivity")) {
clicked = nk_true;
}
nk_do_tooltip_delay_clicked(ctx, "disappears when clicked, timer starts when you move again", bounds, &delay_timer, &clicked);


bounds = nk_widget_bounds(ctx);
nk_label(ctx, "Hover for Gnome-like tooltip", NK_TEXT_LEFT);
if (nk_input_is_mouse_hovering_rect(in, bounds)) {
Expand Down
183 changes: 182 additions & 1 deletion nuklear.h
Original file line number Diff line number Diff line change
Expand Up @@ -3836,6 +3836,9 @@ NK_API void nk_contextual_end(struct nk_context*);
* ============================================================================= */
NK_API void nk_tooltip(struct nk_context*, const char*);
NK_API void nk_tooltip_offset(struct nk_context *ctx, const char *text, enum nk_tooltip_pos position, struct nk_vec2 offset);
NK_API void nk_do_tooltip(struct nk_context*, const char*, struct nk_rect);
NK_API void nk_do_tooltip_delay(struct nk_context*, const char*, struct nk_rect, float*);
NK_API void nk_do_tooltip_delay_clicked(struct nk_context*, const char*, struct nk_rect, float* timer, nk_bool*);
#ifdef NK_INCLUDE_STANDARD_VARARGS
NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
Expand Down Expand Up @@ -4961,6 +4964,10 @@ NK_API nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, en
NK_API nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_still_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_delay_rect(const struct nk_context*, struct nk_rect, float*, float);
NK_API nk_bool nk_input_is_mouse_hovering_still_delay_rect(const struct nk_context*, struct nk_rect, float*, float);
NK_API nk_bool nk_input_is_mouse_hovering_still_delay_clicked_rect(const struct nk_context*, struct nk_rect, float*, float, nk_bool*);
NK_API nk_bool nk_input_is_mouse_moved(const struct nk_input*);
NK_API nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
Expand Down Expand Up @@ -5596,6 +5603,7 @@ struct nk_style_window {

enum nk_tooltip_pos tooltip_origin;
struct nk_vec2 tooltip_offset;
float tooltip_delay;
};

struct nk_style {
Expand Down Expand Up @@ -18451,6 +18459,139 @@ nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
if (!i) return nk_false;
return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
}

/**
* # nk_input_is_mouse_hovering_still_rect
* Returns true if the mouse is hovering over rect and hasn't moved since the last
* frame, false otherwise.
*/
NK_API nk_bool
nk_input_is_mouse_hovering_still_rect(const struct nk_input *i, struct nk_rect rect)
{
if (!i) return nk_false;
return (NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h) &&
!nk_input_is_mouse_moved(i));
}

/**
* # nk_input_is_mouse_hovering_delay_rect
* Returns true if the mouse has been hovering over rect for `delay` seconds or more.
*
* Parameter | Description
* ------------|---------------------------------------------------------------
* \param[in] ctx | Must point to an either stack or heap allocated `nk_context` struct
* \param[in] rect | The rect area you're checking against
* \param[in|out] timer | Must point to a float used to track the total seconds hovered across frames
* \param[in] delay | The wait time in seconds
*
* \returns `true` if the the mouse has hovered long enough, `false otherwise`
*/
NK_API nk_bool
nk_input_is_mouse_hovering_delay_rect(const struct nk_context *ctx, struct nk_rect rect, float* timer, float delay)
{
NK_ASSERT(ctx);
if (!ctx) {
return nk_false;
} else {
const struct nk_input* i = &ctx->input;
if (NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h)) {
*timer += ctx->delta_time_seconds;
return *timer >= delay;
} else if (NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h)) {
*timer = 0;
}
return nk_false;
}

}

/**
* # nk_input_is_mouse_hovering_still_delay_rect
* Returns true if the mouse has been hovering motionless over rect for `delay` seconds or more. The timer
* does not reset once the delay is reached as long as you are still hovering over the rect.
*
* Parameter | Description
* ------------|---------------------------------------------------------------
* \param[in] ctx | Must point to an either stack or heap allocated `nk_context` struct
* \param[in] rect | The rect area you're checking against
* \param[in|out] timer | Must point to a float used to track the total seconds hovered across frames
* \param[in] delay | The wait time in seconds
*
* \returns `true` if the the mouse has hovered without moving long enough, `false otherwise`
*/
NK_API nk_bool
nk_input_is_mouse_hovering_still_delay_rect(const struct nk_context *ctx, struct nk_rect rect, float* timer, float delay)
{
NK_ASSERT(ctx);
if (!ctx) {
return nk_false;
} else {
const struct nk_input* i = &ctx->input;
if (NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h)) {
/* once it triggers, moving within the bounds should not make it disappear */
if (*timer >= delay) {
return nk_true;
}
if (!nk_input_is_mouse_moved(i)) {
*timer += ctx->delta_time_seconds;
return *timer >= delay;
}
*timer = 0;
} else if (NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h)) {
*timer = 0;
}
return nk_false;
}
}

/**
* # nk_input_is_mouse_hovering_still_delay_clicked_rect
* Works the same as `nk_input_is_mouse_hovering_still_delay_rect` unless clicked is set. If clicked is true,
* then it returns false regardless of the timer value as long as the mouse is motionless. It goes back to working
* as normal once the mouse has moved (clicked is set to false, timer to 0).
*
* Parameter | Description
* ------------|---------------------------------------------------------------
* \param[in] ctx | Must point to an either stack or heap allocated `nk_context` struct
* \param[in] rect | The rect area you're checking against
* \param[in|out] timer | Must point to a float used to track the total seconds hovered across frames
* \param[in] delay | The wait time in seconds
* \param[in|out] clicked | Must point to an nk_bool used to indicate whether the item in question has been clicked (reset to false internally on mouse motion)
*
* \returns `true` if the the mouse has hovered without moving long enough, `false otherwise`
*/
NK_API nk_bool
nk_input_is_mouse_hovering_still_delay_clicked_rect(const struct nk_context *ctx, struct nk_rect rect, float* timer, float delay, nk_bool* clicked)
{
NK_ASSERT(ctx);
if (!ctx) {
return nk_false;
} else {
const struct nk_input* i = &ctx->input;
if (*clicked) {
/* could also be based on maintaining hover rather than motionless once clicked */
if (!nk_input_is_mouse_moved(i)) {
return nk_false;
}
*clicked = nk_false;
*timer = 0;
}
if (NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h)) {
/* once it triggers, moving within the bounds should not make it disappear */
if (*timer >= delay) {
return nk_true;
}
if (!nk_input_is_mouse_moved(i)) {
*timer += ctx->delta_time_seconds;
return *timer >= delay;
}
*timer = 0;
} else if (NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h)) {
*timer = 0;
}
return nk_false;
}
}
NK_API nk_bool
nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
{
Expand Down Expand Up @@ -19247,13 +19388,14 @@ nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
win->tooltip_padding = nk_vec2(4,4);

/* default tooltip just down and to the right of the cursor
* so it doesn't cover the text
* so it doesn't cover the text and a default delay of 0.5 seconds
*
* TODO might be worth consolidating tooltip styling
* into its own style structure, though it is a
* type of window...*/
win->tooltip_origin = NK_TOP_LEFT;
win->tooltip_offset = nk_vec2(12, 12);
win->tooltip_delay = 0.5f;
}
NK_API void
nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
Expand Down Expand Up @@ -30766,6 +30908,45 @@ nk_tooltip_end(struct nk_context *ctx)
nk_popup_end(ctx);
}

/**
* Display a default tooltip if the mouse is hovering over the rect `bounds`
*/
NK_API void
nk_do_tooltip(struct nk_context* ctx, const char* text, struct nk_rect bounds)
{
NK_ASSERT(ctx);
if (nk_input_is_mouse_hovering_rect(&ctx->input, bounds)) {
nk_tooltip_offset(ctx, text, ctx->style.window.tooltip_origin, ctx->style.window.tooltip_offset);
}
}

/**
* Display a default tooltip if the mouse hovers motionless for the default delay (ctx->style.window.tooltip_delay)
* `timer` is used to track the time across frames.
*/
NK_API void
nk_do_tooltip_delay(struct nk_context* ctx, const char* text, struct nk_rect bounds, float* timer)
{
NK_ASSERT(ctx);
if (nk_input_is_mouse_hovering_still_delay_rect(ctx, bounds, timer, ctx->style.window.tooltip_delay)) {
nk_tooltip_offset(ctx, text, ctx->style.window.tooltip_origin, ctx->style.window.tooltip_offset);
}
}

/**
* Display a default tooltip if the mouse hovers motionless for the default delay (ctx->style.window.tooltip_delay) unless
* `clicked` is true. `clicked` will be reset to false (and `timer` to 0) when the mouse moves.
* `timer` is used to track the time across frames.
*/
NK_API void
nk_do_tooltip_delay_clicked(struct nk_context* ctx, const char* text, struct nk_rect bounds, float* timer, nk_bool* clicked)
{
NK_ASSERT(ctx);
if (nk_input_is_mouse_hovering_still_delay_clicked_rect(ctx, bounds, timer, ctx->style.window.tooltip_delay, clicked)) {
nk_tooltip_offset(ctx, text, ctx->style.window.tooltip_origin, ctx->style.window.tooltip_offset);
}
}

NK_API void
nk_tooltip_offset(struct nk_context *ctx, const char *text, enum nk_tooltip_pos position, struct nk_vec2 offset)
{
Expand Down
8 changes: 8 additions & 0 deletions src/nuklear.h
Original file line number Diff line number Diff line change
Expand Up @@ -3620,6 +3620,9 @@ NK_API void nk_contextual_end(struct nk_context*);
* ============================================================================= */
NK_API void nk_tooltip(struct nk_context*, const char*);
NK_API void nk_tooltip_offset(struct nk_context *ctx, const char *text, enum nk_tooltip_pos position, struct nk_vec2 offset);
NK_API void nk_do_tooltip(struct nk_context*, const char*, struct nk_rect);
NK_API void nk_do_tooltip_delay(struct nk_context*, const char*, struct nk_rect, float*);
NK_API void nk_do_tooltip_delay_clicked(struct nk_context*, const char*, struct nk_rect, float* timer, nk_bool*);
#ifdef NK_INCLUDE_STANDARD_VARARGS
NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2);
NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2);
Expand Down Expand Up @@ -4745,6 +4748,10 @@ NK_API nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, en
NK_API nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_still_rect(const struct nk_input*, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_hovering_delay_rect(const struct nk_context*, struct nk_rect, float*, float);
NK_API nk_bool nk_input_is_mouse_hovering_still_delay_rect(const struct nk_context*, struct nk_rect, float*, float);
NK_API nk_bool nk_input_is_mouse_hovering_still_delay_clicked_rect(const struct nk_context*, struct nk_rect, float*, float, nk_bool*);
NK_API nk_bool nk_input_is_mouse_moved(const struct nk_input*);
NK_API nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
NK_API nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
Expand Down Expand Up @@ -5380,6 +5387,7 @@ struct nk_style_window {

enum nk_tooltip_pos tooltip_origin;
struct nk_vec2 tooltip_offset;
float tooltip_delay;
};

struct nk_style {
Expand Down
Loading
Loading