[Bf-blender-cvs] [06737a82584] blender2.8: UI: popover-once (click-drag for single actions)

Campbell Barton noreply at git.blender.org
Sat May 19 19:20:51 CEST 2018


Commit: 06737a82584c6be60a25b5f289e3fcd5c26b7aac
Author: Campbell Barton
Date:   Sat May 19 19:16:47 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB06737a82584c6be60a25b5f289e3fcd5c26b7aac

UI: popover-once (click-drag for single actions)

Experimental support for using popovers like menus,
use this when the user hold the mouse down
(previously this did nothing).

This means turning frequently accessed menu items into
popovers doesn't add more clicks to the existing use case.

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_region_popover.c
M	source/blender/editors/interface/interface_widgets.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f0db1782a7e..417aca1210e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -144,8 +144,9 @@ enum {
 #define UI_BLOCK_LIST_ITEM   (1 << 19)
 #define UI_BLOCK_RADIAL      (1 << 20)
 #define UI_BLOCK_POPOVER     (1 << 21)
+#define UI_BLOCK_POPOVER_ONCE (1 << 22)
 /** Always show keymaps, even for non-menus. */
-#define UI_BLOCK_SHOW_SHORTCUT_ALWAYS (1 << 22)
+#define UI_BLOCK_SHOW_SHORTCUT_ALWAYS (1 << 23)
 
 /* uiPopupBlockHandle->menuretval */
 #define UI_RETURN_CANCEL     (1 << 0)   /* cancel all menus cascading */
@@ -429,6 +430,7 @@ typedef struct uiPopover uiPopover;
 uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL();
 void UI_popover_end(struct bContext *C, struct uiPopover *head);
 struct uiLayout *UI_popover_layout(uiPopover *head);
+void UI_popover_once_clear(uiPopover *pup);
 
 /* interface_region_menu_pie.c */
 /* Pie menus */
@@ -1234,6 +1236,9 @@ void UI_widgetbase_draw_cache_end(void);
 /* Special drawing for toolbar, mainly workarounds for inflexible icon sizing. */
 #define USE_TOOLBAR_HACK
 
+/* Support click-drag motion which presses the button and closes a popover (like a menu). */
+#define USE_POPOVER_ONCE
+
 bool UI_but_is_tool(const uiBut *but);
 
 #endif  /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 7ca3ffc8c84..2f91fb86b36 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -491,6 +491,31 @@ bool ui_but_is_editable_as_text(const uiBut *but)
 
 }
 
+bool ui_but_is_toggle(const uiBut *but)
+{
+	return ELEM(
+	        but->type,
+	        UI_BTYPE_BUT_TOGGLE,
+	        UI_BTYPE_TOGGLE,
+	        UI_BTYPE_ICON_TOGGLE,
+	        UI_BTYPE_ICON_TOGGLE_N,
+	        UI_BTYPE_TOGGLE_N,
+	        UI_BTYPE_CHECKBOX,
+	        UI_BTYPE_CHECKBOX_N,
+	        UI_BTYPE_ROW
+	);
+}
+
+#ifdef USE_POPOVER_ONCE
+bool ui_but_is_popover_once_compat(const uiBut *but)
+{
+	return (
+	        (but->type == UI_BTYPE_BUT) ||
+	        ui_but_is_toggle(but)
+	);
+}
+#endif
+
 static uiBut *ui_but_prev(uiBut *but)
 {
 	while (but->prev) {
@@ -8323,6 +8348,28 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
 				data->cancel = true;
 				button_activate_state(C, but, BUTTON_STATE_EXIT);
 				break;
+#ifdef USE_POPOVER_ONCE
+			case LEFTMOUSE:
+			{
+				if (event->val == KM_RELEASE) {
+					if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+						if (!(but->flag & UI_BUT_DISABLED)) {
+							if (ui_but_is_popover_once_compat(but)) {
+								data->cancel = false;
+								button_activate_state(C, but, BUTTON_STATE_EXIT);
+								retval = WM_UI_HANDLER_BREAK;
+								block->handle->menuretval = UI_RETURN_OK;
+							}
+							else if (ui_but_is_editable_as_text(but)) {
+								ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_TEXT_EDITING);
+								retval = WM_UI_HANDLER_BREAK;
+							}
+						}
+					}
+				}
+				break;
+			}
+#endif
 			case MOUSEMOVE:
 			{
 				uiBut *but_other = ui_but_find_mouse_over(ar, event);
@@ -9466,6 +9513,15 @@ static int ui_handle_menu_event(
 		retval = ui_handle_menu_button(C, event, menu);
 	}
 
+#ifdef USE_POPOVER_ONCE
+	if (block->flag & UI_BLOCK_POPOVER_ONCE) {
+		if ((event->type == LEFTMOUSE) && (event->val == KM_RELEASE)) {
+			UI_popover_once_clear(menu->popup_create_vars.arg);
+			block->flag &= ~UI_BLOCK_POPOVER_ONCE;
+		}
+	}
+#endif
+
 	/* if we set a menu return value, ensure we continue passing this on to
 	 * lower menus and buttons, so always set continue then, and if we are
 	 * inside the region otherwise, ensure we swallow the event */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 280156a5290..e1fe64c1e35 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -698,6 +698,8 @@ extern uiBut *ui_but_find_active_in_region(struct ARegion *ar);
 extern uiBut *ui_but_find_mouse_over(struct ARegion *ar, const struct wmEvent *event);
 bool ui_but_is_editable(const uiBut *but);
 bool ui_but_is_editable_as_text(const uiBut *but);
+bool ui_but_is_toggle(const uiBut *but);
+bool ui_but_is_popover_once_compat(const uiBut *but);
 void ui_but_pie_dir_visual(RadialDirection dir, float vec[2]);
 void ui_but_pie_dir(RadialDirection dir, float vec[2]);
 float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index fcfbc3027d0..6be76572e0e 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -79,6 +79,10 @@ struct uiPopover {
 
 	uiMenuCreateFunc menu_func;
 	void *menu_arg;
+
+#ifdef USE_POPOVER_ONCE
+	bool is_once;
+#endif
 };
 
 static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
@@ -125,6 +129,11 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
 	UI_block_region_set(block, handle->region);
 	UI_block_layout_resolve(block, &width, &height);
 	UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
+#ifdef USE_POPOVER_ONCE
+	if (pup->is_once) {
+		UI_block_flag_enable(block, UI_BLOCK_POPOVER_ONCE);
+	}
+#endif
 	UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
 
 	const int block_margin = U.widget_unit / 2;
@@ -195,6 +204,10 @@ uiPopupBlockHandle *ui_popover_panel_create(
 	pup->menu_func = menu_func;
 	pup->menu_arg = arg;
 
+#ifdef USE_POPOVER_ONCE
+	pup->is_once = true;
+#endif
+
 	/* Create popup block. */
 	uiPopupBlockHandle *handle;
 	handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
@@ -262,6 +275,13 @@ uiLayout *UI_popover_layout(uiPopover *pup)
 	return pup->layout;
 }
 
+#ifdef USE_POPOVER_ONCE
+void UI_popover_once_clear(uiPopover *pup)
+{
+	pup->is_once = false;
+}
+#endif
+
 /** \} */
 
 /* We may want to support this in future */
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 7053f2833c3..cdc95d4fb32 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3204,6 +3204,20 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
 	ui_hsv_cursor(x, y);
 }
 
+/* Generic round-box drawing. */
+static void ui_draw_roundbox(const rcti *rect, const float rad, const uiWidgetColors *wcol)
+{
+	uiWidgetBase wtb;
+	widget_init(&wtb);
+	round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
+	widgetbase_draw(&wtb, wcol);
+
+	/* We are drawing on top of widget bases. Flush cache. */
+	glEnable(GL_BLEND);
+	UI_widgetbase_draw_cache_flush();
+	glDisable(GL_BLEND);
+}
+
 
 /* ************ separator, for menus etc ***************** */
 static void ui_draw_separator(const rcti *rect,  uiWidgetColors *wcol)
@@ -4336,6 +4350,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
 	uiFontStyle *fstyle = &style->widget;
 	uiWidgetType *wt = NULL;
 
+#ifdef USE_POPOVER_ONCE
+	const rcti rect_orig = *rect;
+#endif
+
 	/* handle menus separately */
 	if (but->dt == UI_EMBOSS_PULLDOWN) {
 		switch (but->type) {
@@ -4611,6 +4629,25 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
 
 		if (disabled)
 			glEnable(GL_BLEND);
+
+#ifdef USE_POPOVER_ONCE
+		if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
+			if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+				uiWidgetType wt_back = *wt;
+				uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
+				wt_temp->state(wt_temp, state);
+				copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+				wt->wcol.inner[3] = 128;
+				wt->wcol.roundness = 0.5f;
+				ui_draw_roundbox(
+				        &rect_orig,
+				        0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
+				        &wt_temp->wcol);
+				*wt = wt_back;
+			}
+		}
+#endif
+
 		wt->text(fstyle, &wt->wcol, but, rect);
 		if (disabled)
 			glDisable(GL_BLEND);



More information about the Bf-blender-cvs mailing list