diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2018-05-07 02:31:18 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2018-05-07 12:42:12 +0300 |
commit | 51efeb683451d896531baac949de65043edff0b6 (patch) | |
tree | a36b7c037205b77a78a0b0266a7e9ca4571a0a5a /source/blender/editors/screen/area.c | |
parent | 4ec467d3b52744ba2aa4f938973efa27202b23ee (diff) |
UI: Hide & shrink scroll-bars based on cursor position
Scroll-bars are now hidden unless the cursor approaches them, in which case they
smoothly grow and become more & more visible. Note that since 0d309144020168e55,
scroll-bars are drawn on top of editor contents. There's no more jumping of
buttons when scroll-bars appear.
Technical notes:
* AZones are used to adjust scrollbars based on mouse movements
We may want to support screen level AZones if we want scrollbars to also
smoothly appear when approaching them from a different area.
I also plan to make further changes to AZones to clean up stuff a bit.
* Had to move AZone handling to a post ARegion init stage, since we need the
updated View2D data from there.
* View2D masks and scroller rectangles are now updated on every redraw. It's
cheap to do that though.
Diffstat (limited to 'source/blender/editors/screen/area.c')
-rw-r--r-- | source/blender/editors/screen/area.c | 136 |
1 files changed, 98 insertions, 38 deletions
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 58dbebd2b75..e86655ab2cf 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -203,6 +203,24 @@ void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2]) break; } } + else if (az->type == AZONE_REGION_SCROLL) { + /* only if mouse is not hovering the azone */ + if (BLI_rcti_isect_pt_v(&az->rect, mouse_xy) == false) { + View2D *v2d = &az->ar->v2d; + + if (az->direction == AZ_SCROLL_VERT) { + az->alpha = v2d->alpha_vert = 0; + changed = true; + } + else if (az->direction == AZ_SCROLL_HOR) { + az->alpha = v2d->alpha_hor = 0; + changed = true; + } + else { + BLI_assert(0); + } + } + } } if (changed) { @@ -464,6 +482,12 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) area_azone_tag_update(sa); } } + else if (az->type == AZONE_REGION_SCROLL) { + if (az->alpha != 0.0f) { + area_azone_tag_update(sa); + } + /* Don't draw this azone. */ + } } } @@ -1043,7 +1067,7 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar) } -static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen) +static void region_azone_edge_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const bool is_fullscreen) { AZone *az = NULL; const bool is_hidden = (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) == 0; @@ -1074,21 +1098,76 @@ static void region_azone_initialize(ScrArea *sa, ARegion *ar, AZEdge edge, const } +static void region_azone_scrollbar_initialize(ScrArea *sa, ARegion *ar, AZScrollDirection direction) +{ + rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? ar->v2d.vert : ar->v2d.hor; + AZone *az = MEM_callocN(sizeof(*az), __func__); + + BLI_addtail(&sa->actionzones, az); + az->type = AZONE_REGION_SCROLL; + az->ar = ar; + az->direction = direction; + + if (direction == AZ_SCROLL_VERT) { + az->ar->v2d.alpha_vert = 0; + } + else if (direction == AZ_SCROLL_HOR) { + az->ar->v2d.alpha_hor = 0; + } + + BLI_rcti_translate(&scroller_vert, ar->winrct.xmin, ar->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; + + BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2); +} + +static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar) +{ + const View2D *v2d = &ar->v2d; + + if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) { + region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT); + } + if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) && ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) { + region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR); + } +} + /* *************************************************************** */ -static void region_azone_add(ScrArea *sa, ARegion *ar, const int alignment, const bool is_fullscreen) +static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, const int alignment) { + const bool is_fullscreen = screen->state == SCREENFULL; + /* edge code (t b l r) is along which area edge azone will be drawn */ - - if (alignment == RGN_ALIGN_TOP) - region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT, is_fullscreen); + + if (ar->regiontype == RGN_TYPE_HEADER && ar->winy + 6 > sa->winy) { + /* The logic for this is: when the header takes up the full area, + * disallow hiding it to view the main window. + * + * Without this, you can drag down the file selectors header and hide it + * by accident very easily (highly annoying!), the value 6 is arbitrary + * but accounts for small common rounding problems when scaling the UI, + * must be minimum '4' */ + } + else if (alignment == RGN_ALIGN_TOP) + region_azone_edge_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT, is_fullscreen); else if (alignment == RGN_ALIGN_BOTTOM) - region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen); + region_azone_edge_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen); else if (alignment == RGN_ALIGN_RIGHT) - region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen); + region_azone_edge_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT, is_fullscreen); else if (alignment == RGN_ALIGN_LEFT) - region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen); + region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen); + + if (is_fullscreen) { + fullscreen_azone_initialize(sa, ar); + } + + region_azones_scrollbars_initialize(sa, ar); } /* dir is direction to check, not the splitting edge direction! */ @@ -1193,7 +1272,7 @@ static bool region_is_overlap(ScrArea *sa, ARegion *ar) return 0; } -static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad, bool add_azones) +static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *remainder, rcti *overlap_remainder, int quad) { rcti *remainder_prev = remainder; int prefsizex, prefsizey; @@ -1421,30 +1500,8 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (!ar->overlap) { *overlap_remainder = *remainder; } - - /* in end, add azones, where appropriate */ - if (ar->regiontype == RGN_TYPE_HEADER && ar->winy + 6 > sa->winy) { - /* The logic for this is: when the header takes up the full area, - * disallow hiding it to view the main window. - * - * Without this, you can drag down the file selectors header and hide it - * by accident very easily (highly annoying!), the value 6 is arbitrary - * but accounts for small common rounding problems when scaling the UI, - * must be minimum '4' */ - } - else if (add_azones) { - const bScreen *screen = WM_window_get_active_screen(win); - if (ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) { - region_azone_add(sa, ar, alignment, false); - } - else { - region_azone_add(sa, ar, alignment, true); - fullscreen_azone_initialize(sa, ar); - } - } - - region_rect_recursive(win, sa, ar->next, remainder, overlap_remainder, quad, add_azones); + region_rect_recursive(win, sa, ar->next, remainder, overlap_remainder, quad); } static void area_calc_totrct(ScrArea *sa, int window_size_x, int window_size_y) @@ -1574,7 +1631,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar /* region rect sizes */ rect = area->totrct; overlap_rect = rect; - region_rect_recursive(win, area, area->regionbase.first, &rect, &overlap_rect, 0, false); + region_rect_recursive(win, area, area->regionbase.first, &rect, &overlap_rect, 0); for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) { region_subwindow(ar); @@ -1615,13 +1672,10 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* area sizes */ area_calc_totrct(sa, window_size_x, window_size_y); - /* clear all azones, add the area triange widgets */ - area_azone_initialize(win, screen, sa); - /* region rect sizes */ rect = sa->totrct; overlap_rect = rect; - region_rect_recursive(win, sa, sa->regionbase.first, &rect, &overlap_rect, 0, true); + region_rect_recursive(win, sa, sa->regionbase.first, &rect, &overlap_rect, 0); sa->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE; /* default area handlers */ @@ -1629,7 +1683,10 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* checks spacedata, adds own handlers */ if (sa->type->init) sa->type->init(wm, sa); - + + /* clear all azones, add the area triange widgets */ + area_azone_initialize(win, screen, sa); + /* region windows, default and own handlers */ for (ar = sa->regionbase.first; ar; ar = ar->next) { region_subwindow(ar); @@ -1646,6 +1703,9 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* prevent uiblocks to run */ UI_blocklist_free(NULL, &ar->uiblocks); } + + /* Some AZones use View2D data which is only updated in region init, so call that first! */ + region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV); } } |