Fix T37739: uiList drag-resize was not working as expected outside of panels.

Patch by Brecht, with minor edits by myself, thanks a lot!

Tech details: previous drag-resize handling code was based on the assumption that coords
returned by ui_window_to_block() was relative to the bottom on the uiBlock.
This is in fact completly eroneous, usually this func does not translate at all the coords,
it merely rescale them - except for blocks inside panels, where returned values are relative
to the left/bottom corner of the panel... Pretty confusing, solution for now is to store ref mouse
position in window space, and convert them to block each time, just like current mouse pos.
This commit is contained in:
Bastien Montagne 2013-12-10 16:06:20 +01:00
parent 4b127dfc5a
commit a1031d5dd5
Notes: blender-bot 2023-02-14 11:30:59 +01:00
Referenced by issue #37739, template_list UI elements on Nodes don't resize correctly
1 changed files with 38 additions and 46 deletions

View File

@ -174,6 +174,7 @@ typedef struct uiHandleButtonData {
int draglastx, draglasty;
int dragstartx, dragstarty;
int draglastvalue;
int dragstartvalue;
bool dragchange, draglock;
int dragsel;
float dragf, dragfstart;
@ -3585,18 +3586,20 @@ static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
{
uiList *ui_list = but->custom_data;
int *size = (int *)but->poin;
int mx, my, raw_dir_sign;
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;
/* We find the direction of the mouse since last time, before converting coordinates into block's space.
* We'll use it to avoid flickering in case some rows are higher than UI_UNIT_Y.
*/
raw_dir_sign = (data->draglasty - my < 0) ? -1 : 1;
data->draglasty = my;
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_NUM_EDITING) {
@ -3622,52 +3625,40 @@ static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
if (data->draglastvalue > 0 && *size == 0) {
data->draglastvalue = *size;
data->dragstartx = data->dragstarty; /* draglasty already used... */
data->dragstarty = my;
data->dragstarty = event->y;
}
else {
int delta = data->dragstarty - my;
/* We only actually do something if the real mousemouve direction matches the "virtual"
* mousemove direction in current block's space. This avoids flickering when drag-resizing lists with
* items drawing higher that UI_UNIT_Y.
*/
if (delta * raw_dir_sign > 0) {
/* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */
delta = (int)floorf(((float)delta / (float)UI_UNIT_Y) + 0.5f);
int newsize = *size;
int diff = dragy - my;
/* If we are not in autosize mode, default behavior... */
if (*size > 0 && delta != 0) {
/* This prevents some instability in case some items draw more/less than UI_UNIT_Y height. */
delta = (delta < -5) ? -5 : (delta > 5) ? 5 : delta;
/* We can't use ui_numedit_apply()... */
/* list template will clamp, but we do not want to reach 0 aka autosize mode! */
*size = max_ii(*size + delta, 1);
diff = (int)floorf(((float)diff / (float)UI_UNIT_Y) + 0.5f);
/* Used to detect switch to/from autosize mode. */
data->draglastvalue = *size;
/* 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;
data->dragchange = true;
data->applied = data->applied_interactive = true;
/* Restore real dragstarty value! */
data->dragstarty = data->dragstartx;
}
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(data->region);
}
/* If we are leaving autosize mode (growing dragging), restore to minimal size. */
else if (delta > 0) {
/* We can't use ui_numedit_apply()... */
*size = ui_list->dyn_data->visual_height_min;
/* Used to detect switch to/from autosize mode. */
data->draglastvalue = newsize;
/* Restore real dragstarty value! */
data->dragstarty = data->dragstartx;
if (newsize != *size) {
*size = newsize;
/* Used to detect switch to/from autosize mode. */
data->draglastvalue = *size;
/* We can't use ui_numedit_apply()... */
data->dragchange = true;
data->applied = data->applied_interactive = true;
data->dragchange = true;
data->applied = data->applied_interactive = true;
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(data->region);
}
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(data->region);
}
}
}
@ -6877,12 +6868,13 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
button_activate_state(C, but, BUTTON_STATE_INIT);
data = but->active;
data->dragstarty = my;
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;