[Bf-blender-cvs] [718bf8f] master: UI: Ctrl+Tab and Ctrl+Shift+Tab to cycle through space context "tabs"

Julian Eisel noreply at git.blender.org
Mon Sep 5 17:33:01 CEST 2016


Commit: 718bf8fd9d17bddf500bd6b878b0ebcf0d950584
Author: Julian Eisel
Date:   Mon Sep 5 16:58:40 2016 +0200
Branches: master
https://developer.blender.org/rB718bf8fd9d17bddf500bd6b878b0ebcf0d950584

UI: Ctrl+Tab and Ctrl+Shift+Tab to cycle through space context "tabs"

In User Preferences, Properties Editor and toolshelf, Ctrl+Tab and Ctrl+Shift+Tab now activates the next or previous space context (or category in case of toolshelf tabs), respectively.

For Properties Editor such functionality was completely missing, only toolshelf allowed cycling using ctrl+mousewheel (or only mousewheel while hovering tab region). Ctrl+Tab and Ctrl+Shift+Tab are common web browser shortcuts, so they're a reasonable choice to go with.
Reaching the first/last item doesn't cause the cycling to stop, we continue at the other end of the list then. (I didn't add this to Ctrl+Mousewheel toggling in toolshelf since I wanted to keep its behavior unchanged.)

We could get rid of (Ctrl+)Mousewheel cycling in toolshelf, but this may break user habits.

The cycling happens using a new operator, UI_OT_space_context_cycle, for toolshelf tabs it's hardcoded in panel handling code though.
Generalized rna_property_enum_step a bit and moved it to rna_access.c to allow external reuse.

Reviewed By: venomgfx
Differential Revision: https://developer.blender.org/D2189

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

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_ops.c
M	source/blender/editors/interface/interface_panel.c
M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/screen/screen_ops.c
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/rna_access.c

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

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 49e5845..26a6fdd 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1021,6 +1021,12 @@ void ED_keymap_ui(struct wmKeyConfig *keyconf);
 void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
 int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
 
+/* UI_OT_space_context_cycle direction */
+enum {
+	SPACE_CONTEXT_CYCLE_PREV,
+	SPACE_CONTEXT_CYCLE_NEXT,
+};
+
 bool UI_context_copy_to_selected_list(
         struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop,
         struct ListBase *r_lb, bool *r_use_path_from_id, char **r_path);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 1af6d90..cb539bb 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1082,6 +1082,78 @@ static void UI_OT_drop_color(wmOperatorType *ot)
 	RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
 }
 
+/* ------------------------------------------------------------------------- */
+
+static EnumPropertyItem space_context_cycle_direction[] = {
+	{SPACE_CONTEXT_CYCLE_PREV, "PREV", 0, "Previous", ""},
+	{SPACE_CONTEXT_CYCLE_NEXT, "NEXT", 0, "Next", ""},
+	{0, NULL, 0, NULL, NULL}
+};
+
+static int space_context_cycle_poll(bContext *C)
+{
+	ScrArea *sa = CTX_wm_area(C);
+	return ELEM(sa->spacetype, SPACE_BUTS, SPACE_USERPREF);
+}
+
+/**
+ * Helper to get the correct RNA pointer/property pair for changing
+ * the display context of active space type in \sa.
+ */
+static void context_cycle_prop_get(
+        bScreen *screen, const ScrArea *sa,
+        PointerRNA *r_ptr, PropertyRNA **r_prop)
+{
+	const char *propname;
+
+	switch (sa->spacetype) {
+		case SPACE_BUTS:
+			RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sa->spacedata.first, r_ptr);
+			propname = "context";
+			break;
+		case SPACE_USERPREF:
+			RNA_pointer_create(NULL, &RNA_UserPreferences, &U, r_ptr);
+			propname = "active_section";
+			break;
+	}
+
+	*r_prop = RNA_struct_find_property(r_ptr, propname);
+}
+
+static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+	const int direction = RNA_enum_get(op->ptr, "direction");
+
+	PointerRNA ptr;
+	PropertyRNA *prop;
+	context_cycle_prop_get(CTX_wm_screen(C), CTX_wm_area(C), &ptr, &prop);
+
+	const int old_context = RNA_property_enum_get(&ptr, prop);
+	const int new_context = RNA_property_enum_step(
+	                  C, &ptr, prop, old_context,
+	                  direction == SPACE_CONTEXT_CYCLE_PREV ? -1 : 1);
+	RNA_property_enum_set(&ptr, prop, new_context);
+	RNA_property_update(C, &ptr, prop);
+
+	return OPERATOR_FINISHED;
+}
+
+static void UI_OT_space_context_cycle(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Cycle Space Context";
+	ot->description = "Cycle through the editor context by activating the next/previous one";
+	ot->idname = "UI_OT_space_context_cycle";
+
+	/* api callbacks */
+	ot->invoke = space_context_cycle_invoke;
+	ot->poll = space_context_cycle_poll;
+
+	ot->flag = 0;
+
+	RNA_def_enum(ot->srna, "direction", space_context_cycle_direction, SPACE_CONTEXT_CYCLE_NEXT, "Direction",
+	             "Direction to cycle through");
+}
 
 
 /* ********************************************************* */
@@ -1102,6 +1174,7 @@ void ED_operatortypes_ui(void)
 	WM_operatortype_append(UI_OT_edittranslation_init);
 #endif
 	WM_operatortype_append(UI_OT_reloadtranslation);
+	WM_operatortype_append(UI_OT_space_context_cycle);
 
 	/* external */
 	WM_operatortype_append(UI_OT_eyedropper_color);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 79961ea..c131bcb 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1841,6 +1841,52 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
 #undef USE_FLAT_INACTIVE
 }
 
+static int ui_handle_panel_category_cycling(const wmEvent *event, ARegion *ar, const uiBut *active_but)
+{
+	const bool is_mousewheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
+	const bool inside_tabregion = (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax);
+
+	/* if mouse is inside non-tab region, ctrl key is required */
+	if (is_mousewheel && !event->ctrl && !inside_tabregion)
+		return WM_UI_HANDLER_CONTINUE;
+
+
+	if (active_but && ui_but_supports_cycling(active_but)) {
+		/* skip - exception to make cycling buttons
+		 * using ctrl+mousewheel work in tabbed regions */
+	}
+	else {
+		const char *category = UI_panel_category_active_get(ar, false);
+		if (LIKELY(category)) {
+			PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
+			if (LIKELY(pc_dyn)) {
+				if (is_mousewheel) {
+					/* we can probably get rid of this and only allow ctrl+tabbing */
+					pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
+				}
+				else {
+					const bool backwards = event->shift;
+					pc_dyn = backwards ? pc_dyn->prev : pc_dyn->next;
+					if (!pc_dyn) {
+						/* proper cyclic behavior, back to first/last category (only used for ctrl+tab) */
+						pc_dyn = backwards ? ar->panels_category.last : ar->panels_category.first;
+					}
+				}
+
+				if (pc_dyn) {
+					/* intentionally don't reset scroll in this case,
+					 * this allows for quick browsing between tabs */
+					UI_panel_category_active_set(ar, pc_dyn->idname);
+					ED_region_tag_redraw(ar);
+				}
+			}
+		}
+		return WM_UI_HANDLER_BREAK;
+	}
+
+	return WM_UI_HANDLER_CONTINUE;
+}
+
 /* XXX should become modal keymap */
 /* AKey is opening/closing panels, independent of button state now */
 
@@ -1853,6 +1899,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
 
 	retval = WM_UI_HANDLER_CONTINUE;
 
+	/* handle category tabs */
 	if (has_category_tabs) {
 		if (event->val == KM_PRESS) {
 			if (event->type == LEFTMOUSE) {
@@ -1867,32 +1914,9 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
 					retval = WM_UI_HANDLER_BREAK;
 				}
 			}
-			else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
-				/* mouse wheel cycle tabs */
-
-				/* first check if the mouse is in the tab region */
-				if (event->ctrl || (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax)) {
-					if (active_but && ui_but_supports_cycling(active_but)) {
-						/* skip - exception to make cycling buttons
-						 * using ctrl+mousewheel work in tabbed regions */
-					}
-					else {
-						const char *category = UI_panel_category_active_get(ar, false);
-						if (LIKELY(category)) {
-							PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
-							if (LIKELY(pc_dyn)) {
-								pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
-								if (pc_dyn) {
-									/* intentionally don't reset scroll in this case,
-									 * this allows for quick browsing between tabs */
-									UI_panel_category_active_set(ar, pc_dyn->idname);
-									ED_region_tag_redraw(ar);
-								}
-							}
-						}
-						retval = WM_UI_HANDLER_BREAK;
-					}
-				}
+			else if ((event->type == TABKEY && event->ctrl) || ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+				/* cycle tabs */
+				retval = ui_handle_panel_category_cycling(event, ar, active_but);
 			}
 		}
 	}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index c507401..4ea5e20 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -73,38 +73,6 @@
 #define MENU_PADDING		(int)(0.2f * UI_UNIT_Y)
 #define MENU_BORDER			(int)(0.3f * U.widget_unit)
 
-static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int direction)
-{
-	EnumPropertyItem *item_array;
-	int totitem;
-	bool free;
-	int value;
-	int i, i_init;
-	int step = (direction < 0) ? -1 : 1;
-	int step_tot = 0;
-
-	RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
-	value = RNA_property_enum_get(ptr, prop);
-	i = RNA_enum_from_value(item_array, value);
-	i_init = i;
-
-	do {
-		i = mod_i(i + step, totitem);
-		if (item_array[i].identifier[0]) {
-			step_tot += step;
-		}
-	} while ((i != i_init) && (step_tot != direction));
-
-	if (i != i_init) {
-		value = item_array[i].value;
-	}
-
-	if (free) {
-		MEM_freeN(item_array);
-	}
-
-	return value;
-}
 
 bool ui_but_menu_step_poll(const uiBut *but)
 {
@@ -122,7 +90,8 @@ int ui_but_menu_step(uiBut *but, int direction)
 			return but->menu_step_func(but->block->evil_C, direction, but->poin);
 		}
 		else {
-			return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
+			const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
+			return RNA_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction);
 		}
 	}
 
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 6dbb5db..e446194 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4331,7 +4331,13 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
 
 	WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
 	WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
-	
+
+	/* UI */
+	kmi = WM_keymap_add_item(keymap, "UI_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL, 0);
+	RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_NEXT);
+	kmi = WM_keymap_add_item(keymap, "UI_OT_space_context_cycle", TABKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+	RNA_enum_set(kmi->ptr, "direction", SPACE_CONTEXT_CYCLE_PREV);
+
 	/* tests */
 	WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
 	WM_keymap_verify_item(keymap, "SCR

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list