From 427bdc8dcf3a10b31d4982b488ecb619d3ab2916 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 22 Sep 2023 17:15:12 +0200 Subject: [PATCH] UI: Remove dead space between tree view items Part of #107742. There used to be a small margin between items since the layout feels a bit crammed otherwise. But this meant the mouse could be between items, with no item highlighted or reacting to interactions. This was especially annoying when dragging over items for drag and drop: in between items dropping wasn't possible, and the drag-tooltip would disappear, causing notable flickering during motions over the tree view. The view item is now slightly enlarged to keep a look that is not too crammed, and still remove the space between items. Item highlights are still drawn with a smaller height (matching the normal widget height), since anything else looked odd to me. This now feels quite consistent with similar UIs (e.g. File Browser list view or the Outliner), even though we give the items a bit more space. --- .../editors/interface/interface_intern.hh | 4 ++++ .../editors/interface/interface_widgets.cc | 21 +++++++++++++++---- .../editors/interface/views/tree_view.cc | 15 ++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 727d8bd4139..7b89bb2fa48 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -369,6 +369,10 @@ struct uiButProgress : public uiBut { struct uiButViewItem : public uiBut { /* C-Handle to the view item this button was created for. */ uiViewItemHandle *view_item = nullptr; + /* Some items want to have a fixed size for drawing, differing from the interaction rectangle + * (e.g. so highlights are drawn smaller). */ + int draw_width = 0; + int draw_height = 0; }; /** Derived struct for #UI_BTYPE_HSVCUBE. */ diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 0a29ed093bd..18cbe3fd94f 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -4178,19 +4178,32 @@ static void widget_menu_radial_itembut(uiBut *but, widgetbase_draw(&wtb, wcol); } -static void widget_list_itembut(uiWidgetColors *wcol, +static void widget_list_itembut(uiBut *but, + uiWidgetColors *wcol, rcti *rect, const uiWidgetStateInfo *state, int /*roundboxalign*/, const float zoom) { + rcti draw_rect = *rect; + + if (but->type == UI_BTYPE_VIEW_ITEM) { + uiButViewItem *item_but = static_cast(but); + if (item_but->draw_width > 0) { + BLI_rcti_resize_x(&draw_rect, item_but->draw_width); + } + if (item_but->draw_height > 0) { + BLI_rcti_resize_y(&draw_rect, item_but->draw_height); + } + } + uiWidgetBase wtb; widget_init(&wtb); /* no outline */ wtb.draw_outline = false; const float rad = widget_radius_from_zoom(zoom, wcol); - round_box_edges(&wtb, UI_CNR_ALL, rect, rad); + round_box_edges(&wtb, UI_CNR_ALL, &draw_rect, rad); if (state->but_flag & UI_ACTIVE && !(state->but_flag & UI_SELECT)) { copy_v3_v3_uchar(wcol->inner, wcol->text); @@ -4208,7 +4221,7 @@ static void widget_preview_tile(uiBut *but, const float zoom) { if (!ELEM(but->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { - widget_list_itembut(wcol, rect, state, roundboxalign, zoom); + widget_list_itembut(but, wcol, rect, state, roundboxalign, zoom); } /* When the button is not tagged as having a preview icon, do regular icon drawing with the @@ -4666,7 +4679,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_LISTITEM: case UI_WTYPE_VIEW_ITEM: wt.wcol_theme = &btheme->tui.wcol_list_item; - wt.draw = widget_list_itembut; + wt.custom = widget_list_itembut; break; case UI_WTYPE_PROGRESS: diff --git a/source/blender/editors/interface/views/tree_view.cc b/source/blender/editors/interface/views/tree_view.cc index f0bc5a246fd..816965064a0 100644 --- a/source/blender/editors/interface/views/tree_view.cc +++ b/source/blender/editors/interface/views/tree_view.cc @@ -26,6 +26,16 @@ namespace blender::ui { +static int unpadded_item_height() +{ + return UI_UNIT_Y; +} +static int padded_item_height() +{ + const uiStyle *style = UI_style_get_dpi(); + return unpadded_item_height() + style->buttonspacey; +} + /* ---------------------------------------------------------------------- */ AbstractTreeViewItem &TreeViewItemContainer::add_tree_item( @@ -300,6 +310,7 @@ void AbstractTreeViewItem::add_treerow_button(uiBlock &block) &block, UI_BTYPE_VIEW_ITEM, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, nullptr, 0, 0, 0, 0, ""); view_item_but_->view_item = reinterpret_cast(this); + view_item_but_->draw_height = unpadded_item_height(); UI_but_func_set(view_item_but_, tree_row_click_fn, view_item_but_, nullptr); } @@ -579,7 +590,7 @@ void TreeViewLayoutBuilder::build_from_tree(const AbstractTreeView &tree_view) uiLayout &parent_layout = current_layout(); uiLayout *box = uiLayoutBox(&parent_layout); - uiLayoutColumn(box, false); + uiLayoutColumn(box, true); tree_view.foreach_item([this](AbstractTreeViewItem &item) { build_row(item); }, AbstractTreeView::IterOptions::SkipCollapsed | @@ -616,6 +627,8 @@ void TreeViewLayoutBuilder::build_row(AbstractTreeViewItem &item) const if (!item.is_interactive_) { uiLayoutSetActive(overlap, false); } + /* Scale the layout for the padded height. Widgets will be vertically centered then. */ + uiLayoutSetScaleY(overlap, float(padded_item_height()) / UI_UNIT_Y); uiLayout *row = uiLayoutRow(overlap, false); /* Enable emboss for mouse hover highlight. */