diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2018-04-20 18:14:03 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2018-04-20 18:14:52 +0300 |
commit | 5f6c45498c92b91a710a1317f6d41f73fbe83477 (patch) | |
tree | 93b136fb49c656c2c2a5463c91e8a6a38d518354 /source/blender/editors/screen/screen_ops.c | |
parent | 4bfb6d21df96688187f6f1a5d95dd62bcbf85116 (diff) |
UI: New Global Top-Bar (WIP)
== Main Features/Changes for Users
* Add horizontal bar at top of all non-temp windows, consisting out of two horizontal sub-bars.
* Upper sub-bar contains global menus (File, Render, etc.), tabs for workspaces and scene selector.
* Lower sub-bar contains object mode selector, screen-layout and render-layer selector. Later operator and/or tool settings will be placed here.
* Individual sections of the topbar are individually scrollable.
* Workspace tabs can be double- or ctrl-clicked for renaming and contain 'x' icon for deleting.
* Top-bar should scale nicely with DPI.
* The lower half of the top-bar can be hided by dragging the lower top-bar edge up. Better hiding options are planned (e.g. hide in fullscreen modes).
* Info editors at the top of the window and using the full window width with be replaced by the top-bar.
* In fullscreen modes, no more info editor is added on top, the top-bar replaces it.
== Technical Features/Changes
* Adds initial support for global areas
A global area is part of the window, not part of the regular screen-layout.
I've added a macro iterator to iterate over both, global and screen-layout level areas. When iterating over areas, from now on developers should always consider if they have to include global areas.
* Adds a TOPBAR editor type
The editor type is hidden in the UI editor type menu.
* Adds a variation of the ID template to display IDs as tab buttons (template_ID_tabs in BPY)
* Does various changes to RNA button creation code to improve their appearance in the horizontal top-bar.
* Adds support for dynamically sized regions. That is, regions that scale automatically to the layout bounds.
The code for this is currently a big hack (it's based on drawing the UI multiple times). This should definitely be improved.
* Adds a template for displaying operator properties optimized for the top-bar. This will probably change a lot still and is in fact disabled in code.
Since the final top-bar design depends a lot on other 2.8 designs (mainly tool-system and workspaces), we decided to not show the operator or tool settings in the top-bar for now. That means most of the lower sub-bar is empty for the time being.
NOTE: Top-bar or global area data is not written to files or SDNA. They are simply added to the window when opening Blender or reading a file. This allows us doing changes to the top-bar without having to care for compatibility.
== ToDo's
It's a bit hard to predict all the ToDo's here are the known main ones:
* Add options for the new active-tool system and for operator redo to the topbar.
* Automatically hide the top-bar in fullscreen modes.
* General visual polish.
* Top-bar drag & drop support (WIP in temp-tab_drag_drop).
* Improve dynamic regions (should also fix some layout glitches).
* Make internal terminology consistent.
* Enable topbar file writing once design is more advanced.
* Address TODO's and XXX's in code :)
Thanks @brecht for the review! And @sergey for the complaining ;)
Differential Revision: D2758
Diffstat (limited to 'source/blender/editors/screen/screen_ops.c')
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 205 |
1 files changed, 151 insertions, 54 deletions
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 25d5fbbdc4c..8b889c61deb 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -791,8 +791,8 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sActionzoneData *sad = op->customdata; - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); + const int screen_size_x = WM_window_screen_pixels_x(win); + const int screen_size_y = WM_window_screen_pixels_y(win); switch (event->type) { case MOUSEMOVE: @@ -816,7 +816,8 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) /* once we drag outside the actionzone, register a gesture * check we're not on an edge so join finds the other area */ is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && - (screen_find_active_scredge(sc, winsize_x, winsize_y, event->x, event->y) == NULL)); + (screen_area_map_find_active_scredge( + AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y) == NULL)); } else { const int delta_min = 1; @@ -1049,6 +1050,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old)); newsc = BKE_workspace_layout_screen_get(layout_new); WM_window_set_active_layout(newwin, workspace, layout_new); + ED_screen_global_areas_create(newwin); /* copy area to new screen */ ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true); @@ -1116,25 +1118,73 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot) */ typedef struct sAreaMoveData { - int bigger, smaller, origval; + int bigger, smaller, origval, step; char dir; - bool do_snap; + enum AreaMoveSnapType { + /* Snapping disabled */ + SNAP_NONE = 0, + /* Snap to mid-point and adjacent edges. */ + SNAP_MIDPOINT_AND_ADJACENT, + /* Snap to either bigger or smaller, nothing in-between (used for + * global areas). This has priority over other snap types, if it is + * used, toggling SNAP_MIDPOINT_AND_ADJACENT doesn't work. */ + SNAP_BIGGER_SMALLER_ONLY, + } snap_type; } sAreaMoveData; /* helper call to move area-edge, sets limits * need window size in order to get correct limits */ -static void area_move_set_limits(bScreen *sc, int dir, - const int winsize_x, const int winsize_y, - int *bigger, int *smaller) +static void area_move_set_limits( + wmWindow *win, bScreen *sc, int dir, + const int winsize_x, const int winsize_y, + int *bigger, int *smaller, + bool *use_bigger_smaller_snap) { - ScrArea *sa; int areaminy = ED_area_headersize(); int areamin; - + /* we check all areas and test for free space with MINSIZE */ *bigger = *smaller = 100000; - - for (sa = sc->areabase.first; sa; sa = sa->next) { + + if (use_bigger_smaller_snap != NULL) { + *use_bigger_smaller_snap = false; + for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { + const int size_min = round_fl_to_int(area->global->size_min * UI_DPI_FAC); + const int size_max = round_fl_to_int(area->global->size_max * UI_DPI_FAC); + + /* logic here is only tested for lower edge :) */ + /* left edge */ + if ((area->v1->editflag && area->v2->editflag)) { + *smaller = area->v4->vec.x - size_max; + *bigger = area->v4->vec.x - size_min; + *use_bigger_smaller_snap = true; + return; + } + /* top edge */ + else if ((area->v2->editflag && area->v3->editflag)) { + *smaller = area->v1->vec.y + size_min; + *bigger = area->v1->vec.y + size_max; + *use_bigger_smaller_snap = true; + return; + } + /* right edge */ + else if ((area->v3->editflag && area->v4->editflag)) { + *smaller = area->v1->vec.x + size_min; + *bigger = area->v1->vec.x + size_max; + *use_bigger_smaller_snap = true; + return; + } + /* lower edge */ + else if ((area->v4->editflag && area->v1->editflag)) { + *smaller = area->v2->vec.y - size_max; + *bigger = area->v2->vec.y - size_min; + *use_bigger_smaller_snap = true; + return; + } + } + } + + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { if (dir == 'h') { int y1; areamin = areaminy; @@ -1180,9 +1230,8 @@ static int area_move_init(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); ScrEdge *actedge; sAreaMoveData *md; - ScrVert *v1; - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); + const int screen_size_x = WM_window_screen_pixels_x(win); + const int screen_size_y = WM_window_screen_pixels_y(win); int x, y; /* required properties */ @@ -1190,7 +1239,7 @@ static int area_move_init(bContext *C, wmOperator *op) y = RNA_int_get(op->ptr, "y"); /* setup */ - actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, x, y); + actedge = screen_find_active_scredge(win, sc, x, y); if (actedge == NULL) return 0; md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData"); @@ -1200,23 +1249,33 @@ static int area_move_init(bContext *C, wmOperator *op) if (md->dir == 'h') md->origval = actedge->v1->vec.y; else md->origval = actedge->v1->vec.x; - select_connected_scredge(sc, actedge); - /* now all vertices with 'flag==1' are the ones that can be moved. Move this to editflag */ - for (v1 = sc->vertbase.first; v1; v1 = v1->next) + select_connected_scredge(win, actedge); + /* now all vertices with 'flag == 1' are the ones that can be moved. Move this to editflag */ + ED_screen_verts_iter(win, sc, v1) { v1->editflag = v1->flag; - - area_move_set_limits(sc, md->dir, winsize_x, winsize_y, &md->bigger, &md->smaller); - + } + + bool use_bigger_smaller_snap = false; + area_move_set_limits(win, sc, md->dir, screen_size_x, screen_size_y, + &md->bigger, &md->smaller, + &use_bigger_smaller_snap); + + md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_NONE; + return 1; } static int area_snap_calc_location( - const bScreen *sc, const int delta, - const int origval, const int dir, + const bScreen *sc, const enum AreaMoveSnapType snap_type, + const int delta, const int origval, const int dir, const int bigger, const int smaller) { - int final_loc = -1; + BLI_assert(snap_type != SNAP_NONE); + if (snap_type == SNAP_BIGGER_SMALLER_ONLY) { + return ((origval + delta) >= bigger) ? bigger : smaller; + } + int final_loc = -1; const int m_loc = origval + delta; const int axis = (dir == 'v') ? 0 : 1; int snap_dist; @@ -1260,29 +1319,29 @@ static void area_move_apply_do( const bContext *C, int delta, const int origval, const int dir, const int bigger, const int smaller, - const bool do_snap) + const enum AreaMoveSnapType snap_type) { + wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); - ScrVert *v1; bool doredraw = false; CLAMP(delta, -smaller, bigger); short final_loc = -1; - if (do_snap) { - final_loc = area_snap_calc_location(sc, delta, origval, dir, bigger, smaller); - } - else { + if (snap_type == SNAP_NONE) { final_loc = origval + delta; if (delta != bigger && delta != -smaller) { final_loc -= (final_loc % AREAGRID); } } + else { + final_loc = area_snap_calc_location(sc, snap_type, delta, origval, dir, bigger, smaller); + } BLI_assert(final_loc != -1); short axis = (dir == 'v') ? 0 : 1; - for (v1 = sc->vertbase.first; v1; v1 = v1->next) { + ED_screen_verts_iter(win, sc, v1) { if (v1->editflag) { short oldval = (&v1->vec.x)[axis]; (&v1->vec.x)[axis] = final_loc; @@ -1297,11 +1356,23 @@ static void area_move_apply_do( /* only redraw if we actually moved a screen vert, for AREAGRID */ if (doredraw) { - for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + bool redraw_all = false; + ED_screen_areas_iter(win, sc, sa) { if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag) { + if (ED_area_is_global(sa)) { + sa->global->cur_fixed_height = round_fl_to_int((sa->v2->vec.y - sa->v1->vec.y) / UI_DPI_FAC); + sc->do_refresh = true; + redraw_all = true; + } ED_area_tag_redraw(sa); } } + if (redraw_all) { + ED_screen_areas_iter(win, sc, sa) { + ED_area_tag_redraw(sa); + } + } + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */ /* Update preview thumbnail */ BKE_icon_changed(sc->id.icon_id); @@ -1313,7 +1384,7 @@ static void area_move_apply(bContext *C, wmOperator *op) sAreaMoveData *md = op->customdata; int delta = RNA_int_get(op->ptr, "delta"); - area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->do_snap); + area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->snap_type); } static void area_move_exit(bContext *C, wmOperator *op) @@ -1392,10 +1463,14 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; case KM_MODAL_SNAP_ON: - md->do_snap = true; + if (md->snap_type == SNAP_NONE) { + md->snap_type = SNAP_MIDPOINT_AND_ADJACENT; + } break; case KM_MODAL_SNAP_OFF: - md->do_snap = false; + if (md->snap_type == SNAP_MIDPOINT_AND_ADJACENT) { + md->snap_type = SNAP_NONE; + } break; } break; @@ -1644,8 +1719,8 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) wmWindow *win = CTX_wm_window(C); bScreen *sc = CTX_wm_screen(C); sAreaSplitData *sd; - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); + const int screen_size_x = WM_window_screen_pixels_x(win); + const int screen_size_y = WM_window_screen_pixels_y(win); int dir; /* no full window splitting allowed */ @@ -1698,7 +1773,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) else y = event->x; - actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, x, y); + actedge = screen_area_map_find_active_scredge(AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, x, y); if (actedge == NULL) return OPERATOR_CANCELLED; @@ -1718,7 +1793,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* do the split */ if (area_split_apply(C, op)) { - area_move_set_limits(sc, dir, winsize_x, winsize_y, &sd->bigger, &sd->smaller); + area_move_set_limits(win, sc, dir, screen_size_x, screen_size_y, &sd->bigger, &sd->smaller, NULL); /* add temp handler for edge move or cancel */ WM_event_add_modal_handler(C, op); @@ -1836,10 +1911,11 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) if (sd->previewmode == 0) { if (sd->do_snap) { const int snap_loc = area_snap_calc_location( - CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->bigger, sd->smaller); + CTX_wm_screen(C), SNAP_MIDPOINT_AND_ADJACENT, sd->delta, sd->origval, dir, + sd->bigger, sd->smaller); sd->delta = snap_loc - sd->origval; } - area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, false); + area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, SNAP_NONE); } else { if (sd->sarea) { @@ -1863,7 +1939,8 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1; const int snap_loc = area_snap_calc_location( - CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->origmin + sd->origsize, -sd->origmin); + CTX_wm_screen(C), SNAP_MIDPOINT_AND_ADJACENT, sd->delta, sd->origval, dir, + sd->origmin + sd->origsize, -sd->origmin); sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0; sd->delta = snap_loc - sd->origval; @@ -2579,6 +2656,14 @@ static int screen_maximize_area_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int screen_maximize_area_poll(bContext *C) +{ + const bScreen *screen = CTX_wm_screen(C); + const ScrArea *area = CTX_wm_area(C); + return ED_operator_areaactive(C) && + ((screen->state != SCREENNORMAL) || (area->spacetype != SPACE_TOPBAR)); +} + static void SCREEN_OT_screen_full_area(wmOperatorType *ot) { PropertyRNA *prop; @@ -2588,7 +2673,7 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot) ot->idname = "SCREEN_OT_screen_full_area"; ot->exec = screen_maximize_area_exec; - ot->poll = ED_operator_areaactive; + ot->poll = screen_maximize_area_poll; ot->flag = 0; prop = RNA_def_boolean(ot->srna, "use_hide_panels", false, "Hide Panels", "Hide all the panels"); @@ -2898,10 +2983,11 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent uiLayout *layout; PointerRNA ptr; ScrEdge *actedge; - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); + const int screen_size_x = WM_window_screen_pixels_x(win); + const int screen_size_y = WM_window_screen_pixels_y(win); - actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, event->x, event->y); + actedge = screen_area_map_find_active_scredge( + AREAMAP_FROM_SCREEN(sc), screen_size_x, screen_size_y, event->x, event->y); if (actedge == NULL) return OPERATOR_CANCELLED; @@ -3305,6 +3391,18 @@ static int region_flip_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static int region_flip_poll(bContext *C) +{ + ScrArea *area = CTX_wm_area(C); + + /* don't flip anything around in topbar */ + if (area->spacetype == SPACE_TOPBAR) { + CTX_wm_operator_poll_msg_set(C, "Flipping regions in the Top-bar is not allowed"); + return 0; + } + + return ED_operator_areaactive(C); +} static void SCREEN_OT_region_flip(wmOperatorType *ot) { @@ -3315,7 +3413,7 @@ static void SCREEN_OT_region_flip(wmOperatorType *ot) /* api callbacks */ ot->exec = region_flip_exec; - ot->poll = ED_operator_areaactive; + ot->poll = region_flip_poll; ot->flag = 0; } @@ -3408,12 +3506,11 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN uiItemS(layout); - /* file browser should be fullscreen all the time, but other regions can be maximized/restored... */ - if (sa->spacetype != SPACE_FILE) { - if (sa->full) - uiItemO(layout, IFACE_("Tile Area"), ICON_NONE, "SCREEN_OT_screen_full_area"); - else - uiItemO(layout, IFACE_("Maximize Area"), ICON_NONE, "SCREEN_OT_screen_full_area"); + /* file browser should be fullscreen all the time, topbar should + * never be. But other regions can be maximized/restored... */ + if (!ELEM(sa->spacetype, SPACE_FILE, SPACE_TOPBAR)) { + const char *but_str = sa->full ? IFACE_("Tile Area") : IFACE_("Maximize Area"); + uiItemO(layout, but_str, ICON_NONE, "SCREEN_OT_screen_full_area"); } } |