From 6a0264896b38794ec8242040cf5104c4e06d844e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 26 Apr 2018 12:01:44 +0200 Subject: UI: toolbar single column size snapping Once a region is set to it's snapped size, zooming keeps the size. --- source/blender/blenkernel/BKE_screen.h | 2 ++ source/blender/editors/include/ED_screen.h | 3 ++ source/blender/editors/interface/view2d_ops.c | 27 ++++++++++++++++-- source/blender/editors/screen/area.c | 33 ++++++++++++++++++++++ source/blender/editors/screen/screen_ops.c | 21 ++++++++++++-- source/blender/editors/space_view3d/space_view3d.c | 13 +++++++++ 6 files changed, 93 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 2736833a5ca..69b5e7ea6fe 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -140,6 +140,8 @@ typedef struct ARegionType { void (*exit)(struct wmWindowManager *, struct ARegion *); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); + /* snap the size of the region (can be NULL for no snapping). */ + int (*snap_size)(const struct ARegion *ar, int size, int axis); /* contextual changes should be handled here */ void (*listener)(struct bScreen *, struct ScrArea *, struct ARegion *, struct wmNotifier *, const struct Scene *scene); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 6d9b4af7c01..b4857051c89 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -91,6 +91,9 @@ void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); +int ED_region_snap_size_test(const struct ARegion *ar); +bool ED_region_snap_size_apply(struct ARegion *ar, int snap_flag); + /* message_bus callbacks */ void ED_region_do_msg_notify_tag_redraw( struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index dc68c8b58de..6150b7e254e 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -641,6 +641,7 @@ static void view_zoomstep_apply_ex( View2D *v2d = &ar->v2d; const rctf cur_old = v2d->cur; float dx, dy; + const int snap_test = ED_region_snap_size_test(ar); /* calculate amount to move view by, ensuring symmetry so the * old zoom level is restored after zooming back the same amount @@ -725,6 +726,12 @@ static void view_zoomstep_apply_ex( /* validate that view is in valid configuration after this operation */ UI_view2d_curRect_validate(v2d); + if (ED_region_snap_size_apply(ar, snap_test)) { + ScrArea *sa = CTX_wm_area(C); + ED_area_tag_redraw(sa); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + } + /* request updates to be done... */ ED_region_tag_redraw(vzd->ar); UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); @@ -898,7 +905,8 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) v2dViewZoomData *vzd = op->customdata; View2D *v2d = vzd->v2d; float dx, dy; - + const int snap_test = ED_region_snap_size_test(vzd->ar); + /* get amount to move view by */ dx = RNA_float_get(op->ptr, "deltax"); dy = RNA_float_get(op->ptr, "deltay"); @@ -961,7 +969,13 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) /* validate that view is in valid configuration after this operation */ UI_view2d_curRect_validate(v2d); - + + if (ED_region_snap_size_apply(vzd->ar, snap_test)) { + ScrArea *sa = CTX_wm_area(C); + ED_area_tag_redraw(sa); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + } + /* request updates to be done... */ ED_region_tag_redraw(vzd->ar); UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); @@ -2000,6 +2014,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; int winx, winy; + const int snap_test = ED_region_snap_size_test(ar); /* zoom 1.0 */ winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); @@ -2033,7 +2048,13 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) /* validate that view is in valid configuration after this operation */ UI_view2d_curRect_validate(v2d); - + + if (ED_region_snap_size_apply(ar, snap_test)) { + ScrArea *sa = CTX_wm_area(C); + ED_area_tag_redraw(sa); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + } + /* request updates to be done... */ ED_region_tag_redraw(ar); UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 678c3281335..0f9378d0a41 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2741,3 +2741,36 @@ void ED_region_message_subscribe( ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus); } } + +int ED_region_snap_size_test(const ARegion *ar) +{ + /* Use a larger value because toggling scrollbars can jump in size. */ + const int snap_match_threshold = 16; + if (ar->type->snap_size != NULL) { + return ((((ar->sizex - ar->type->snap_size(ar, ar->sizex, 0)) <= snap_match_threshold) << 0) | + (((ar->sizey - ar->type->snap_size(ar, ar->sizey, 1)) <= snap_match_threshold) << 1)); + } + return 0; +} + +bool ED_region_snap_size_apply(ARegion *ar, int snap_flag) +{ + bool changed = false; + if (ar->type->snap_size != NULL) { + if (snap_flag & (1 << 0)) { + short snap_size = ar->type->snap_size(ar, ar->sizex, 0); + if (snap_size != ar->sizex) { + ar->sizex = snap_size; + changed = true; + } + } + if (snap_flag & (1 << 1)) { + short snap_size = ar->type->snap_size(ar, ar->sizey, 1); + if (snap_size != ar->sizey) { + ar->sizey = snap_size; + changed = true; + } + } + } + return changed; +} diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6ed56e91a0f..7dab2c7c3db 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2156,7 +2156,8 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) /* execute the events */ switch (event->type) { case MOUSEMOVE: - + { + const int snap_size_threshold = U.widget_unit * 3; if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) { delta = event->x - rmd->origx; if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta; @@ -2165,8 +2166,15 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) delta /= UI_DPI_FAC; rmd->ar->sizex = rmd->origval + delta; + + if (rmd->ar->type->snap_size) { + short sizex_test = rmd->ar->type->snap_size(rmd->ar, rmd->ar->sizex, 0); + if (ABS(rmd->ar->sizex - sizex_test) < snap_size_threshold) { + rmd->ar->sizex = sizex_test; + } + } CLAMP(rmd->ar->sizex, 0, rmd->maxsize); - + if (rmd->ar->sizex < UI_UNIT_X) { rmd->ar->sizex = rmd->origval; if (!(rmd->ar->flag & RGN_FLAG_HIDDEN)) @@ -2184,6 +2192,13 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) delta /= UI_DPI_FAC; rmd->ar->sizey = rmd->origval + delta; + + if (rmd->ar->type->snap_size) { + short sizey_test = rmd->ar->type->snap_size(rmd->ar, rmd->ar->sizey, 1); + if (ABS(rmd->ar->sizey - sizey_test) < snap_size_threshold) { + rmd->ar->sizey = sizey_test; + } + } CLAMP(rmd->ar->sizey, 0, rmd->maxsize); /* note, 'UI_UNIT_Y/4' means you need to drag the header almost @@ -2203,7 +2218,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); break; - + } case LEFTMOUSE: if (event->val == KM_RELEASE) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index b4d6d554e4f..4fb4193517b 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1277,6 +1277,18 @@ static void view3d_buttons_region_listener( } } +static int view3d_tools_region_snap_size(const ARegion *ar, int size, int axis) +{ + if (axis == 0) { + /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */ + const float snap_units = 3.25f; + const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1); + const int snap_size = (snap_units * U.widget_unit) / aspect; + return snap_size; + } + return size; +} + /* add handlers, stuff you only do once or on area/region changes */ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar) { @@ -1474,6 +1486,7 @@ void ED_spacetype_view3d(void) art->prefsizey = 50; /* XXX */ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = view3d_buttons_region_listener; + art->snap_size = view3d_tools_region_snap_size; art->init = view3d_tools_region_init; art->draw = view3d_tools_region_draw; BLI_addhead(&st->regiontypes, art); -- cgit v1.2.3