From 9b3bd5582be99e26b6c3651f66db516982bc8461 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 2 Apr 2014 13:09:43 +0200 Subject: Replace resize code of image scopes by use of new GRIP button. This deduplicates/simplifies some code. Also cleanup up a bit scopes UI code! Use new GRIP button for uiList grab-resize. This allows us to greatly simplifies the code, and get rid of a few hacks in uiList event handling! Note autosize mode of uiList is now trigered by any value of list_grip below a given threshold, rather than the fixed zero value... Reviewers: brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D343 --- source/blender/editors/interface/interface_draw.c | 43 +- .../blender/editors/interface/interface_handlers.c | 443 +++++---------------- .../blender/editors/interface/interface_layout.c | 9 - .../editors/interface/interface_templates.c | 183 +++++---- 4 files changed, 218 insertions(+), 460 deletions(-) (limited to 'source/blender/editors/interface') diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 13551d9df42..2d13159261b 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -444,24 +444,11 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w static void draw_scope_end(const rctf *rect, GLint *scissor) { - float scaler_x1, scaler_x2; - /* restore scissortest */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* scale widget */ - scaler_x1 = rect->xmin + BLI_rctf_size_x(rect) / 2 - SCOPE_RESIZE_PAD; - scaler_x2 = rect->xmin + BLI_rctf_size_x(rect) / 2 + SCOPE_RESIZE_PAD; - - glColor4f(0.f, 0.f, 0.f, 0.25f); - fdrawline(scaler_x1, rect->ymin - 4, scaler_x2, rect->ymin - 4); - fdrawline(scaler_x1, rect->ymin - 7, scaler_x2, rect->ymin - 7); - glColor4f(1.f, 1.f, 1.f, 0.25f); - fdrawline(scaler_x1, rect->ymin - 5, scaler_x2, rect->ymin - 5); - fdrawline(scaler_x1, rect->ymin - 8, scaler_x2, rect->ymin - 8); - + /* outline */ glColor4f(0.f, 0.f, 0.f, 0.5f); uiSetRoundBox(UI_CNR_ALL); @@ -539,7 +526,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) rect.xmin = (float)recti->xmin + 1; rect.xmax = (float)recti->xmax - 1; - rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; + rect.ymin = (float)recti->ymin + 1; rect.ymax = (float)recti->ymax - 1; w = BLI_rctf_size_x(&rect); @@ -588,7 +575,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line); } - /* outline, scale gripper */ + /* outline */ draw_scope_end(&rect, scissor); } @@ -610,7 +597,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rect.xmin = (float)recti->xmin + 1; rect.xmax = (float)recti->xmax - 1; - rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; + rect.ymin = (float)recti->ymin + 1; rect.ymax = (float)recti->ymax - 1; if (scopes->wavefrm_yfac < 0.5f) @@ -629,14 +616,13 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), colorsycc_alpha[c][i] = colorsycc[c][i] * alpha; } } - + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.f, 0.f, 0.f, 0.3f); uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); - /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); @@ -694,7 +680,7 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), glScalef(w, h, 0.f); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - + glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); @@ -755,10 +741,9 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); } } - } - /* outline, scale gripper */ + /* outline */ draw_scope_end(&rect, scissor); } @@ -840,7 +825,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco rect.xmin = (float)recti->xmin + 1; rect.xmax = (float)recti->xmax - 1; - rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; + rect.ymin = (float)recti->ymin + 1; rect.ymax = (float)recti->ymax - 1; w = BLI_rctf_size_x(&rect); @@ -850,7 +835,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco diam = (w < h) ? w : h; alpha = scopes->vecscope_alpha * scopes->vecscope_alpha * scopes->vecscope_alpha; - + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -906,9 +891,9 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco glPopMatrix(); } - /* outline, scale gripper */ + /* outline */ draw_scope_end(&rect, scissor); - + glDisable(GL_BLEND); } @@ -1505,7 +1490,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc rect.xmin = (float)recti->xmin + 1; rect.xmax = (float)recti->xmax - 1; - rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; + rect.ymin = (float)recti->ymin + 1; rect.ymax = (float)recti->ymax - 1; width = BLI_rctf_size_x(&rect) + 1; @@ -1616,7 +1601,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); } - /* outline, scale gripper */ + /* outline */ draw_scope_end(&rect, scissor); glDisable(GL_BLEND); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c911e0d9ac9..6f06544c3e2 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3942,6 +3942,12 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto int retval = WM_UI_HANDLER_CONTINUE; const bool horizontal = (BLI_rctf_size_x(&but->rect) < BLI_rctf_size_y(&but->rect)); + /* Note: Having to store org point in window space and recompute it to block "space" each time + * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which + * returns different results when the block is inside a panel or not... + * See T37739. + */ + mx = event->x; my = event->y; ui_window_to_block(data->region, block, &mx, &my); @@ -4001,94 +4007,6 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, return ui_do_but_EXIT(C, but, data, event); } - -static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) -{ - uiList *ui_list = but->custom_data; - int *size = (int *)but->poin; - int mx, my, dragx, dragy; - int retval = WM_UI_HANDLER_CONTINUE; - - /* Note: Having to store org point in window space and recompute it to block "space" each time - * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which - * returns different results when the block is inside a panel or not... - * See T37739. - */ - dragx = data->dragstartx; - dragy = data->dragstarty; - ui_window_to_block(data->region, block, &dragx, &dragy); - - mx = event->x; - my = event->y; - ui_window_to_block(data->region, block, &mx, &my); - - if (data->state == BUTTON_STATE_NUM_EDITING) { - if (event->type == ESCKEY) { - if (event->val == KM_PRESS) { - data->cancel = true; - data->escapecancel = true; - *size = (int)data->origvalue; - button_activate_state(C, but, BUTTON_STATE_EXIT); - ui_list->flag &= ~UILST_RESIZING; - ED_region_tag_redraw(data->region); - } - } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { - button_activate_state(C, but, BUTTON_STATE_EXIT); - ui_list->flag &= ~UILST_RESIZING; - ED_region_tag_redraw(data->region); - } - else if (event->type == MOUSEMOVE) { - /* If we switched from dragged to auto size, suspend shrinking dragging and set dragstarty to a temp - * refpoint. - */ - if (data->draglastvalue > 0 && *size == 0) { - data->draglastvalue = *size; - data->dragstartx = data->dragstarty; /* draglasty already used... */ - data->dragstarty = event->y; - } - else { - int newsize = *size; - int diff = dragy - my; - - diff = iroundf((float)diff / (float)UI_UNIT_Y); - - /* If we are not in autosize mode, default behavior... */ - if (*size > 0) { - /* list template will clamp, but we do not want to reach 0 aka autosize mode! */ - newsize = data->dragstartvalue + diff; - } - /* If we are leaving autosize mode (growing dragging), restore to minimal size. */ - else if (diff > 0) { - /* We can't use ui_numedit_apply()... */ - newsize = ui_list->dyn_data->visual_height_min; - - /* Restore real dragstarty value! */ - data->dragstarty = data->dragstartx; - } - - /* Used to detect switch to/from autosize mode. */ - data->draglastvalue = newsize; - - if (newsize != *size) { - *size = newsize; - - /* We can't use ui_numedit_apply()... */ - data->dragchange = true; - data->applied = data->applied_interactive = true; - - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; - ED_region_tag_redraw(data->region); - } - } - } - - retval = WM_UI_HANDLER_BREAK; - } - - return retval; -} - static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { @@ -5279,40 +5197,22 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt return WM_UI_HANDLER_CONTINUE; } -static bool in_scope_resize_zone(uiBut *but, int UNUSED(x), int y) -{ - /* bottom corner return (x > but->rect.xmax - SCOPE_RESIZE_PAD) && (y < but->rect.ymin + SCOPE_RESIZE_PAD); */ - return (y < but->rect.ymin + SCOPE_RESIZE_PAD); -} - static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx, int my) { Histogram *hist = (Histogram *)but->poin; - /* rcti rect; */ bool changed = true; - float /* dx, */ dy; /* UNUSED */ - - /* BLI_rcti_rctf_copy(&rect, &but->rect); */ - - /* dx = mx - data->draglastx; */ /* UNUSED */ - dy = my - data->draglasty; + float dy = my - data->draglasty; + + /* scale histogram values (dy / 10 for better control) */ + const float yfac = min_ff(powf(hist->ymax, 2.0f), 1.0f) * 0.5f; + hist->ymax += (dy * 0.1f) * yfac; + + /* 0.1 allows us to see HDR colors up to 10 */ + CLAMP(hist->ymax, 0.1f, 100.f); - if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { - /* resize histogram widget itself */ - hist->height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC; - } - else { - /* scale histogram values (dy / 10 for better control) */ - const float yfac = min_ff(powf(hist->ymax, 2.0f), 1.0f) * 0.5f; - hist->ymax += (dy * 0.1f) * yfac; - - /* 0.1 allows us to see HDR colors up to 10 */ - CLAMP(hist->ymax, 0.1f, 100.f); - } - data->draglastx = mx; data->draglasty = my; - + return changed; } @@ -5373,27 +5273,15 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, int my) { Scopes *scopes = (Scopes *)but->poin; - /* rcti rect; */ bool changed = true; - float /* dx, */ dy /* , yfac =1.0f */; /* UNUSED */ + float dy; - /* BLI_rcti_rctf_copy(&rect, &but->rect); */ - - /* dx = mx - data->draglastx; */ /* UNUSED */ dy = my - data->draglasty; + /* scale waveform values */ + scopes->wavefrm_yfac += dy / 200.0f; - if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { - /* resize waveform widget itself */ - scopes->wavefrm_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC; - } - else { - /* scale waveform values */ - /* yfac = scopes->wavefrm_yfac; */ /* UNUSED */ - scopes->wavefrm_yfac += dy / 200.0f; - - CLAMP(scopes->wavefrm_yfac, 0.5f, 2.f); - } + CLAMP(scopes->wavefrm_yfac, 0.5f, 2.0f); data->draglastx = mx; data->draglasty = my; @@ -5455,75 +5343,6 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB return WM_UI_HANDLER_CONTINUE; } -static bool ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int mx, int my) -{ - Scopes *scopes = (Scopes *)but->poin; - /* rcti rect; */ - bool changed = true; - /* float dx, dy; */ - - /* BLI_rcti_rctf_copy(&rect, &but->rect); */ - - /* dx = mx - data->draglastx; */ - /* dy = my - data->draglasty; */ - - if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { - /* resize vectorscope widget itself */ - scopes->vecscope_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC; - } - - data->draglastx = mx; - data->draglasty = my; - - return changed; -} - -static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) -{ - int mx, my; - - mx = event->x; - my = event->y; - ui_window_to_block(data->region, block, &mx, &my); - - if (data->state == BUTTON_STATE_HIGHLIGHT) { - if (event->type == LEFTMOUSE && event->val == KM_PRESS) { - data->dragstartx = mx; - data->dragstarty = my; - data->draglastx = mx; - data->draglasty = my; - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - /* also do drag the first time */ - if (ui_numedit_but_VECTORSCOPE(but, data, mx, my)) - ui_numedit_apply(C, block, but, data); - - return WM_UI_HANDLER_BREAK; - } - } - else if (data->state == BUTTON_STATE_NUM_EDITING) { - if (event->type == ESCKEY) { - if (event->val == KM_PRESS) { - data->cancel = true; - data->escapecancel = true; - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - } - else if (event->type == MOUSEMOVE) { - if (mx != data->draglastx || my != data->draglasty) { - if (ui_numedit_but_VECTORSCOPE(but, data, mx, my)) - ui_numedit_apply(C, block, but, data); - } - } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - return WM_UI_HANDLER_BREAK; - } - - return WM_UI_HANDLER_CONTINUE; -} - static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { VECCOPY2D(but->linkto, event->mval); @@ -5567,25 +5386,19 @@ static bool ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonD dy /= 5.0f; } - if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { - /* resize preview widget itself */ - scopes->track_preview_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC; - } - else { - if (!scopes->track_locked) { - if (scopes->marker->framenr != scopes->framenr) - scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr); + if (!scopes->track_locked) { + if (scopes->marker->framenr != scopes->framenr) + scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr); - scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect); - scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect); + scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); + scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect); + scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect); - WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); - } - - scopes->ok = 0; + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); } + scopes->ok = 0; + data->draglastx = mx; data->draglasty = my; @@ -6248,7 +6061,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * retval = ui_do_but_SLI(C, block, but, data, event); break; case LISTBOX: - retval = ui_do_but_LISTBOX(C, block, but, data, event); + /* Nothing to do! */ break; case LISTROW: retval = ui_do_but_LISTROW(C, but, data, event); @@ -6268,7 +6081,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * retval = ui_do_but_WAVEFORM(C, block, but, data, event); break; case VECTORSCOPE: - retval = ui_do_but_VECTORSCOPE(C, block, but, data, event); + /* Nothing to do! */ break; case TEX: case SEARCH_MENU: @@ -7437,13 +7250,12 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar) { - uiBut *but, *dragbut; + uiBut *but; uiList *ui_list; uiListDyn *dyn_data; int retval = WM_UI_HANDLER_CONTINUE; int type = event->type, val = event->val; int mx, my; - bool is_over_dragbut = false; but = ui_list_find_mouse_over(ar, event->x, event->y); if (!but) { @@ -7460,145 +7272,108 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar) my = event->y; ui_window_to_block(ar, but->block, &mx, &my); - /* Find our "dragging" button. */ - for (dragbut = but->block->buttons.first; dragbut; dragbut = dragbut->next) { - if (dragbut->poin == (void *)ui_list) { - break; - } - } - if (dragbut && dragbut == ui_but_find_mouse_over(ar, event)) { - is_over_dragbut = true; - } - - if (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS && !(but->flag & UI_BUT_DISABLED)) { - uiHandleButtonData *data; - int *size = (int *)but->poin; - - ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); - button_activate_state(C, but, BUTTON_STATE_INIT); - - data = but->active; - data->dragstarty = event->y; + /* convert pan to scrollwheel */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - /* Again, have to override values set by ui_numedit_begin, because our listbox button also has a rnapoin... */ - *size = data->origvalue = (double)dyn_data->visual_height; - data->dragstartvalue = *size; - ui_list->flag |= UILST_RESIZING; - - retval = WM_UI_HANDLER_BREAK; + /* if type still is mousepan, we call it handled, since delta-y accumulate */ + /* also see wm_event_system.c do_wheel_ui hack */ + if (type == MOUSEPAN) + retval = WM_UI_HANDLER_BREAK; } - else { - /* convert pan to scrollwheel */ - if (type == MOUSEPAN) { - ui_pan_to_scroll(event, &type, &val); - /* if type still is mousepan, we call it handled, since delta-y accumulate */ - /* also see wm_event_system.c do_wheel_ui hack */ - if (type == MOUSEPAN) - retval = WM_UI_HANDLER_BREAK; - } + if (val == KM_PRESS) { + if (ELEM(type, UPARROWKEY, DOWNARROWKEY) || + ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) + { + const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop); + int value, min, max, inc; - if (val == KM_PRESS) { - if (ELEM(type, UPARROWKEY, DOWNARROWKEY) || - ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) - { - const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop); - int value, min, max, inc; + /* activate up/down the list */ + value = value_orig; + if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) { + inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1; + } + else { + inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1; + } - /* activate up/down the list */ - value = value_orig; - if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) { - inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1; - } - else { - inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1; - } + if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) { + /* If we have a display order different from collection order, we have some work! */ + int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), __func__); + int *new_order = dyn_data->items_filter_neworder; + int i, org_idx = -1, len = dyn_data->items_len; + int current_idx = -1; + int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; - if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) { - /* If we have a display order different from collection order, we have some work! */ - int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), __func__); - int *new_order = dyn_data->items_filter_neworder; - int i, org_idx = -1, len = dyn_data->items_len; - int current_idx = -1; - int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; - - for (i = 0; i < len; i++) { - if (!dyn_data->items_filter_flags || - ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) - { - org_order[new_order ? new_order[++org_idx] : ++org_idx] = i; - if (i == value) { - current_idx = new_order ? new_order[org_idx] : org_idx; - } - } - else if (i == value && org_idx >= 0) { - current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1; + for (i = 0; i < len; i++) { + if (!dyn_data->items_filter_flags || + ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) + { + org_order[new_order ? new_order[++org_idx] : ++org_idx] = i; + if (i == value) { + current_idx = new_order ? new_order[org_idx] : org_idx; } } - /* Now, org_order maps displayed indices to real indices, - * and current_idx either contains the displayed index of active value (positive), - * or its more-nearest one (negated). - */ - if (current_idx < 0) { - current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1); - } - else { - current_idx += inc; + else if (i == value && org_idx >= 0) { + current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1; } - CLAMP(current_idx, 0, dyn_data->items_shown - 1); - value = org_order[current_idx]; - MEM_freeN(org_order); + } + /* Now, org_order maps displayed indices to real indices, + * and current_idx either contains the displayed index of active value (positive), + * or its more-nearest one (negated). + */ + if (current_idx < 0) { + current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1); } else { - value += inc; + current_idx += inc; } + CLAMP(current_idx, 0, dyn_data->items_shown - 1); + value = org_order[current_idx]; + MEM_freeN(org_order); + } + else { + value += inc; + } - CLAMP(value, 0, dyn_data->items_len - 1); + CLAMP(value, 0, dyn_data->items_len - 1); - RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max); - CLAMP(value, min, max); + RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max); + CLAMP(value, min, max); - if (value != value_orig) { - RNA_property_int_set(&but->rnapoin, but->rnaprop, value); - RNA_property_update(C, &but->rnapoin, but->rnaprop); + if (value != value_orig) { + RNA_property_int_set(&but->rnapoin, but->rnaprop, value); + RNA_property_update(C, &but->rnapoin, but->rnaprop); - ui_apply_undo(but); + ui_apply_undo(but); - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; - ED_region_tag_redraw(ar); - } - retval = WM_UI_HANDLER_BREAK; + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(ar); + } + retval = WM_UI_HANDLER_BREAK; + } + else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { + /* We now have proper grip, but keep this anyway! */ + if (ui_list->list_grip < (dyn_data->visual_height_min - UI_LIST_AUTO_SIZE_THRESHOLD)) { + ui_list->list_grip = dyn_data->visual_height; } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { - /* We now have proper grip, but keep this anyway! */ - if (ui_list->list_grip == 0) - ui_list->list_grip = dyn_data->visual_height; + ui_list->list_grip += (type == WHEELUPMOUSE) ? -1 : 1; + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(ar); + + retval = WM_UI_HANDLER_BREAK; + } + else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { + if (dyn_data->height > dyn_data->visual_height) { /* list template will clamp */ - if (type == WHEELUPMOUSE) - ui_list->list_grip--; - else - ui_list->list_grip++; + ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1; - ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; ED_region_tag_redraw(ar); retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { - if (dyn_data->height > dyn_data->visual_height) { - /* list template will clamp */ - if (type == WHEELUPMOUSE) - ui_list->list_scroll--; - else - ui_list->list_scroll++; - - ED_region_tag_redraw(ar); - - retval = WM_UI_HANDLER_BREAK; - } - } } } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index be57987ee3c..1686abab9c7 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2528,15 +2528,6 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, Pr but->rnapoin = *actptr; but->rnaprop = actprop; - /* Resizing data. */ - /* Note: we can't use usual "num button" value handling, as it only tries rnapoin when it is non-NULL... :/ - * So just setting but->poin, not but->pointype. - */ - but->poin = (void *)&ui_list->list_grip; - but->hardmin = but->softmin = 0.0f; - but->hardmax = but->softmax = 1000.0f; /* Should be more than enough! */ - but->a1 = 0.0f; - /* only for the undo string */ if (but->flag & UI_BUT_UNDO) { but->tip = RNA_property_description(actprop); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9fd8acce3ee..371c70d5b7e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1705,39 +1705,33 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); PointerRNA cptr; - RNAUpdateCb *cb; uiBlock *block; - uiBut *bt; + uiLayout *col; Histogram *hist; - rctf rect; - + if (!prop || RNA_property_type(prop) != PROP_POINTER) return; - + cptr = RNA_property_pointer_get(ptr, prop); if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram)) return; - - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - - rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; - rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y; - - block = uiLayoutAbsoluteBlock(layout); - //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb); - hist = (Histogram *)cptr.data; - hist->height = (hist->height <= 20) ? 20 : hist->height; + if (hist->height < UI_UNIT_Y) { + hist->height = UI_UNIT_Y; + } + else if (hist->height > UI_UNIT_Y * 20) { + hist->height = UI_UNIT_Y * 20; + } - bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), UI_DPI_FAC * hist->height, - hist, 0, 0, 0, 0, ""); + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + uiDefBut(block, HISTOGRAM, 0, "", 0, 0, UI_UNIT_X * 10, hist->height, hist, 0, 0, 0, 0, ""); - MEM_freeN(cb); + /* Resize grip. */ + uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f), &hist->height, + UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, ""); } /********************* Waveform Template ************************/ @@ -1746,36 +1740,33 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); PointerRNA cptr; - RNAUpdateCb *cb; uiBlock *block; - uiBut *bt; + uiLayout *col; Scopes *scopes; - rctf rect; - + if (!prop || RNA_property_type(prop) != PROP_POINTER) return; - + cptr = RNA_property_pointer_get(ptr, prop); if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) return; scopes = (Scopes *)cptr.data; - - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - - rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; - rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y; - - block = uiLayoutAbsoluteBlock(layout); - - scopes->wavefrm_height = (scopes->wavefrm_height <= 20) ? 20 : scopes->wavefrm_height; - bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), UI_DPI_FAC * scopes->wavefrm_height, - scopes, 0, 0, 0, 0, ""); - (void)bt; /* UNUSED */ - - MEM_freeN(cb); + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); + + if (scopes->wavefrm_height < UI_UNIT_Y) { + scopes->wavefrm_height = UI_UNIT_Y; + } + else if (scopes->wavefrm_height > UI_UNIT_Y * 20) { + scopes->wavefrm_height = UI_UNIT_Y * 20; + } + + uiDefBut(block, WAVEFORM, 0, "", 0, 0, UI_UNIT_X * 10, scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + + /* Resize grip. */ + uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f), &scopes->wavefrm_height, + UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, ""); } /********************* Vectorscope Template ************************/ @@ -1784,36 +1775,33 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); PointerRNA cptr; - RNAUpdateCb *cb; uiBlock *block; - uiBut *bt; + uiLayout *col; Scopes *scopes; - rctf rect; - + if (!prop || RNA_property_type(prop) != PROP_POINTER) return; - + cptr = RNA_property_pointer_get(ptr, prop); if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) return; scopes = (Scopes *)cptr.data; - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - - rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; - rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y; - - block = uiLayoutAbsoluteBlock(layout); + if (scopes->vecscope_height < UI_UNIT_Y) { + scopes->vecscope_height = UI_UNIT_Y; + } + else if (scopes->vecscope_height > UI_UNIT_Y * 20) { + scopes->vecscope_height = UI_UNIT_Y * 20; + } - scopes->vecscope_height = (scopes->vecscope_height <= 20) ? 20 : scopes->vecscope_height; - - bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), - UI_DPI_FAC * scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); - uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - - MEM_freeN(cb); + col = uiLayoutColumn(layout, true); + block = uiLayoutGetBlock(col); + + uiDefBut(block, VECTORSCOPE, 0, "", 0, 0, UI_UNIT_X * 10, scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); + + /* Resize grip. */ + uiDefIconButI(block, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10, (short)(UI_UNIT_Y * 0.8f), &scopes->vecscope_height, + UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, ""); } /********************* CurveMapping Template ************************/ @@ -2695,30 +2683,17 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma { uiListDyn *dyn_data = ui_list->dyn_data; int activei_row, max_scroll; + const bool use_auto_size = (ui_list->list_grip < (rows - UI_LIST_AUTO_SIZE_THRESHOLD)); /* default rows */ - if (rows == 0) + if (rows <= 0) rows = 5; dyn_data->visual_height_min = rows; - if (maxrows == 0) - maxrows = 5; - if (columns == 0) + if (maxrows < rows) + maxrows = max_ii(rows, 5); + if (columns <= 0) columns = 9; - if (ui_list->list_grip >= (rows - 1) && ui_list->list_grip != 0) { - /* Only enable auto-size mode when we have dragged one row away from minimum size. - * Avoids to switch too easily to auto-size mode when resizing to minimum size... - */ - maxrows = rows = max_ii(ui_list->list_grip, rows); - } - else { - ui_list->list_grip = 0; /* Reset to auto-size mode. */ - /* Prevent auto-size mode to take effect while grab-resizing! */ - if (ui_list->flag & UILST_RESIZING) { - maxrows = rows; - } - } - if (columns > 1) { dyn_data->height = (int)ceil((double)len / (double)columns); activei_row = (int)floor((double)activei / (double)columns); @@ -2728,8 +2703,12 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma activei_row = activei; } - /* Expand size if needed and possible. */ - if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) { + if (!use_auto_size) { + /* No auto-size, yet we clamp at min size! */ + maxrows = rows = max_ii(ui_list->list_grip, rows); + } + else if ((rows != maxrows) && (dyn_data->height > rows)) { + /* Expand size if needed and possible. */ rows = min_ii(dyn_data->height, maxrows); } @@ -2753,6 +2732,21 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len); } +static void ui_list_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2)) +{ + uiList *ui_list = arg1; + uiListDyn *dyn_data = ui_list->dyn_data; + + /* This way we get diff in number of additional items to show (positive) or hide (negative). */ + const int diff = iroundf((float)(dyn_data->resize - dyn_data->resize_prev) / (float)UI_UNIT_Y); + + if (diff != 0) { + ui_list->list_grip += diff; + dyn_data->resize_prev += diff * UI_UNIT_Y; + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + } +} + void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, int rows, int maxrows, int layout_type, int columns) @@ -2859,6 +2853,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co if (!ui_list->dyn_data) { ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), "uiList.dyn_data"); + ui_list->list_grip = -UI_LIST_AUTO_SIZE_THRESHOLD; /* Force auto size by default. */ } dyn_data = ui_list->dyn_data; @@ -3104,6 +3099,18 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co } if (glob) { + /* About GRIP drag-resize: + * We can't directly use results from GRIP button, since we have a rather complex behavior here + * (sizing by discrete steps and, overall, autosize feature). + * Since we *never* know whether we are grip-resizing or not (because there is no callback for when a + * button enters/leaves its "edit mode"), we use the fact that grip-controlled value (dyn_data->resize) + * is completely handled by the grip during the grab resize, so settings its value here has no effect + * at all. + * It is only meaningful when we are not resizing, in which case this gives us the correct "init drag" value. + * Note we cannot affect dyn_data->resize_prev here, since this value is not controlled by the grip! + */ + dyn_data->resize = dyn_data->resize_prev + (dyn_data->visual_height - ui_list->list_grip) * UI_UNIT_Y; + row = uiLayoutRow(glob, true); subblock = uiLayoutGetBlock(row); uiBlockSetEmboss(subblock, UI_EMBOSSN); @@ -3114,9 +3121,9 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co TIP_("Hide filtering options")); uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ - but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.8f, ui_list, - 0.0, 0.0, 0, -1, ""); - uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + but = uiDefIconButI(subblock, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.8f, + &dyn_data->resize, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(but, ui_list_resize_update_cb, ui_list, NULL); uiBlockSetEmboss(subblock, UI_EMBOSS); @@ -3132,9 +3139,9 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co TIP_("Show filtering options")); uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ - but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.8f, ui_list, - 0.0, 0.0, 0, -1, ""); - uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + but = uiDefIconButI(subblock, GRIP, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.8f, + &dyn_data->resize, 0.0, 0.0, 0, 0, ""); + uiButSetFunc(but, ui_list_resize_update_cb, ui_list, NULL); uiBlockSetEmboss(subblock, UI_EMBOSS); } -- cgit v1.2.3