UI: Draw scroll-bars overlapping with editor content
authorJulian Eisel <eiseljulian@gmail.com>
Thu, 26 Apr 2018 22:49:00 +0000 (00:49 +0200)
committerJulian Eisel <eiseljulian@gmail.com>
Mon, 7 May 2018 09:42:12 +0000 (11:42 +0200)
Scroll-bars used to draw in a little extra space in the editor, causing
buttons to jump a bit when they appeared/disappeared. Now they draw on
top of the buttons, just small enough to avoid bigger overlaps. Followup commits
will do further adjustments.

With this we can get rid of a hack that was calling the (often Python
defined) panel definition - the panel 'draw' callback - twice.

source/blender/editors/include/UI_view2d.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_panel.c
source/blender/editors/interface/view2d.c
source/blender/editors/interface/view2d_ops.c
source/blender/editors/screen/area.c

index 65c69c7f2878073cc23407af35312d22ab767d0e..a19b2f05e2e2f03f65d3217def52a14bc25ac163 100644 (file)
@@ -103,11 +103,11 @@ enum eView2D_Gridlines {
 /* ------ Defines for Scrollers ----- */
 
 /* scroller area */
-#define V2D_SCROLL_HEIGHT      (0.55f * U.widget_unit)
-#define V2D_SCROLL_WIDTH       (0.55f * U.widget_unit)
+#define V2D_SCROLL_HEIGHT      (0.45f * U.widget_unit)
+#define V2D_SCROLL_WIDTH       (0.45f * U.widget_unit)
 /* For scrollers with scale markings (text written onto them) */
-#define V2D_SCROLL_HEIGHT_TEXT (0.85f * U.widget_unit)
-#define V2D_SCROLL_WIDTH_TEXT  (0.85f * U.widget_unit)
+#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit)
+#define V2D_SCROLL_WIDTH_TEXT  (0.79f * U.widget_unit)
 
 /* scroller 'handles' hotspot radius for mouse */
 #define V2D_SCROLLER_HANDLE_SIZE    (0.6f * U.widget_unit)
@@ -222,7 +222,7 @@ void UI_view2d_center_set(struct View2D *v2d, float x, float y);
 
 void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac);
 
-short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
+short UI_view2d_mouse_in_scrollers(const struct ARegion *ar, struct View2D *v2d, int x, int y);
 
 /* cached text drawing in v2d, to allow pixel-aligned draw as post process */
 void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y,
index 4d6a43d3a759f62e22faae7d2a75af6ef9e88f40..704a602f6c149933d29562514556f2eb86712752 100644 (file)
@@ -75,6 +75,7 @@
 #include "ED_keyframing.h"
 
 #include "UI_interface.h"
+#include "UI_view2d.h"
 
 #include "BLF_api.h"
 
@@ -7411,8 +7412,9 @@ static bool ui_region_contains_point_px(ARegion *ar, int x, int y)
                ui_window_to_region(ar, &mx, &my);
 
                /* check if in the rect */
-               if (!BLI_rcti_isect_pt(&v2d->mask, mx, my))
+               if (!BLI_rcti_isect_pt(&v2d->mask, mx, my) || UI_view2d_mouse_in_scrollers(ar, &ar->v2d, x, y)) {
                        return false;
+               }
        }
        
        return true;
index aa10efe45cb840627978671ddbfd3d590e6ea080..f621a9067893886821201198255e70c2ab7b47b3 100644 (file)
@@ -2017,6 +2017,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons
 
        retval = WM_UI_HANDLER_CONTINUE;
 
+       /* Scrollbars can overlap panels now, they have handling priority. */
+       if (UI_view2d_mouse_in_scrollers(ar, &ar->v2d, event->x, event->y)) {
+               return retval;
+       }
+
        /* handle category tabs */
        if (has_category_tabs) {
                if (event->val == KM_PRESS) {
index 10be0b52ba53f0f1a9e174b5c425f581665e43c8..8342387f956743f129e2b031d095e7b01f5b9e37 100644 (file)
@@ -147,7 +147,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
        
        scroll = view2d_scroll_mapped(v2d->scroll);
        
-       /* scrollers shrink mask area, but should be based off regionsize 
+       /* scrollers are based off regionsize
         *      - they can only be on one to two edges of the region they define
         *      - if they overlap, they must not occupy the corners (which are reserved for other widgets)
         */
@@ -162,14 +162,12 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
                        /* on left-hand edge of region */
                        v2d->vert = v2d->mask;
                        v2d->vert.xmax = scroll_width;
-                       v2d->mask.xmin = v2d->vert.xmax + 1;
                }
                else if (scroll & V2D_SCROLL_RIGHT) {
                        /* on right-hand edge of region */
                        v2d->vert = v2d->mask;
                        v2d->vert.xmax++; /* one pixel extra... was leaving a minor gap... */
                        v2d->vert.xmin = v2d->vert.xmax - scroll_width;
-                       v2d->mask.xmax = v2d->vert.xmin - 1;
                }
                
                /* horizontal scroller */
@@ -177,25 +175,22 @@ static void view2d_masks(View2D *v2d, bool check_scrollers)
                        /* on bottom edge of region */
                        v2d->hor = v2d->mask;
                        v2d->hor.ymax = scroll_height;
-                       v2d->mask.ymin = v2d->hor.ymax + 1;
                }
                else if (scroll & V2D_SCROLL_TOP) {
                        /* on upper edge of region */
                        v2d->hor = v2d->mask;
                        v2d->hor.ymin = v2d->hor.ymax - scroll_height;
-                       v2d->mask.ymax = v2d->hor.ymin - 1;
                }
                
                /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
                if (scroll & V2D_SCROLL_VERTICAL) {
-                       /* just set y min/max for vertical scroller to y min/max of mask as appropriate */
                        if (scroll & (V2D_SCROLL_BOTTOM)) {
                                /* on bottom edge of region */
-                               v2d->vert.ymin = v2d->mask.ymin;
+                               v2d->vert.ymin = v2d->hor.ymax;
                        }
                        else if (scroll & V2D_SCROLL_TOP) {
                                /* on upper edge of region */
-                               v2d->vert.ymax = v2d->mask.ymax;
+                               v2d->vert.ymax = v2d->hor.ymin;
                        }
                }
        }
@@ -1650,7 +1645,7 @@ View2DScrollers *UI_view2d_scrollers_calc(
        hor = v2d->hor;
        
        /* slider rects need to be smaller than region */
-       smaller = (int)(0.2f * U.widget_unit);
+       smaller = (int)(0.1f * U.widget_unit);
        hor.xmin += smaller;
        hor.xmax -= smaller;
        if (scroll & V2D_SCROLL_BOTTOM)
@@ -1848,20 +1843,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
                {
                        state |= UI_SCROLL_ARROWS;
                }
-               
-               /* clean rect behind slider, but not with transparent background */
-               if (scrollers_back_color[3] == 255) {
-                       Gwn_VertFormat *format = immVertexFormat();
-                       unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
-
-                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
-                       immUniformColor3ubv(scrollers_back_color);
-                       immRecti(pos, v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
 
-                       immUnbindProgram();
-               }
-               
                UI_draw_widget_scroll(&wcol, &hor, &slider, state);
                
                /* scale indicators */
@@ -1960,19 +1942,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
                        state |= UI_SCROLL_ARROWS;
                }
                
-               /* clean rect behind slider, but not with transparent background */
-               if (scrollers_back_color[3] == 255) {
-                       Gwn_VertFormat *format = immVertexFormat();
-                       unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
-
-                       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
-                       immUniformColor3ubv(scrollers_back_color);
-                       immRecti(pos, v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
-
-                       immUnbindProgram();
-               }
-               
                UI_draw_widget_scroll(&wcol, &vert, &slider, state);
                
                
@@ -2427,9 +2396,8 @@ void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac)
  * - 'v' = in vertical scroller.
  * - 0 = not in scroller.
  */
-short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y)
+short UI_view2d_mouse_in_scrollers(const ARegion *ar, View2D *v2d, int x, int y)
 {
-       ARegion *ar = CTX_wm_region(C);
        int co[2];
        int scroll = view2d_scroll_mapped(v2d->scroll);
        
index 6150b7e254e696e3f36ee042ae4dfbf506c144f1..90ef47aa7123e36c2aec2592707fdd6cba3a4cc6 100644 (file)
@@ -1908,7 +1908,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
        short in_scroller = 0;
                
        /* check if mouse in scrollbars, if they're enabled */
-       in_scroller = UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y);
+       in_scroller = UI_view2d_mouse_in_scrollers(ar, v2d, event->x, event->y);
        
        /* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */
        if (in_scroller) {
index 89e22aebed005b2245bddd05f8fbab93d92cded2..58dbebd2b7507c44a6137d2fb4f4a5604dbb11a6 100644 (file)
@@ -1986,7 +1986,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
        View2DScrollers *scrollers;
        int x, y, xco, yco, w, em, triangle;
        bool is_context_new = 0;
-       int redo;
        int scroll;
 
        bool use_category_tabs = (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI));  /* XXX, should use some better check? */
@@ -2064,140 +2063,131 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
        }
 
 
-       /* sortof hack - but we cannot predict the height of panels, until it's being generated */
-       /* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
-       /* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
-       for (redo = 2; redo > 0; redo--) {
-               
-               if (vertical) {
-                       w = BLI_rctf_size_x(&v2d->cur);
-                       em = (ar->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */
-               }
-               else {
-                       w = UI_PANEL_WIDTH;
-                       em = (ar->type->prefsizex) ? 10 : 20;
-               }
+       if (vertical) {
+               w = BLI_rctf_size_x(&v2d->cur);
+               em = (ar->type->prefsizex) ? 10 : 20; /* works out to 10*UI_UNIT_X or 20*UI_UNIT_X */
+       }
+       else {
+               w = UI_PANEL_WIDTH;
+               em = (ar->type->prefsizex) ? 10 : 20;
+       }
 
-               w -= margin_x;
-               
-               /* create panels */
-               UI_panels_begin(C, ar);
+       w -= margin_x;
 
-               /* set view2d view matrix  - UI_block_begin() stores it */
-               UI_view2d_view_ortho(v2d);
+       /* create panels */
+       UI_panels_begin(C, ar);
 
-               BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
-               {
-                       bool open;
+       /* set view2d view matrix  - UI_block_begin() stores it */
+       UI_view2d_view_ortho(v2d);
 
-                       panel = UI_panel_find_by_type(ar, pt);
+       BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
+       {
+               bool open;
 
-                       if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
-                               if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
-                                       continue;
-                               }
+               panel = UI_panel_find_by_type(ar, pt);
+
+               if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
+                       if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
+                               continue;
                        }
+               }
 
-                       /* draw panel */
-                       block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
-                       panel = UI_panel_begin(sa, ar, block, pt, panel, &open);
+               /* draw panel */
+               block = UI_block_begin(C, ar, pt->idname, UI_EMBOSS);
+               panel = UI_panel_begin(sa, ar, block, pt, panel, &open);
 
-                       /* bad fixed values */
-                       triangle = (int)(UI_UNIT_Y * 1.1f);
+               /* bad fixed values */
+               triangle = (int)(UI_UNIT_Y * 1.1f);
 
-                       if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
-                               /* for enabled buttons */
-                               panel->layout = UI_block_layout(
-                                       block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
-                                       triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
+               if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+                       /* for enabled buttons */
+                       panel->layout = UI_block_layout(
+                                       block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+                                       triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
 
-                               pt->draw_header(C, panel);
+                       pt->draw_header(C, panel);
 
-                               UI_block_layout_resolve(block, &xco, &yco);
-                               panel->labelofs = xco - triangle;
-                               panel->layout = NULL;
-                       }
-                       else {
-                               panel->labelofs = 0;
-                       }
+                       UI_block_layout_resolve(block, &xco, &yco);
+                       panel->labelofs = xco - triangle;
+                       panel->layout = NULL;
+               }
+               else {
+                       panel->labelofs = 0;
+               }
 
-                       if (open) {
-                               short panelContext;
+               if (open) {
+                       short panelContext;
 
-                               /* panel context can either be toolbar region or normal panels region */
-                               if (ar->regiontype == RGN_TYPE_TOOLS)
-                                       panelContext = UI_LAYOUT_TOOLBAR;
-                               else
-                                       panelContext = UI_LAYOUT_PANEL;
+                       /* panel context can either be toolbar region or normal panels region */
+                       if (ar->regiontype == RGN_TYPE_TOOLS)
+                               panelContext = UI_LAYOUT_TOOLBAR;
+                       else
+                               panelContext = UI_LAYOUT_PANEL;
 
-                               panel->layout = UI_block_layout(
-                                       block, UI_LAYOUT_VERTICAL, panelContext,
-                                       style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
+                       panel->layout = UI_block_layout(
+                                       block, UI_LAYOUT_VERTICAL, panelContext,
+                                       style->panelspace, 0, w - 2 * style->panelspace, em, 0, style);
 
-                               pt->draw(C, panel);
+                       pt->draw(C, panel);
 
-                               UI_block_layout_resolve(block, &xco, &yco);
-                               panel->layout = NULL;
+                       UI_block_layout_resolve(block, &xco, &yco);
+                       panel->layout = NULL;
+
+                       yco -= 2 * style->panelspace;
+                       UI_panel_end(block, w, -yco);
+               }
+               else {
+                       yco = 0;
+                       UI_panel_end(block, w, 0);
+               }
+
+               UI_block_end(C, block);
+       }
+       BLI_SMALLSTACK_ITER_END;
 
-                               yco -= 2 * style->panelspace;
-                               UI_panel_end(block, w, -yco);
+       /* align panels and return size */
+       UI_panels_end(C, ar, &x, &y);
+
+       /* before setting the view */
+       if (vertical) {
+               /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
+               if (v2d->cur.ymax < -FLT_EPSILON) {
+                       /* Clamp to lower view boundary */
+                       if (v2d->tot.ymin < -v2d->winy) {
+                               y = min_ii(y, 0);
                        }
                        else {
-                               yco = 0;
-                               UI_panel_end(block, w, 0);
+                               y = min_ii(y, v2d->cur.ymin);
                        }
-
-                       UI_block_end(C, block);
                }
-               BLI_SMALLSTACK_ITER_END;
 
-               /* align panels and return size */
-               UI_panels_end(C, ar, &x, &y);
-               
-               /* before setting the view */
-               if (vertical) {
-                       /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
-                       if (v2d->cur.ymax < -FLT_EPSILON) {
-                               /* Clamp to lower view boundary */
-                               if (v2d->tot.ymin < -v2d->winy) {
-                                       y = min_ii(y, 0);
-                               }
-                               else {
-                                       y = min_ii(y, v2d->cur.ymin);
-                               }
+               y = -y;
+       }
+       else {
+               /* don't jump back when panels close or hide */
+               if (!is_context_new) {
+                       if (v2d->tot.xmax > v2d->winx) {
+                               x = max_ii(x, 0);
                        }
-
-                       y = -y;
-               }
-               else {
-                       /* don't jump back when panels close or hide */
-                       if (!is_context_new) {
-                               if (v2d->tot.xmax > v2d->winx) {
-                                       x = max_ii(x, 0);
-                               }
-                               else {
-                                       x = max_ii(x, v2d->cur.xmax);
-                               }
+                       else {
+                               x = max_ii(x, v2d->cur.xmax);
                        }
-
-                       y = -y;
                }
-               
-               /* this also changes the 'cur' */
-               UI_view2d_totRect_set(v2d, x, y);
-               
-               if (scroll != v2d->scroll) {
-                       /* Note: this code scales fine, but because of rounding differences, positions of elements
-                        * flip +1 or -1 pixel compared to redoing the entire layout again.
-                        * Leaving in commented code for future tests */
+
+               y = -y;
+       }
+
+       /* this also changes the 'cur' */
+       UI_view2d_totRect_set(v2d, x, y);
+
+       if (scroll != v2d->scroll) {
+               /* Note: this code scales fine, but because of rounding differences, positions of elements
+                * flip +1 or -1 pixel compared to redoing the entire layout again.
+                * Leaving in commented code for future tests */
 #if 0
-                       UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur));
-                       break;
+               UI_panels_scale(ar, BLI_rctf_size_x(&v2d->cur));
+               break;
 #endif
-               }
-               else {
-                       break;
-               }
        }
 
        region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);