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
This commit is contained in:
Bastien Montagne 2014-04-02 13:09:43 +02:00
parent 4faef1e10c
commit 9b3bd5582b
6 changed files with 255 additions and 484 deletions

View File

@ -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);

View File

@ -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,24 +5386,18 @@ 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;
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);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
}
else {
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);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
}
scopes->ok = 0;
}
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;
/* 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 (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS && !(but->flag & UI_BUT_DISABLED)) {
uiHandleButtonData *data;
int *size = (int *)but->poin;
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;
ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
button_activate_state(C, but, BUTTON_STATE_INIT);
data = but->active;
data->dragstarty = event->y;
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;
}
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;
/* 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;
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;
}
}
/* 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;
}
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);
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);
ui_apply_undo(but);
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(ar);
}
retval = WM_UI_HANDLER_BREAK;
/* 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 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;
/* list template will clamp */
if (type == WHEELUPMOUSE)
ui_list->list_grip--;
else
ui_list->list_grip++;
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;
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;
}
}
/* 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;
}
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);
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);
ui_apply_undo(but);
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;
}
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 */
ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1;
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;
}
}
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -153,7 +153,7 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
PropertyRNA *prop;
PointerRNA scopesptr;
uiBlock *block;
rctf rect;
uiLayout *col;
MovieClipScopes *scopes;
if (!ptr->data)
@ -175,16 +175,21 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
scopesptr = RNA_property_pointer_get(ptr, prop);
scopes = (MovieClipScopes *)scopesptr.data;
rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
rect.ymin = 0; rect.ymax = 6.0f * UI_UNIT_Y;
if (scopes->track_preview_height < UI_UNIT_Y) {
scopes->track_preview_height = UI_UNIT_Y;
}
else if (scopes->track_preview_height > UI_UNIT_Y * 20) {
scopes->track_preview_height = UI_UNIT_Y * 20;
}
block = uiLayoutAbsoluteBlock(layout);
col = uiLayoutColumn(layout, true);
block = uiLayoutGetBlock(col);
scopes->track_preview_height =
(scopes->track_preview_height <= 20) ? 20 : scopes->track_preview_height;
uiDefBut(block, TRACKPREVIEW, 0, "", 0, 0, UI_UNIT_X * 10, scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect),
scopes->track_preview_height * UI_DPI_FAC, 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->track_preview_height, UI_UNIT_Y, UI_UNIT_Y * 20.0f, 0.0f, 0.0f, "");
}
/********************* Marker Template ************************/

View File

@ -154,6 +154,12 @@ typedef struct uiListDyn {
int items_len; /* Number of items in collection. */
int items_shown; /* Number of items actually visible after filtering. */
/* Those are temp data used during drag-resize with GRIP button (they are in pixels, the meaningful data is the
* difference between resize_prev and resize)...
*/
int resize;
int resize_prev;
/* Filtering data. */
int *items_filter_flags; /* items_len length. */
int *items_filter_neworder; /* org_idx -> new_idx, items_len length. */
@ -319,9 +325,11 @@ enum {
/* uiList flag */
enum {
UILST_SCROLL_TO_ACTIVE_ITEM = 1 << 0, /* Scroll list to make active item visible. */
UILST_RESIZING = 1 << 1, /* We are currently resizing, deactivate autosize! */
};
/* Value (in number of items) we have to go below minimum shown items to enable auto size. */
#define UI_LIST_AUTO_SIZE_THRESHOLD 1
/* uiList filter flags (dyn_data) */
enum {
UILST_FLT_ITEM = 1 << 31, /* This item has passed the filter process successfully. */