[Bf-blender-cvs] [571aead323d] blender2.8: UI: support immediate non-overlapping tooltips

Campbell Barton noreply at git.blender.org
Tue Sep 4 09:58:43 CEST 2018


Commit: 571aead323dd4cb84d2a39894172c119d6dfbab5
Author: Campbell Barton
Date:   Tue Sep 4 17:57:59 2018 +1000
Branches: blender2.8
https://developer.blender.org/rB571aead323dd4cb84d2a39894172c119d6dfbab5

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.

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_query.c
M	source/blender/editors/interface/interface_region_tooltip.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_tooltip.c

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index e739308bd1e..51cff1c9440 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -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
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a1e3117e3a5..8805907b337 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -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);
 			}
 		}
 	}
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.c
index d0f7e1341de..ba4fdf43875 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.c
@@ -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;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 6f4e48a9793..ae98798dd7b 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -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)
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 66e3a77a66a..36f030e4eac 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -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);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index cd1357e85b1..f074c083b31 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -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 {
diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c
index 94a44a97afd..0953351de2b 100644
--- a/source/blender/windowmanager/intern/wm_tooltip.c
+++ b/source/blender/windowmanager/intern/wm_tooltip.c
@@ -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;
 }



More information about the Bf-blender-cvs mailing list