UI: cleanup next/prev order in menu code

Recent flag re-order broke it since bits overlap, but logic here was far too complicated & fragile,
Checked the type of each button when testing which direction to handle events as well as block direction.

Now store the block-flipped state as a flag.
This commit is contained in:
Campbell Barton 2014-11-15 14:32:23 +01:00
parent 694f15dee3
commit c1e48c0ff0
4 changed files with 36 additions and 50 deletions

View File

@ -124,7 +124,8 @@ enum {
/* uiBlock->flag (controls) */
#define UI_BLOCK_LOOP (1 << 0)
#define UI_BLOCK_SEARCH_MENU (1 << 2)
#define UI_BLOCK_IS_FLIP (1 << 1)
#define UI_BLOCK_NO_FLIP (1 << 2)
#define UI_BLOCK_NUMSELECT (1 << 3)
#define UI_BLOCK_NO_WIN_CLIP (1 << 4) /* don't apply window clipping */ /* was UI_BLOCK_ENTER_OK */
#define UI_BLOCK_CLIPBOTTOM (1 << 5)
@ -133,7 +134,7 @@ enum {
#define UI_BLOCK_KEEP_OPEN (1 << 8)
#define UI_BLOCK_POPUP (1 << 9)
#define UI_BLOCK_OUT_1 (1 << 10)
#define UI_BLOCK_NO_FLIP (1 << 11)
#define UI_BLOCK_SEARCH_MENU (1 << 11)
#define UI_BLOCK_POPUP_MEMORY (1 << 12)
#define UI_BLOCK_CLIP_EVENTS (1 << 13) /* stop handling mouse events */

View File

@ -3270,6 +3270,9 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu
if (free) {
MEM_freeN(item_array);
}
BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
block->flag |= UI_BLOCK_IS_FLIP;
}
/**
@ -3888,6 +3891,8 @@ void UI_block_order_flip(uiBlock *block)
but->rect.ymax = centy - (but->rect.ymax - centy);
SWAP(float, but->rect.ymin, but->rect.ymax);
}
block->flag ^= UI_BLOCK_IS_FLIP;
}

View File

@ -8045,7 +8045,7 @@ static int ui_handle_menu_event(
{
ARegion *ar;
uiBlock *block;
uiBut *but, *bt;
uiBut *but;
int mx, my, retval;
bool inside;
bool inside_title; /* check for title dragging */
@ -8173,7 +8173,9 @@ static int ui_handle_menu_event(
ui_pan_to_scroll(event, &type, &val);
if (val == KM_PRESS) {
const eButType type_flip = UI_BTYPE_BUT | UI_BTYPE_ROW;
const bool is_next =
(ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE) ==
((block->flag & UI_BLOCK_IS_FLIP) != 0));
if (ui_menu_pass_event_to_parent_if_nonactive(menu, but, level, retval))
break;
@ -8184,57 +8186,22 @@ static int ui_handle_menu_event(
but = ui_but_find_active_in_region(ar);
if (but) {
/* is there a situation where UI_DIR_LEFT or UI_DIR_RIGHT would also change navigation direction? */
if (((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DIR_DOWN)) ||
((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DIR_RIGHT)) ||
((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DIR_UP)))
{
/* the following is just a hack - uiBut->type set to
* UI_BTYPE_BUT and UI_BTYPE_BUT_MENU have there menus built opposite ways -
* this should be changed so that all popup-menus use the same uiBlock->direction */
if (but->type & type_flip)
but = ui_but_next(but);
else
but = ui_but_prev(but);
}
else {
if (but->type & type_flip)
but = ui_but_prev(but);
else
but = ui_but_next(but);
}
if (but) {
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
ui_menu_scroll(ar, block, my, but);
}
/* next button */
but = is_next ? ui_but_next(but) : ui_but_prev(but);
}
if (!but) {
if (((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DIR_DOWN)) ||
((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DIR_RIGHT)) ||
((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DIR_UP)))
{
if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
bt = ui_but_last(block);
}
else {
/* keep ui_but_first() */
}
}
else {
if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
/* keep ui_but_first() */
}
else {
bt = ui_but_last(block);
}
/* wrap button */
uiBut *but_wrap;
but_wrap = is_next ? ui_but_first(block) : ui_but_last(block);
if (but_wrap) {
but = but_wrap;
}
}
if (bt) {
ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE);
ui_menu_scroll(ar, block, my, bt);
}
if (but) {
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
ui_menu_scroll(ar, block, my, but);
}
}

View File

@ -977,6 +977,11 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
if (free) {
MEM_freeN(item_array);
}
if ((block->flag & UI_BLOCK_NO_FLIP) == 0) {
BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
block->flag |= UI_BLOCK_IS_FLIP;
}
}
else if (prop && RNA_property_type(prop) != PROP_ENUM) {
RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
@ -1431,6 +1436,11 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
MEM_freeN(item);
}
}
if ((block->flag & UI_BLOCK_NO_FLIP) == 0) {
BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
block->flag |= UI_BLOCK_IS_FLIP;
}
}
/* Pointer RNA button with search */
@ -1663,6 +1673,9 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
if (layout->context)
CTX_store_set(C, NULL);
/* menus are created flipped (from event handling pov) */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
static uiBut *ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN,