UI: Screen Operations Status Bar

Status bar showing screen area operations when hovering on editor edges
and action zones. Screen area operators (move edge, split, join, etc)
showing keymaps and info during operations.

Pull Request: https://projects.blender.org/blender/blender/pulls/125467
This commit is contained in:
Harley Acheson
2024-07-31 22:11:37 +02:00
committed by Harley Acheson
parent fcfcdef360
commit 5642944e33
3 changed files with 121 additions and 13 deletions

View File

@@ -79,6 +79,7 @@
#include "ED_object.hh"
#include "ED_render.hh"
#include "ED_screen.hh"
#include "ED_screen_types.hh"
#include "ED_undo.hh"
#include "IMB_imbuf.hh"
@@ -6301,6 +6302,39 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
UI_block_emboss_set(block, previous_emboss);
}
static bool uiTemplateInputStatusAzone(uiLayout *layout, AZone *az, ARegion *region)
{
if (az->type == AZONE_AREA) {
uiItemL(layout, nullptr, ICON_MOUSE_LMB_DRAG);
if (U.experimental.use_docking) {
uiItemL(layout, IFACE_("Split/Dock"), ICON_NONE);
}
else {
uiItemL(layout, IFACE_("Split/Join"), ICON_NONE);
}
uiItemS_ex(layout, 0.7f);
uiItemL(layout, "", ICON_EVENT_SHIFT);
uiItemL(layout, nullptr, ICON_MOUSE_LMB_DRAG);
uiItemL(layout, IFACE_("Duplicate into Window"), ICON_NONE);
uiItemS_ex(layout, 0.7f);
uiItemL(layout, "", ICON_EVENT_CTRL);
uiItemL(layout, nullptr, ICON_MOUSE_LMB_DRAG);
uiItemL(layout, IFACE_("Swap Areas"), ICON_NONE);
return true;
}
if (az->type == AZONE_REGION) {
uiItemL(layout, nullptr, ICON_MOUSE_LMB_DRAG);
uiItemS_ex(layout, 0.3f);
uiItemL(layout,
(region->visible) ? IFACE_("Resize Region") : IFACE_("Show Hidden Region"),
ICON_NONE);
return true;
}
return false;
}
void uiTemplateInputStatus(uiLayout *layout, bContext *C)
{
wmWindow *win = CTX_wm_window(C);
@@ -6327,11 +6361,38 @@ void uiTemplateInputStatus(uiLayout *layout, bContext *C)
return;
}
bScreen *screen = CTX_wm_screen(C);
ARegion *region = screen->active_region;
uiLayout *row = uiLayoutRow(layout, true);
if (region == nullptr) {
/* Check if over an action zone. */
LISTBASE_FOREACH (ScrArea *, area_iter, &screen->areabase) {
LISTBASE_FOREACH (AZone *, az, &area_iter->actionzones) {
if (BLI_rcti_isect_pt_v(&az->rect, win->eventstate->xy)) {
region = az->region;
if (uiTemplateInputStatusAzone(row, az, region)) {
return;
}
break;
}
}
}
}
if (!region) {
/* On a gap between editors. */
uiItemL(row, nullptr, ICON_MOUSE_LMB_DRAG);
uiItemL(row, IFACE_("Resize"), ICON_NONE);
uiItemS_ex(row, 0.7f);
uiItemL(row, nullptr, ICON_MOUSE_RMB);
uiItemS_ex(row, -0.6f);
uiItemL(row, IFACE_("Options"), ICON_NONE);
return;
}
/* Otherwise should cursor keymap status. */
for (int i = 0; i < 3; i++) {
uiLayout *box = uiLayoutRow(layout, false);
uiLayout *col = uiLayoutColumn(box, false);
uiLayout *row = uiLayoutRow(col, true);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
const char *msg = CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT,
@@ -6339,20 +6400,18 @@ void uiTemplateInputStatus(uiLayout *layout, bContext *C)
const char *msg_drag = CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT,
WM_window_cursor_keymap_status_get(win, i, 1));
if (msg || (msg_drag == nullptr)) {
/* Icon and text separately are closer together with aligned layout. */
if (msg) {
uiItemL(row, "", (ICON_MOUSE_LMB + i));
uiItemS_ex(row, -0.6f);
uiItemL(row, msg ? msg : "", ICON_NONE);
uiItemS_ex(row, 0.7f);
}
if (msg_drag) {
uiItemL(row, "", (ICON_MOUSE_LMB_DRAG + i));
uiItemL(row, msg_drag, ICON_NONE);
uiItemS_ex(row, 0.7f);
}
/* Use trick with empty string to keep icons in same position. */
row = uiLayoutRow(col, false);
uiItemL(row, " ", ICON_NONE);
}
}

View File

@@ -1035,6 +1035,10 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
screen->active_region = nullptr;
}
if (region_prev != screen->active_region || !screen->active_region) {
WM_window_status_area_tag_redraw(win);
}
/* Check for redraw headers. */
if (region_prev != screen->active_region) {

View File

@@ -1357,6 +1357,7 @@ static void area_swap_exit(bContext *C, wmOperator *op)
{
WM_cursor_modal_restore(CTX_wm_window(C));
MEM_SAFE_FREE(op->customdata);
ED_workspace_status_text(C, nullptr);
}
static void area_swap_cancel(bContext *C, wmOperator *op)
@@ -1382,11 +1383,15 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
sActionzoneData *sad = static_cast<sActionzoneData *>(op->customdata);
switch (event->type) {
case MOUSEMOVE:
case MOUSEMOVE: {
/* Second area to swap with. */
sad->sa2 = ED_area_find_under_cursor(C, SPACE_TYPE_ANY, event->xy);
WM_cursor_set(CTX_wm_window(C), (sad->sa2) ? WM_CURSOR_SWAP_AREA : WM_CURSOR_STOP);
WorkspaceStatus status(C);
status.item(IFACE_("Select Area"), ICON_MOUSE_LMB);
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
break;
}
case LEFTMOUSE: /* release LMB */
if (event->val == KM_RELEASE) {
if (!sad->sa2 || sad->sa1 == sad->sa2) {
@@ -1886,7 +1891,7 @@ static int area_snap_calc_location(const bScreen *screen,
}
/* moves selected screen edge amount of delta, used by split & move */
static void area_move_apply_do(const bContext *C,
static void area_move_apply_do(bContext *C,
int delta,
const int origval,
const eScreenAxis dir_axis,
@@ -1894,6 +1899,11 @@ static void area_move_apply_do(const bContext *C,
const int smaller,
const enum AreaMoveSnapType snap_type)
{
WorkspaceStatus status(C);
status.item(IFACE_("Confirm"), ICON_MOUSE_LMB);
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
status.item_bool(IFACE_("Snap"), snap_type == SNAP_FRACTION_AND_ADJACENT, ICON_EVENT_CTRL);
wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
short final_loc = -1;
@@ -1978,7 +1988,7 @@ static void area_move_exit(bContext *C, wmOperator *op)
/* this makes sure aligned edges will result in aligned grabbing */
BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
BKE_screen_remove_double_scredges(CTX_wm_screen(C));
ED_workspace_status_text(C, nullptr);
G.moving &= ~G_TRANSFORM_WM;
}
@@ -2004,6 +2014,11 @@ static int area_move_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
WorkspaceStatus status(C);
status.item(IFACE_("Confirm"), ICON_MOUSE_LMB);
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
status.item(IFACE_("Snap"), ICON_EVENT_CTRL);
/* add temp handler */
G.moving |= G_TRANSFORM_WM;
WM_event_add_modal_handler(C, op);
@@ -2058,6 +2073,11 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
}
WorkspaceStatus status(C);
status.item(IFACE_("Confirm"), ICON_MOUSE_LMB);
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
status.item_bool(
IFACE_("Snap"), md->snap_type == SNAP_FRACTION_AND_ADJACENT, ICON_EVENT_CTRL);
break;
}
}
@@ -2314,6 +2334,7 @@ static void area_split_exit(bContext *C, wmOperator *op)
WM_cursor_modal_restore(CTX_wm_window(C));
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, nullptr);
ED_workspace_status_text(C, nullptr);
/* this makes sure aligned edges will result in aligned grabbing */
BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
@@ -2579,8 +2600,18 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
sd->bigger,
sd->smaller);
sd->delta = snap_loc - sd->origval;
area_move_apply_do(C,
sd->delta,
sd->origval,
dir_axis,
sd->bigger,
sd->smaller,
SNAP_FRACTION_AND_ADJACENT);
}
else {
area_move_apply_do(
C, sd->delta, sd->origval, dir_axis, sd->bigger, sd->smaller, SNAP_NONE);
}
area_move_apply_do(C, sd->delta, sd->origval, dir_axis, sd->bigger, sd->smaller, SNAP_NONE);
}
else {
if (sd->sarea) {
@@ -3658,6 +3689,8 @@ static void area_join_exit(bContext *C, wmOperator *op)
BKE_screen_remove_unused_scredges(CTX_wm_screen(C));
BKE_screen_remove_unused_scrverts(CTX_wm_screen(C));
ED_workspace_status_text(C, nullptr);
G.moving &= ~G_TRANSFORM_WM;
}
@@ -3987,6 +4020,18 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
area_join_dock_cb_window(jd, op);
WM_cursor_set(jd->win1, area_join_cursor(jd, event));
WM_event_add_notifier(C, NC_WINDOW, nullptr);
WorkspaceStatus status(C);
if (jd->sa1 && jd->sa1 == jd->sa2) {
status.item(IFACE_("Select Split"), ICON_MOUSE_LMB);
}
else if (jd->dock_target == AreaDockTarget::None) {
status.item(IFACE_("Select Area"), ICON_MOUSE_LMB);
}
else {
status.item(IFACE_("Select Location"), ICON_MOUSE_LMB);
}
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
break;
}
case LEFTMOUSE: