diff --git a/source/blender/editors/include/ED_screen.hh b/source/blender/editors/include/ED_screen.hh index e23003ee45c..9b52eb9ce7f 100644 --- a/source/blender/editors/include/ED_screen.hh +++ b/source/blender/editors/include/ED_screen.hh @@ -685,6 +685,7 @@ void ED_region_generic_tools_region_message_subscribe( * Callback for #ARegionType.snap_size */ int ED_region_generic_tools_region_snap_size(const ARegion *region, int size, int axis); +int ED_region_generic_panel_region_snap_size(const ARegion *region, int size, int axis); /* `area_query.cc` */ diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index ccd45b469f1..77cc07f0173 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -313,6 +313,9 @@ enum { #define UI_PANEL_CATEGORY_MARGIN_WIDTH (U.widget_unit * 1.0f) +/* Minimum width for a panel showing only category tabs. */ +#define UI_PANEL_CATEGORY_MIN_WIDTH 26.0f + /* Both these margins should be ignored if the panel doesn't show a background (check * #UI_panel_should_show_background()). */ #define UI_PANEL_MARGIN_X (U.widget_unit * 0.4f) diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 02682ab7382..9ff05a8ee82 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1293,6 +1293,11 @@ void ui_draw_aligned_panel(const ARegion *region, { const Panel *panel = block->panel; + if (panel->sizex < 0 || panel->sizey < 0) { + /* Nothing to draw. */ + return; + } + /* Add 0.001f to prevent flicker from float inaccuracy. */ const rcti header_rect = { rect->xmin, @@ -1478,6 +1483,10 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) immUnbindProgram(); + /* If the area is too small to show panels, then don't show any tabs as active. */ + const bool too_narrow = BLI_rcti_size_x(®ion->winrct) <= + int(UI_PANEL_CATEGORY_MIN_WIDTH * UI_SCALE_FAC / aspect); + LISTBASE_FOREACH (PanelCategoryDyn *, pc_dyn, ®ion->runtime->panels_category) { const rcti *rct = &pc_dyn->rect; if (rct->ymin > v2d->mask.ymax) { @@ -1491,7 +1500,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) const char *category_id = pc_dyn->idname; const char *category_id_draw = IFACE_(category_id); size_t category_draw_len = BLF_DRAW_STR_DUMMY_MAX; - const bool is_active = STREQ(category_id, category_id_active); + const bool is_active = !too_narrow && STREQ(category_id, category_id_active); GPU_blend(GPU_BLEND_ALPHA); @@ -2517,6 +2526,25 @@ static int ui_handle_panel_category_cycling(const wmEvent *event, return WM_UI_HANDLER_CONTINUE; } +static void ui_panel_region_width_set(ARegion *region, const float aspect, int unscaled_size) +{ + const float size_new = unscaled_size / aspect; + if (region->alignment & RGN_ALIGN_RIGHT) { + region->winrct.xmin = region->winrct.xmax - (size_new * UI_SCALE_FAC); + } + else { + region->winrct.xmax = region->winrct.xmin + (size_new * UI_SCALE_FAC); + } + region->winx = size_new * UI_SCALE_FAC; + region->sizex = size_new; + region->v2d.winx = region->winx; + region->v2d.cur.xmin = 0; + region->v2d.cur.xmax = size_new * UI_SCALE_FAC; + region->v2d.mask.xmin = 0; + region->v2d.mask.xmax = size_new * UI_SCALE_FAC; + UI_view2d_curRect_validate(®ion->v2d); +} + int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *region, @@ -2544,7 +2572,26 @@ int ui_handler_panel_region(bContext *C, if (event->type == LEFTMOUSE) { PanelCategoryDyn *pc_dyn = panel_categories_find_mouse_over(region, event); if (pc_dyn) { + const bool already_active = STREQ(pc_dyn->idname, + UI_panel_category_active_get(region, false)); UI_panel_category_active_set(region, pc_dyn->idname); + + const float aspect = BLI_rctf_size_y(®ion->v2d.cur) / + (BLI_rcti_size_y(®ion->v2d.mask) + 1); + const bool too_narrow = BLI_rcti_size_x(®ion->winrct) <= + int(std::ceil(UI_PANEL_CATEGORY_MIN_WIDTH * UI_SCALE_FAC / + aspect)); + if (too_narrow) { + /* Enlarge region. */ + ui_panel_region_width_set(region, aspect, 250.0f); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, nullptr); + } + else if (already_active) { + /* Minimize region. */ + ui_panel_region_width_set(region, aspect, UI_PANEL_CATEGORY_MIN_WIDTH); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, nullptr); + } + ED_region_tag_redraw(region); /* Reset scroll to the top (#38348). */ diff --git a/source/blender/editors/screen/area.cc b/source/blender/editors/screen/area.cc index c037a996ec6..3589905f127 100644 --- a/source/blender/editors/screen/area.cc +++ b/source/blender/editors/screen/area.cc @@ -3376,6 +3376,16 @@ void ED_region_panels_draw(const bContext *C, ARegion *region) mask.xmax -= round_fl_to_int(UI_view2d_scale_get_x(®ion->v2d) * UI_PANEL_CATEGORY_MARGIN_WIDTH); } + + /* Hide scrollbars below a threshold. */ + const float aspect = BLI_rctf_size_y(®ion->v2d.cur) / + (BLI_rcti_size_y(®ion->v2d.mask) + 1); + int min_width = UI_panel_category_is_visible(region) ? 60.0f * UI_SCALE_FAC / aspect : + 40.0f * UI_SCALE_FAC / aspect; + if (BLI_rcti_size_x(®ion->winrct) <= min_width) { + v2d->scroll &= ~(V2D_SCROLL_HORIZONTAL | V2D_SCROLL_VERTICAL); + } + UI_view2d_scrollers_draw(v2d, use_mask ? &mask : nullptr); } diff --git a/source/blender/editors/screen/area_utils.cc b/source/blender/editors/screen/area_utils.cc index 0a6af0ee0f7..9d1bf9a81b4 100644 --- a/source/blender/editors/screen/area_utils.cc +++ b/source/blender/editors/screen/area_utils.cc @@ -66,4 +66,19 @@ int ED_region_generic_tools_region_snap_size(const ARegion *region, int size, in return size; } +int ED_region_generic_panel_region_snap_size(const ARegion *region, int size, int axis) +{ + if (axis == 0) { + if (!UI_panel_category_is_visible(region)) { + return size; + } + + /* Using Y axis avoids slight feedback loop when adjusting X. */ + const float aspect = BLI_rctf_size_y(®ion->v2d.cur) / + (BLI_rcti_size_y(®ion->v2d.mask) + 1); + return int(UI_PANEL_CATEGORY_MIN_WIDTH / aspect); + } + return size; +} + /** \} */ diff --git a/source/blender/editors/space_clip/space_clip.cc b/source/blender/editors/space_clip/space_clip.cc index 5d2d2e14263..6eae4706ca1 100644 --- a/source/blender/editors/space_clip/space_clip.cc +++ b/source/blender/editors/space_clip/space_clip.cc @@ -1275,6 +1275,7 @@ void ED_spacetype_clip() art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI; art->poll = clip_properties_region_poll; art->init = clip_properties_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->draw = clip_properties_region_draw; art->listener = clip_properties_region_listener; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_image/space_image.cc b/source/blender/editors/space_image/space_image.cc index ec8d251b5a3..baf2a46bc22 100644 --- a/source/blender/editors/space_image/space_image.cc +++ b/source/blender/editors/space_image/space_image.cc @@ -1249,6 +1249,7 @@ void ED_spacetype_image() art->listener = image_buttons_region_listener; art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; art->init = image_buttons_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->layout = image_buttons_region_layout; art->draw = image_buttons_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 5e4f3d5ecbc..272706ec2e3 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -2143,6 +2143,7 @@ void ED_spacetype_node() art->listener = node_region_listener; art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; art->init = node_buttons_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->draw = node_buttons_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_sequencer/space_sequencer.cc b/source/blender/editors/space_sequencer/space_sequencer.cc index 844eb81a7d5..f34e417480d 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.cc +++ b/source/blender/editors/space_sequencer/space_sequencer.cc @@ -1161,6 +1161,7 @@ void ED_spacetype_sequencer() art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; art->listener = sequencer_buttons_region_listener; art->init = sequencer_buttons_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->draw = sequencer_buttons_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_text/space_text.cc b/source/blender/editors/space_text/space_text.cc index 456e80213a4..f0826050cf2 100644 --- a/source/blender/editors/space_text/space_text.cc +++ b/source/blender/editors/space_text/space_text.cc @@ -460,6 +460,7 @@ void ED_spacetype_text() art->keymapflag = ED_KEYMAP_UI; art->init = text_properties_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->draw = text_properties_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index c4455aa68d4..b6a9aa9d7e4 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -1632,6 +1632,7 @@ void ED_spacetype_view3d() art->listener = view3d_buttons_region_listener; art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; art->init = view3d_buttons_region_init; + art->snap_size = ED_region_generic_panel_region_snap_size; art->layout = view3d_buttons_region_layout; art->draw = ED_region_panels_draw; BLI_addhead(&st->regiontypes, art);