UI: Scrollbar Behavior Changes

Changes to scrollbars so that they are always visible, but thin and
dim, and widen and become more visible as your mouse approaches.

See D6505 for details and examples.

Differential Revision: https://developer.blender.org/D6505

Reviewed by Campbell Barton
This commit is contained in:
Harley Acheson 2022-06-27 06:45:49 -07:00
parent 279e7dac7d
commit 6243972319
Notes: blender-bot 2023-02-14 08:49:53 +01:00
Referenced by commit c172522060, Fix T100141: Header Alignment of New Editors
Referenced by issue #100141, Regression: Right aligned header
Referenced by issue #69391, Scrollbars Design
5 changed files with 77 additions and 81 deletions

View File

@ -49,8 +49,21 @@ enum eView2D_CommonViewTypes {
/* ------ Defines for Scrollers ----- */
/** Scroll bar area. */
#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit)
#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit)
/* Maximum has to include outline which varies with line width. */
#define V2D_SCROLL_HEIGHT ((0.45f * U.widget_unit) + (2.0f * U.pixelsize))
#define V2D_SCROLL_WIDTH ((0.45f * U.widget_unit) + (2.0f * U.pixelsize))
/* Alpha of scrollbar when at minimum size. */
#define V2D_SCROLL_MIN_ALPHA (0.4f)
/* Minimum size needs to include outline which varies with line width. */
#define V2D_SCROLL_MIN_WIDTH ((5.0f * U.dpi_fac) + (2.0f * U.pixelsize))
/* When to start showing the full-width scroller. */
#define V2D_SCROLL_HIDE_WIDTH (AREAMINX * U.dpi_fac)
#define V2D_SCROLL_HIDE_HEIGHT (HEADERY * U.dpi_fac)
/** Scroll bars with 'handles' used for scale (zoom). */
#define V2D_SCROLL_HANDLE_HEIGHT (0.6f * U.widget_unit)
#define V2D_SCROLL_HANDLE_WIDTH (0.6f * U.widget_unit)
@ -236,9 +249,13 @@ void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *region,
void UI_view2d_scrollers_calc(struct View2D *v2d,
const struct rcti *mask_custom,
struct View2DScrollers *r_scrollers);
/**
* Draw scroll-bars in the given 2D-region.
*/
void UI_view2d_scrollers_draw_ex(struct View2D *v2d,
const struct rcti *mask_custom,
bool use_full_hide);
void UI_view2d_scrollers_draw(struct View2D *v2d, const struct rcti *mask_custom);
/* List view tools. */
@ -329,8 +346,10 @@ struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
/**
* Get scrollbar sizes of the current 2D view.
* The size will be zero if the view has its scrollbars disabled.
*
* \param mapped: whether to use view2d_scroll_mapped which changes flags
*/
void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y);
void UI_view2d_scroller_size_get(const struct View2D *v2d, bool mapped, float *r_x, float *r_y);
/**
* Calculate the scale per-axis of the drawing-area
*

View File

@ -143,6 +143,11 @@ static void hud_panels_register(ARegionType *art, int space_type, int region_typ
static void hud_region_init(wmWindowManager *wm, ARegion *region)
{
ED_region_panels_init(wm, region);
/* Reset zoom from panels init because we don't want zoom allowed for redo panel. */
region->v2d.maxzoom = 1.0f;
region->v2d.minzoom = 1.0f;
UI_region_handlers_add(&region->handlers);
region->flag |= RGN_FLAG_TEMP_REGIONDATA;
}
@ -251,7 +256,7 @@ static ARegion *hud_region_add(ScrArea *area)
if (region_win) {
float x, y;
UI_view2d_scroller_size_get(&region_win->v2d, &x, &y);
UI_view2d_scroller_size_get(&region_win->v2d, true, &x, &y);
region->runtime.offset_x = x;
region->runtime.offset_y = y;
}

View File

@ -149,7 +149,9 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
}
}
scroll = view2d_scroll_mapped(v2d->scroll);
/* Do not use mapped scroll here because we want to update scroller rects
* even if they are not displayed. For init purposes. See T75003.*/
scroll = v2d->scroll;
/* Scrollers are based off region-size:
* - they can only be on one to two edges of the region they define
@ -158,7 +160,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
if (scroll) {
float scroll_width, scroll_height;
UI_view2d_scroller_size_get(v2d, &scroll_width, &scroll_height);
UI_view2d_scroller_size_get(v2d, false, &scroll_width, &scroll_height);
/* vertical scroller */
if (scroll & V2D_SCROLL_LEFT) {
@ -191,18 +193,6 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
v2d->hor = *mask_scroll;
v2d->hor.ymin = v2d->hor.ymax - scroll_height;
}
/* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
if (scroll & V2D_SCROLL_VERTICAL) {
if (scroll & V2D_SCROLL_BOTTOM) {
/* on bottom edge of region */
v2d->vert.ymin = v2d->hor.ymax;
}
else if (scroll & V2D_SCROLL_TOP) {
/* on upper edge of region */
v2d->vert.ymax = v2d->hor.ymin;
}
}
}
}
@ -260,6 +250,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
v2d->keeptot = V2D_KEEPTOT_STRICT;
v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
tot_changed = do_init;
/* scroller settings are currently not set here... that is left for regions... */
@ -276,6 +267,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
/* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
v2d->keeptot = V2D_KEEPTOT_STRICT;
v2d->keepofs = (V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
tot_changed = do_init;
/* scroller settings are currently not set here... that is left for regions... */
@ -493,8 +485,8 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
}
/* check if we should restore aspect ratio (if view size changed) */
if (v2d->keepzoom & V2D_KEEPASPECT) {
bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
if (v2d->keepzoom & V2D_KEEPASPECT && !(v2d->keeptot == V2D_KEEPTOT_STRICT)) {
bool do_x = false, do_y = false, do_cur;
float curRatio, winRatio;
/* when a window edge changes, the aspect ratio can't be used to
@ -532,53 +524,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
/* do_win = do_y; */ /* UNUSED */
if (do_cur) {
if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winx != v2d->oldwinx)) {
/* Special exception for Outliner (and later channel-lists):
* - The view may be moved left to avoid contents
* being pushed out of view when view shrinks.
* - The keeptot code will make sure cur->xmin will not be less than tot->xmin
* (which cannot be allowed).
* - width is not adjusted for changed ratios here.
*/
if (winx < v2d->oldwinx) {
const float temp = v2d->oldwinx - winx;
cur->xmin -= temp;
cur->xmax -= temp;
/* width does not get modified, as keepaspect here is just set to make
* sure visible area adjusts to changing view shape!
*/
}
}
else {
/* portrait window: correct for x */
width = height / winRatio;
}
/* portrait window: correct for x */
width = height / winRatio;
}
else {
if ((v2d->keeptot == V2D_KEEPTOT_STRICT) && (winy != v2d->oldwiny)) {
/* special exception for Outliner (and later channel-lists):
* - Currently, no actions need to be taken here...
*/
if (winy < v2d->oldwiny) {
const float temp = v2d->oldwiny - winy;
if (v2d->align & V2D_ALIGN_NO_NEG_Y) {
cur->ymin -= temp;
cur->ymax -= temp;
}
else { /* Assume V2D_ALIGN_NO_POS_Y or combination */
cur->ymin += temp;
cur->ymax += temp;
}
}
}
else {
/* landscape window: correct for y */
height = width * winRatio;
}
/* landscape window: correct for y */
height = width * winRatio;
}
/* store region size for next time */
@ -1510,7 +1461,7 @@ void UI_view2d_scrollers_calc(View2D *v2d,
}
}
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
void UI_view2d_scrollers_draw_ex(View2D *v2d, const rcti *mask_custom, bool use_full_hide)
{
View2DScrollers scrollers;
UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers);
@ -1518,6 +1469,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
rcti vert, hor;
const int scroll = view2d_scroll_mapped(v2d->scroll);
const char emboss_alpha = btheme->tui.widget_emboss[3];
const float alpha_min = use_full_hide ? 0.0f : V2D_SCROLL_MIN_ALPHA;
uchar scrollers_back_color[4];
/* Color for scrollbar backs */
@ -1530,7 +1483,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
/* horizontal scrollbar */
if (scroll & V2D_SCROLL_HORIZONTAL) {
uiWidgetColors wcol = btheme->tui.wcol_scroll;
const float alpha_fac = v2d->alpha_hor / 255.0f;
/* 0..255 -> min...1 */
const float alpha_fac = ((v2d->alpha_hor / 255.0f) * (1.0f - alpha_min)) + alpha_min;
rcti slider;
int state;
@ -1543,8 +1497,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
wcol.inner[3] *= alpha_fac;
wcol.item[3] *= alpha_fac;
wcol.outline[3] *= alpha_fac;
btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
wcol.outline[3] = 0;
btheme->tui.widget_emboss[3] = 0; /* will be reset later */
/* show zoom handles if:
* - zooming on x-axis is allowed (no scroll otherwise)
@ -1565,7 +1519,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
if (scroll & V2D_SCROLL_VERTICAL) {
uiWidgetColors wcol = btheme->tui.wcol_scroll;
rcti slider;
const float alpha_fac = v2d->alpha_vert / 255.0f;
/* 0..255 -> min...1 */
const float alpha_fac = ((v2d->alpha_vert / 255.0f) * (1.0f - alpha_min)) + alpha_min;
int state;
slider.xmin = vert.xmin;
@ -1577,8 +1532,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
wcol.inner[3] *= alpha_fac;
wcol.item[3] *= alpha_fac;
wcol.outline[3] *= alpha_fac;
btheme->tui.widget_emboss[3] *= alpha_fac; /* will be reset later */
wcol.outline[3] = 0;
btheme->tui.widget_emboss[3] = 0; /* will be reset later */
/* show zoom handles if:
* - zooming on y-axis is allowed (no scroll otherwise)
@ -1599,6 +1554,11 @@ void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
btheme->tui.widget_emboss[3] = emboss_alpha;
}
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
{
UI_view2d_scrollers_draw_ex(v2d, mask_custom, false);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -1835,13 +1795,14 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C)
return &(region->v2d);
}
void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y)
void UI_view2d_scroller_size_get(const View2D *v2d, bool mapped, float *r_x, float *r_y)
{
const int scroll = view2d_scroll_mapped(v2d->scroll);
const int scroll = (mapped) ? view2d_scroll_mapped(v2d->scroll) : v2d->scroll;
if (r_x) {
if (scroll & V2D_SCROLL_VERTICAL) {
*r_x = (scroll & V2D_SCROLL_VERTICAL_HANDLES) ? V2D_SCROLL_HANDLE_WIDTH : V2D_SCROLL_WIDTH;
*r_x = ((*r_x - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_vert / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
}
else {
*r_x = 0;
@ -1851,6 +1812,7 @@ void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y)
if (scroll & V2D_SCROLL_HORIZONTAL) {
*r_y = (scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ? V2D_SCROLL_HANDLE_HEIGHT :
V2D_SCROLL_HEIGHT;
*r_y = ((*r_y - V2D_SCROLL_MIN_WIDTH) * (v2d->alpha_hor / 255.0f)) + V2D_SCROLL_MIN_WIDTH;
}
else {
*r_y = 0;

View File

@ -1075,6 +1075,7 @@ static void region_azone_scrollbar_init(ScrArea *area,
{
rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? region->v2d.vert : region->v2d.hor;
AZone *az = MEM_callocN(sizeof(*az), __func__);
float hide_width;
BLI_addtail(&area->actionzones, az);
az->type = AZONE_REGION_SCROLL;
@ -1083,16 +1084,18 @@ static void region_azone_scrollbar_init(ScrArea *area,
if (direction == AZ_SCROLL_VERT) {
az->region->v2d.alpha_vert = 0;
hide_width = V2D_SCROLL_HIDE_HEIGHT;
}
else if (direction == AZ_SCROLL_HOR) {
az->region->v2d.alpha_hor = 0;
hide_width = V2D_SCROLL_HIDE_WIDTH;
}
BLI_rcti_translate(&scroller_vert, region->winrct.xmin, region->winrct.ymin);
az->x1 = scroller_vert.xmin - AZONEFADEIN;
az->y1 = scroller_vert.ymin - AZONEFADEIN;
az->x2 = scroller_vert.xmax + AZONEFADEIN;
az->y2 = scroller_vert.ymax + AZONEFADEIN;
az->x1 = scroller_vert.xmin - ((direction == AZ_SCROLL_VERT) ? hide_width : 0);
az->y1 = scroller_vert.ymin - ((direction == AZ_SCROLL_HOR) ? hide_width : 0);
az->x2 = scroller_vert.xmax + ((direction == AZ_SCROLL_VERT) ? hide_width : 0);
az->y2 = scroller_vert.ymax + ((direction == AZ_SCROLL_HOR) ? hide_width : 0);
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
@ -3125,7 +3128,12 @@ void ED_region_panels_draw(const bContext *C, ARegion *region)
UI_view2d_mask_from_win(v2d, &mask);
mask.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH;
}
UI_view2d_scrollers_draw(v2d, use_mask ? &mask : NULL);
bool use_full_hide = false;
if (region->overlap) {
/* Don't always show scrollbars for transparent regions as it's distracting. */
use_full_hide = true;
}
UI_view2d_scrollers_draw_ex(v2d, use_mask ? &mask : NULL, use_full_hide);
}
void ED_region_panels_ex(const bContext *C, ARegion *region, const char *contexts[])

View File

@ -887,14 +887,16 @@ static AZone *area_actionzone_refresh_xy(ScrArea *area, const int xy[2], const b
float dist_fac = 0.0f, alpha = 0.0f;
if (az->direction == AZ_SCROLL_HOR) {
dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN;
float hide_width = (az->y2 - az->y1) / 2.0f;
dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / hide_width;
CLAMP(dist_fac, 0.0f, 1.0f);
alpha = 1.0f - dist_fac;
v2d->alpha_hor = alpha * 255;
}
else if (az->direction == AZ_SCROLL_VERT) {
dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN;
float hide_width = (az->x2 - az->x1) / 2.0f;
dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / hide_width;
CLAMP(dist_fac, 0.0f, 1.0f);
alpha = 1.0f - dist_fac;