diff options
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 6 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_ops.c | 73 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 76 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_regions.c | 35 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 8 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 39 |
7 files changed, 178 insertions, 60 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 49e5845e3ca..26a6fdd7d1f 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 1af6d902b18..cb539bb1c5d 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 79961eae79d..c131bcb8e14 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 c507401b9a0..4ea5e2092b6 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 6dbb5db53d0..e446194a1da 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, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 9cbe132282f..820465ee7d1 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -916,6 +916,7 @@ int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value); int RNA_property_enum_get_default(PointerRNA *ptr, PropertyRNA *prop); void *RNA_property_enum_py_data_get(PropertyRNA *prop); +int RNA_property_enum_step(const struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int direction); PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 047e5ea17ab..6879a0534e9 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2873,6 +2873,45 @@ void *RNA_property_enum_py_data_get(PropertyRNA *prop) return eprop->py_data; } +/** + * Get the value of the item that is \a step items away from \a from_value. + * + * \param from_value: Item value to start stepping from. + * \param step: Absolute value defines step size, sign defines direction. + * E.g to get the next item, pass 1, for the previous -1. + */ +int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step) +{ + EnumPropertyItem *item_array; + int totitem; + bool free; + int result_value = from_value; + int i, i_init; + int single_step = (step < 0) ? -1 : 1; + int step_tot = 0; + + RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free); + i = RNA_enum_from_value(item_array, from_value); + i_init = i; + + do { + i = mod_i(i + single_step, totitem); + if (item_array[i].identifier[0]) { + step_tot += single_step; + } + } while ((i != i_init) && (step_tot != step)); + + if (i != i_init) { + result_value = item_array[i].value; + } + + if (free) { + MEM_freeN(item_array); + } + + return result_value; +} + PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; |