UI: Consistent Menu/Block/Popup Content Ordering #109798

Merged
Harley Acheson merged 13 commits from Harley/blender:MenuDirection into main 2023-08-31 20:25:02 +02:00
18 changed files with 23 additions and 159 deletions

View File

@ -871,6 +871,9 @@ void blo_do_versions_userdef(UserDef *userdef)
*/
{
/* Keep this block, even when empty. */
/* Clear deprecated USER_MENUFIXEDORDER user flag for reuse. */
userdef->uiflag &= ~USER_UIFLAG_UNUSED_4;
}
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {

View File

@ -145,23 +145,19 @@ enum {
/** #uiBlock.flag (controls) */
enum {
UI_BLOCK_LOOP = 1 << 0,
/** Indicate that items in a popup are drawn with inverted order. Used for arrow key navigation
* so that it knows to invert the navigation direction to match the drawing order. */
UI_BLOCK_IS_FLIP = 1 << 1,
UI_BLOCK_NO_FLIP = 1 << 2,
UI_BLOCK_NUMSELECT = 1 << 3,
UI_BLOCK_NUMSELECT = 1 << 1,
/** Don't apply window clipping. */
UI_BLOCK_NO_WIN_CLIP = 1 << 4,
UI_BLOCK_CLIPBOTTOM = 1 << 5,
UI_BLOCK_CLIPTOP = 1 << 6,
UI_BLOCK_MOVEMOUSE_QUIT = 1 << 7,
UI_BLOCK_KEEP_OPEN = 1 << 8,
UI_BLOCK_POPUP = 1 << 9,
UI_BLOCK_OUT_1 = 1 << 10,
UI_BLOCK_SEARCH_MENU = 1 << 11,
UI_BLOCK_POPUP_MEMORY = 1 << 12,
UI_BLOCK_NO_WIN_CLIP = 1 << 2,
UI_BLOCK_CLIPBOTTOM = 1 << 3,
UI_BLOCK_CLIPTOP = 1 << 4,
UI_BLOCK_MOVEMOUSE_QUIT = 1 << 5,
UI_BLOCK_KEEP_OPEN = 1 << 6,
UI_BLOCK_POPUP = 1 << 7,
UI_BLOCK_OUT_1 = 1 << 8,
UI_BLOCK_SEARCH_MENU = 1 << 9,
UI_BLOCK_POPUP_MEMORY = 1 << 10,
/** Stop handling mouse events. */
UI_BLOCK_CLIP_EVENTS = 1 << 13,
UI_BLOCK_CLIP_EVENTS = 1 << 11,
/* #uiBlock::flags bits 14-17 are identical to #uiBut::drawflag bits. */
@ -874,7 +870,6 @@ void UI_block_direction_set(uiBlock *block, char direction);
/**
* This call escapes if there's alignment flags.
*/
void UI_block_order_flip(uiBlock *block);
void UI_block_flag_enable(uiBlock *block, int flag);
void UI_block_flag_disable(uiBlock *block, int flag);
void UI_block_translate(uiBlock *block, int x, int y);

View File

@ -4315,7 +4315,6 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
if (!item->identifier[0]) {
/* inconsistent, but menus with categories do not look good flipped */
if (item->name) {
block->flag |= UI_BLOCK_NO_FLIP;
categories++;
entries_nosepr_count++;
}
@ -4347,8 +4346,8 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
const char *title = RNA_property_ui_name(but->rnaprop);
if (title[0] && (categories == 0) && (block->flag & UI_BLOCK_NO_FLIP)) {
/* Title at the top for menus with categories. */
if (title[0] && !but->str[0] && (categories == 0)) {
/* Show title when no categories and calling button has no text. */
uiDefBut(block,
UI_BTYPE_LABEL,
0,
@ -4472,32 +4471,11 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
}
}
if (title[0] && (categories == 0) && !(block->flag & UI_BLOCK_NO_FLIP)) {
/* Title at the bottom for menus without categories. */
uiItemS(layout);
uiDefBut(block,
UI_BTYPE_LABEL,
0,
title,
0,
0,
UI_UNIT_X * 5,
UI_UNIT_Y,
nullptr,
0.0,
0.0,
0,
0,
"");
}
UI_block_layout_set_current(block, layout);
if (free) {
MEM_freeN((void *)item_array);
}
BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
block->flag |= UI_BLOCK_IS_FLIP;
}
static void ui_def_but_rna__panel_type(bContext *C, uiLayout *layout, void *but_p)
@ -5852,39 +5830,6 @@ void UI_block_direction_set(uiBlock *block, char direction)
block->direction = direction;
}
void UI_block_order_flip(uiBlock *block)
{
float centy, miny = 10000, maxy = -10000;
if (U.uiflag & USER_MENUFIXEDORDER) {
return;
}
if (block->flag & UI_BLOCK_NO_FLIP) {
return;
}
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->drawflag & UI_BUT_ALIGN) {
return;
}
if (but->rect.ymin < miny) {
miny = but->rect.ymin;
}
if (but->rect.ymax > maxy) {
maxy = but->rect.ymax;
}
}
/* mirror trick */
centy = (miny + maxy) / 2.0f;
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
but->rect.ymin = centy - (but->rect.ymin - centy);
but->rect.ymax = centy - (but->rect.ymax - centy);
std::swap(but->rect.ymin, but->rect.ymax);
}
block->flag ^= UI_BLOCK_IS_FLIP;
}
void UI_block_flag_enable(uiBlock *block, int flag)
{
block->flag |= flag;

View File

@ -10483,19 +10483,18 @@ static int ui_handle_menu_event(bContext *C,
if (val == KM_PRESS) {
/* Determine scroll operation. */
uiMenuScrollType scrolltype;
const bool ui_block_flipped = (block->flag & UI_BLOCK_IS_FLIP) != 0;
if (ELEM(type, EVT_PAGEUPKEY, EVT_HOMEKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_TOP : MENU_SCROLL_BOTTOM;
scrolltype = MENU_SCROLL_TOP;
}
else if (ELEM(type, EVT_PAGEDOWNKEY, EVT_ENDKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_BOTTOM : MENU_SCROLL_TOP;
scrolltype = MENU_SCROLL_BOTTOM;
}
else if (ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_UP : MENU_SCROLL_DOWN;
scrolltype = MENU_SCROLL_UP;
}
else {
scrolltype = ui_block_flipped ? MENU_SCROLL_DOWN : MENU_SCROLL_UP;
scrolltype = MENU_SCROLL_DOWN;
}
if (ui_menu_pass_event_to_parent_if_nonactive(

View File

@ -1290,7 +1290,6 @@ static void ui_item_menu_hold(bContext *C, ARegion *butregion, uiBut *but)
UI_popup_menu_but_set(pup, butregion, but);
block->flag |= UI_BLOCK_POPUP_HOLD;
block->flag |= UI_BLOCK_IS_FLIP;
char direction = UI_DIR_DOWN;
if (!but->drawstr[0]) {
@ -1554,9 +1553,6 @@ void uiItemsFullEnumO_items(uiLayout *layout,
if (item->name) {
if (item != item_array && !radial && split != nullptr) {
target = uiLayoutColumn(split, layout->align);
/* inconsistent, but menus with labels do not look good flipped */
block->flag |= UI_BLOCK_NO_FLIP;
}
uiBut *but;
@ -1659,9 +1655,6 @@ void uiItemsFullEnumO(uiLayout *layout,
if (free) {
MEM_freeN((void *)item_array);
}
/* intentionally don't touch UI_BLOCK_IS_FLIP here,
* we don't know the context this is called in */
}
else if (prop && RNA_property_type(prop) != PROP_ENUM) {
RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
@ -2723,8 +2716,6 @@ void uiItemsEnumR(uiLayout *layout, PointerRNA *ptr, const char *propname)
if (item[i].name) {
if (i != 0) {
column = uiLayoutColumn(split, false);
/* inconsistent, but menus with labels do not look good flipped */
block->flag |= UI_BLOCK_NO_FLIP;
}
uiItemL(column, item[i].name, ICON_NONE);
@ -2742,9 +2733,6 @@ void uiItemsEnumR(uiLayout *layout, PointerRNA *ptr, const char *propname)
if (free) {
MEM_freeN((void *)item);
}
/* intentionally don't touch UI_BLOCK_IS_FLIP here,
* we don't know the context this is called in */
}
/* Pointer RNA button with search */
@ -2955,20 +2943,13 @@ void uiItemPointerR(uiLayout *layout,
void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
MenuType *mt = (MenuType *)arg_mt;
UI_menutype_draw(C, mt, layout);
/* Menus are created flipped (from event handling point of view). */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
{
PanelType *pt = (PanelType *)arg_pt;
UI_paneltype_draw(C, pt, layout);
/* Panels are created flipped (from event handling POV). */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
static uiBut *ui_item_menu(uiLayout *layout,
@ -3576,8 +3557,6 @@ static void menu_item_enum_opname_menu(bContext * /*C*/, uiLayout *layout, void
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsFullEnumO(layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
/* override default, needed since this was assumed pre 2.70 */
UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
}
@ -3668,7 +3647,6 @@ static void menu_item_enum_rna_menu(bContext * /*C*/, uiLayout *layout, void *ar
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
}
void uiItemMenuEnumR_prop(

View File

@ -188,9 +188,7 @@ static void ui_popup_menu_create_block(bContext *C,
const uiStyle *style = UI_style_get_dpi();
pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN);
if (!pup->but) {
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
/* A title is only provided when a Menu has a label, this is not always the case, see e.g.
* `VIEW3D_MT_edit_mesh_context_menu` -- this specifies its own label inside the draw function
* depending on vertex/edge/face mode. We still want to flag the uiBlock (but only insert into
@ -360,7 +358,6 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (RGN_TYPE_IS_HEADER_ANY(region->regiontype)) {
if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP);
UI_block_order_flip(block);
}
}
}
@ -408,20 +405,6 @@ static uiPopupBlockHandle *ui_popup_menu_create(
pup->my = window->eventstate->xy[1];
pup->popup = true;
}
/* some enums reversing is strange, currently we have no good way to
* reverse some enum's but not others, so reverse all so the first menu
* items are always close to the mouse cursor */
else {
#if 0
/* if this is an rna button then we can assume its an enum
* flipping enums is generally not good since the order can be
* important #28786. */
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
#endif
}
uiPopupBlockHandle *handle = ui_popup_block_create(
C, butregion, but, nullptr, ui_block_func_POPUP, pup, ui_block_free_func_POPUP);
@ -492,8 +475,6 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
pup->title = title;
ui_popup_menu_create_block(C, pup, title, block_name);
/* Further buttons will be laid out top to bottom by default. */
pup->block->flag |= UI_BLOCK_IS_FLIP;
/* create in advance so we can let buttons point to retval already */
pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__);

View File

@ -107,8 +107,6 @@ static void ui_popover_create_block(bContext *C,
uiLayoutContextCopy(pup->layout, pup->but->context);
}
}
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
@ -415,9 +413,6 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
* The begin/end stype of calling popups doesn't allow 'can_refresh' to be set.
* For now close this style of popovers when accessed. */
UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
/* Panels are created flipped (from event handling POV). */
pup->block->flag ^= UI_BLOCK_IS_FLIP;
}
uiLayout *UI_popover_layout(uiPopover *pup)

View File

@ -253,11 +253,6 @@ static void ui_popup_block_position(wmWindow *window,
else {
offset_x = butrct.xmin - block->rect.xmin - center_x;
}
/* changed direction? */
if ((dir1 & block->direction) == 0) {
/* TODO: still do */
UI_block_order_flip(block);
}
}
else if (dir1 == UI_DIR_DOWN) {
offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
@ -276,11 +271,6 @@ static void ui_popup_block_position(wmWindow *window,
else {
offset_x = butrct.xmin - block->rect.xmin - center_x;
}
/* changed direction? */
if ((dir1 & block->direction) == 0) {
/* TODO: still do */
UI_block_order_flip(block);
}
}
/* Center over popovers for eg. */

View File

@ -2986,8 +2986,6 @@ static void constraint_ops_extra_draw(bContext *C, uiLayout *layout, void *con_v
uiLayoutSetUnitsX(layout, 4.0f);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
/* Apply. */
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
@ -3863,7 +3861,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *region, void *arg_lit
const int h = UI_UNIT_X * (args.icon_scale + args.show_labels);
uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS_PULLDOWN);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NO_FLIP);
UI_block_flag_enable(block, UI_BLOCK_LOOP);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
bool free;

View File

@ -2062,8 +2062,6 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
MoveToCollectionData *menu = static_cast<MoveToCollectionData *>(menu_v);
const char *name = BKE_collection_ui_name_get(menu->collection);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
RNA_int_set(&menu->ptr, "collection_index", menu->index);
RNA_boolean_set(&menu->ptr, "is_new", true);

View File

@ -473,8 +473,6 @@ static void workspace_add_menu(bContext * /*C*/, uiLayout *layout, void *templat
WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
if (startup_config) {
LISTBASE_FOREACH (WorkSpace *, workspace, &startup_config->workspaces) {
uiLayout *row = uiLayoutRow(layout, false);

View File

@ -533,8 +533,6 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void * /*a
last_category = user->category;
}
UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
}
void uiTemplateTextureUser(uiLayout *layout, bContext *C)

View File

@ -651,7 +651,6 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
bNodeSocket *sock = arg->sock;
bNodeTreeType *ntreetype = arg->ntree->typeinfo;
UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
UI_block_layout_set_current(block, layout);
split = uiLayoutSplit(layout, 0.0f, false);

View File

@ -240,8 +240,6 @@ static void gpencil_modifier_ops_extra_draw(bContext *C, uiLayout *layout, void
uiLayoutSetUnitsX(layout, 4.0f);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
/* Apply. */
if (!(mti->flags & eGpencilModifierTypeFlag_NoApply)) {
uiItemO(layout,

View File

@ -1197,7 +1197,7 @@ typedef enum eUserpref_UI_Flag {
USER_ZOOM_TO_MOUSEPOS = (1 << 20),
USER_SHOW_FPS = (1 << 21),
USER_REGISTER_ALL_USERS = (1 << 22),
USER_MENUFIXEDORDER = (1 << 23),
USER_UIFLAG_UNUSED_4 = (1 << 23), /* Cleared. */
USER_CONTINUOUS_MOUSE = (1 << 24),
USER_ZOOM_INVERT = (1 << 25),
USER_ZOOM_HORIZ = (1 << 26), /* for CONTINUE and DOLLY zoom */

View File

@ -4980,13 +4980,6 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_PLAINMENUS);
RNA_def_property_ui_text(prop, "Toolbox Column Layout", "Use a column layout for toolbox");
prop = RNA_def_property(srna, "use_directional_menus", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, nullptr, "uiflag", USER_MENUFIXEDORDER);
RNA_def_property_ui_text(prop,
"Contents Follow Opening Direction",
"Otherwise menus, etc will always be top to bottom, left to right, "
"no matter opening direction");
static const EnumPropertyItem header_align_items[] = {
{0, "NONE", 0, "Keep Existing", "Keep existing header alignment"},
{USER_HEADER_FROM_PREF, "TOP", 0, "Top", "Top aligned on load"},

View File

@ -206,8 +206,6 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v)
uiLayoutSetUnitsX(layout, 4.0f);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
/* Apply. */
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),

View File

@ -122,8 +122,6 @@ static void gpencil_shaderfx_ops_extra_draw(bContext *C, uiLayout *layout, void
uiLayoutSetUnitsX(layout, 4.0f);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
/* Duplicate. */
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate"),