UI: support immediate non-overlapping tooltips
Use these for the toolbar, since they're non-overlapping the interface, showing them quickly isn't a problem.
This commit is contained in:
parent
e913e79fb5
commit
571aead323
|
@ -407,6 +407,7 @@ typedef bool (*uiMenuStepFunc)(struct bContext *C, int direction, void *arg1);
|
|||
|
||||
|
||||
/* interface_query.c */
|
||||
bool UI_but_is_tooltip_no_overlap(const uiBut *but);
|
||||
bool UI_but_is_tool(const uiBut *but);
|
||||
#define UI_but_is_decorator(but) \
|
||||
((but)->func == ui_but_anim_decorate_cb)
|
||||
|
@ -1281,6 +1282,8 @@ void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar)
|
|||
|
||||
/* How long before a tool-tip shows. */
|
||||
#define UI_TOOLTIP_DELAY 0.5
|
||||
/* For cases when the tooltips don't overlap, use an 'instant' tip. */
|
||||
#define UI_TOOLTIP_DELAY_QUICK 0.05
|
||||
|
||||
/* Float precision helpers */
|
||||
#define UI_PRECISION_FLOAT_MAX 6
|
||||
|
|
|
@ -7066,7 +7066,8 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
|
|||
if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
|
||||
if (!but->block->tooltipdisabled) {
|
||||
if (!wm->drags.first) {
|
||||
WM_tooltip_timer_init(C, data->window, data->region, ui_but_tooltip_init);
|
||||
bool quick = UI_but_is_tooltip_no_overlap(but);
|
||||
WM_tooltip_timer_init(C, data->window, data->region, ui_but_tooltip_init, quick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,14 @@ bool UI_but_is_tool(const uiBut *but)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool UI_but_is_tooltip_no_overlap(const uiBut *but)
|
||||
{
|
||||
if (!ui_block_is_popover(but->block)) {
|
||||
return UI_but_is_tool(but);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -962,7 +962,7 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
|
|||
|
||||
static ARegion *ui_tooltip_create_with_data(
|
||||
bContext *C, uiTooltipData *data,
|
||||
const float init_position[2],
|
||||
const float init_position[2], const rcti *init_rect_overlap,
|
||||
const float aspect)
|
||||
{
|
||||
const float pad_px = UI_TIP_PADDING;
|
||||
|
@ -1066,19 +1066,98 @@ static ARegion *ui_tooltip_create_with_data(
|
|||
#undef TIP_BORDER_X
|
||||
#undef TIP_BORDER_Y
|
||||
|
||||
|
||||
/* Clamp to window bounds. */
|
||||
{
|
||||
/* Ensure at least 5 px above screen bounds
|
||||
* UI_UNIT_Y is just a guess to be above the menu item */
|
||||
const int pad = max_ff(1.0f, U.pixelsize) * 5;
|
||||
const rcti rect_clamp = {
|
||||
.xmin = pad,
|
||||
.xmax = winx - pad,
|
||||
.ymin = pad + (UI_UNIT_Y * 2),
|
||||
.ymax = winy - pad,
|
||||
};
|
||||
int offset_dummy[2];
|
||||
BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
|
||||
if (init_rect_overlap != NULL) {
|
||||
const int pad = max_ff(1.0f, U.pixelsize) * 5;
|
||||
const rcti init_rect = {
|
||||
.xmin = init_rect_overlap->xmin - pad,
|
||||
.xmax = init_rect_overlap->xmax + pad,
|
||||
.ymin = init_rect_overlap->ymin - pad,
|
||||
.ymax = init_rect_overlap->ymax + pad,
|
||||
};
|
||||
const rcti rect_clamp = {
|
||||
.xmin = 0,
|
||||
.xmax = winx,
|
||||
.ymin = 0,
|
||||
.ymax = winy,
|
||||
};
|
||||
/* try right. */
|
||||
const int size_x = BLI_rcti_size_x(&rect_i);
|
||||
const int size_y = BLI_rcti_size_y(&rect_i);
|
||||
const int cent_overlap_x = BLI_rcti_cent_x(&init_rect);
|
||||
const int cent_overlap_y = BLI_rcti_cent_y(&init_rect);
|
||||
struct {
|
||||
rcti xpos;
|
||||
rcti xneg;
|
||||
rcti ypos;
|
||||
rcti yneg;
|
||||
} rect;
|
||||
|
||||
{ /* xpos */
|
||||
rcti r = rect_i;
|
||||
r.xmin = init_rect.xmax;
|
||||
r.xmax = r.xmin + size_x;
|
||||
r.ymin = cent_overlap_y - (size_y / 2);
|
||||
r.ymax = r.ymin + size_y;
|
||||
rect.xpos = r;
|
||||
}
|
||||
{ /* xneg */
|
||||
rcti r = rect_i;
|
||||
r.xmin = init_rect.xmin - size_x;
|
||||
r.xmax = r.xmin + size_x;
|
||||
r.ymin = cent_overlap_y - (size_y / 2);
|
||||
r.ymax = r.ymin + size_y;
|
||||
rect.xneg = r;
|
||||
}
|
||||
{ /* ypos */
|
||||
rcti r = rect_i;
|
||||
r.xmin = cent_overlap_x - (size_x / 2);
|
||||
r.xmax = r.xmin + size_x;
|
||||
r.ymin = init_rect.ymax;
|
||||
r.ymax = r.ymin + size_y;
|
||||
rect.ypos = r;
|
||||
}
|
||||
{ /* yneg */
|
||||
rcti r = rect_i;
|
||||
r.xmin = cent_overlap_x - (size_x / 2);
|
||||
r.xmax = r.xmin + size_x;
|
||||
r.ymin = init_rect.ymin - size_y;
|
||||
r.ymax = r.ymin + size_y;
|
||||
rect.yneg = r;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
const rcti *r = (&rect.xpos) + j;
|
||||
if (BLI_rcti_inside_rcti(&rect_clamp, r)) {
|
||||
rect_i = *r;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
/* Fallback, we could pick the best fallback, for now just use xpos. */
|
||||
int offset_dummy[2];
|
||||
rect_i = rect.xpos;
|
||||
BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
const int pad = max_ff(1.0f, U.pixelsize) * 5;
|
||||
const rcti rect_clamp = {
|
||||
.xmin = pad,
|
||||
.xmax = winx - pad,
|
||||
.ymin = pad + (UI_UNIT_Y * 2),
|
||||
.ymax = winy - pad,
|
||||
};
|
||||
int offset_dummy[2];
|
||||
BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
|
||||
}
|
||||
}
|
||||
|
||||
/* add padding */
|
||||
|
@ -1088,7 +1167,9 @@ static ARegion *ui_tooltip_create_with_data(
|
|||
|
||||
/* widget rect, in region coords */
|
||||
{
|
||||
/* Compensate for margin offset, visually this corrects the position. */
|
||||
const int margin = UI_POPUP_MARGIN;
|
||||
BLI_rcti_translate(&rect_i, margin, margin / 2);
|
||||
|
||||
data->bbox.xmin = margin;
|
||||
data->bbox.xmax = BLI_rcti_size_x(&rect_i) - margin;
|
||||
|
@ -1142,15 +1223,33 @@ ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *b
|
|||
return NULL;
|
||||
}
|
||||
|
||||
init_position[0] = BLI_rctf_cent_x(&but->rect);
|
||||
init_position[1] = but->rect.ymin;
|
||||
|
||||
if (butregion) {
|
||||
ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
|
||||
init_position[0] = win->eventstate->x;
|
||||
const bool is_no_overlap = UI_but_is_tooltip_no_overlap(but);
|
||||
rcti init_rect;
|
||||
if (is_no_overlap) {
|
||||
rctf overlap_rect_fl;
|
||||
init_position[0] = BLI_rctf_cent_x(&but->rect);
|
||||
init_position[1] = BLI_rctf_cent_y(&but->rect);
|
||||
if (butregion) {
|
||||
ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
|
||||
ui_block_to_window_rctf(butregion, but->block, &overlap_rect_fl, &but->rect);
|
||||
}
|
||||
else {
|
||||
overlap_rect_fl = but->rect;
|
||||
}
|
||||
BLI_rcti_rctf_copy_round(&init_rect, &overlap_rect_fl);
|
||||
}
|
||||
else {
|
||||
init_position[0] = BLI_rctf_cent_x(&but->rect);
|
||||
init_position[1] = but->rect.ymin - (UI_POPUP_MARGIN / 2);
|
||||
if (butregion) {
|
||||
ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
|
||||
init_position[0] = win->eventstate->x;
|
||||
}
|
||||
}
|
||||
|
||||
return ui_tooltip_create_with_data(C, data, init_position, aspect);
|
||||
ARegion *ar = ui_tooltip_create_with_data(C, data, init_position, is_no_overlap ? &init_rect : NULL, aspect);
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
|
||||
|
@ -1167,7 +1266,7 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
|
|||
init_position[0] = win->eventstate->x;
|
||||
init_position[1] = win->eventstate->y;
|
||||
|
||||
return ui_tooltip_create_with_data(C, data, init_position, aspect);
|
||||
return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
|
||||
}
|
||||
|
||||
void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar)
|
||||
|
|
|
@ -628,7 +628,7 @@ typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *, struct ARegion *,
|
|||
|
||||
void WM_tooltip_timer_init(
|
||||
struct bContext *C, struct wmWindow *win, struct ARegion *ar,
|
||||
wmTooltipInitFn init);
|
||||
wmTooltipInitFn init, bool quick);
|
||||
void WM_tooltip_timer_clear(struct bContext *C, struct wmWindow *win);
|
||||
void WM_tooltip_clear(struct bContext *C, struct wmWindow *win);
|
||||
void WM_tooltip_init(struct bContext *C, struct wmWindow *win);
|
||||
|
|
|
@ -2422,7 +2422,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
|
|||
int part;
|
||||
gz = wm_gizmomap_highlight_find(gzmap, C, event, &part);
|
||||
if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) {
|
||||
WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init);
|
||||
WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
void WM_tooltip_timer_init(
|
||||
bContext *C, wmWindow *win, ARegion *ar,
|
||||
wmTooltipInitFn init)
|
||||
wmTooltipInitFn init, bool quick)
|
||||
{
|
||||
WM_tooltip_timer_clear(C, win);
|
||||
|
||||
|
@ -49,7 +49,8 @@ void WM_tooltip_timer_init(
|
|||
screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__);
|
||||
}
|
||||
screen->tool_tip->region_from = ar;
|
||||
screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, UI_TOOLTIP_DELAY);
|
||||
screen->tool_tip->timer = WM_event_add_timer(
|
||||
wm, win, TIMER, quick ? UI_TOOLTIP_DELAY_QUICK : UI_TOOLTIP_DELAY);
|
||||
screen->tool_tip->init = init;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue