diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 8 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 251 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_layout.c | 9 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 168 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_buttons.c | 6 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_screen_types.h | 39 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui_api.c | 5 |
10 files changed, 365 insertions, 130 deletions
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index fe2f52d79fd..924cdff798d 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -267,6 +267,8 @@ void BKE_spacedata_draw_locks(int set) /* not region itself */ void BKE_area_region_free(SpaceType *st, ARegion *ar) { + uiList *uilst; + if (st) { ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype); @@ -285,6 +287,12 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar) } BLI_freelistN(&ar->panels); + + for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) { + if (uilst->dyn_data) { + MEM_freeN(uilst->dyn_data); + } + } BLI_freelistN(&ar->ui_lists); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index bab015d2a81..ff44bcc4cfe 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6127,6 +6127,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) { ui_list->type = NULL; + ui_list->dyn_data = NULL; } if (spacetype == SPACE_EMPTY) { diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 9a9cab9b46c..5712b64ae8f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -845,7 +845,7 @@ void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); #define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id, struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr, - const char *active_propname, int rows, int maxrows, int layout_type); + const char *active_propname, int rows, int maxrows, int layout_type, int columns); void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index f9ee2b67e6b..c0c8367eb8c 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -170,6 +170,7 @@ typedef struct uiHandleButtonData { /* coords are Window/uiBlock relative (depends on the button) */ int draglastx, draglasty; int dragstartx, dragstarty; + int draglastvalue; bool dragchange, draglock; int dragsel; float dragf, dragfstart; @@ -3406,6 +3407,87 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } +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; + int retval = WM_UI_HANDLER_CONTINUE; + + 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) { + data->cancel = true; + data->escapecancel = true; + *size = (int)data->origvalue; + button_activate_state(C, but, BUTTON_STATE_EXIT); + ED_region_tag_redraw(data->region); + } + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + 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->draglasty = data->dragstarty; + data->dragstarty = my; + } + else { + int delta = -(my - data->dragstarty); + /* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */ + delta /= UI_UNIT_Y; + + /* If we are not in autosize mode, default behavior... */ + if (*size > 0 && delta != 0) { + /* Note: In case some items of the list would draw more than UI_UNIT_Y height, we only grow from one + * item at a time, to avoid instability! + */ + delta = delta / abs(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); + + /* Used to detect switch to/from autosize mode. */ + data->draglastvalue = *size; + + data->dragchange = true; + data->applied = data->applied_interactive = true; + + 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; + + /* Restore real dragstarty value! */ + data->dragstarty = data->draglasty; + + /* Used to detect switch to/from autosize mode. */ + data->draglastvalue = *size; + + 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) { @@ -5367,8 +5449,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case NUMSLI: retval = ui_do_but_SLI(C, block, but, data, event); break; - case ROUNDBOX: case LISTBOX: + retval = ui_do_but_LISTBOX(C, block, but, data, event); + break; + case ROUNDBOX: case LABEL: case LISTLABEL: case ROW: @@ -5622,8 +5706,6 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y) uiBut *but; int mx, my; -// if (!win->active) -// return NULL; if (!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -5768,7 +5850,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s WM_cursor_grab_disable(data->window, NULL); } #else - WM_cursor_grab_disable(data->window, ); + WM_cursor_grab_disable(data->window, NULL); #endif } } @@ -6423,90 +6505,125 @@ 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 = ui_list_find_mouse_over(ar, event->x, event->y); + uiBut *but, *dragbut; + 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; - if (but) { - uiList *ui_list = but->custom_data; + but = ui_list_find_mouse_over(ar, event->x, event->y); + if (!but) { + return retval; + } - if (ui_list) { - - /* 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; + ui_list = but->custom_data; + if (!ui_list || !ui_list->dyn_data) { + return retval; + } + dyn_data = ui_list->dyn_data; - /* activate up/down the list */ - value = value_orig; + mx = event->x; + my = event->y; + ui_window_to_block(ar, but->block, &mx, &my); - if (ELEM(type, UPARROWKEY, WHEELUPMOUSE)) - value--; - else - value++; + /* 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->x, event->y)) { + is_over_dragbut = true; + } - CLAMP(value, 0, ui_list->list_last_len - 1); + if (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS) { + uiHandleButtonData *data; + int *size = (int *)but->poin; - if (value < ui_list->list_scroll) - ui_list->list_scroll = value; - else if (value >= ui_list->list_scroll + ui_list->list_size) - ui_list->list_scroll = value - ui_list->list_size + 1; + ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); + button_activate_state(C, but, BUTTON_STATE_INIT); - RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max); - value = CLAMPIS(value, min, max); + data = but->active; + data->dragstarty = my; - if (value != value_orig) { - RNA_property_int_set(&but->rnapoin, but->rnaprop, value); - RNA_property_update(C, &but->rnapoin, but->rnaprop); + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - ui_apply_undo(but); - ED_region_tag_redraw(ar); - } + /* 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; - retval = WM_UI_HANDLER_BREAK; + 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; + + /* activate up/down the list */ + value = value_orig; + + if (ELEM(type, UPARROWKEY, WHEELUPMOUSE)) + value--; + else + value++; + + 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); } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { - /* silly replacement for proper grip */ - if (ui_list->list_grip_size == 0) - ui_list->list_grip_size = ui_list->list_size; + 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 == 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++; + + 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_size--; + ui_list->list_scroll--; else - ui_list->list_grip_size++; - - ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1); + ui_list->list_scroll++; ED_region_tag_redraw(ar); retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { - if (ui_list->list_last_len > ui_list->list_size) { - /* 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 7ff7c279dcd..ce9b0db6b14 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2432,6 +2432,15 @@ 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 451c38ded2d..5ffb47c4df0 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2497,30 +2497,89 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN } } +typedef struct { + int visual_items; /* Visual number of items (i.e. number of items we have room to display). */ + int start_idx; /* Index of first item to display. */ + int end_idx; /* Index of last item to display + 1. */ +} uiListLayoutdata; + +static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, + uiListLayoutdata *layoutdata) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + int activei_row, max_scroll; + + /* default rows */ + if (rows == 0) + rows = 5; + dyn_data->visual_height_min = rows; + if (maxrows == 0) + maxrows = 5; + if (columns == 0) + columns = 9; + if (ui_list->list_grip >= rows) + maxrows = rows = ui_list->list_grip; + else + ui_list->list_grip = 0; /* Reset to auto-size mode. */ + + if (columns > 1) { + dyn_data->height = (int)ceil((double)len / (double)columns); + activei_row = (int)floor((double)activei / (double)columns); + } + else { + dyn_data->height = len; + activei_row = activei; + } + + /* Expand size if needed and possible. */ + if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) { + rows = min_ii(dyn_data->height, maxrows); + } + + /* If list length changes or list is tagged to check this, and active is out of view, scroll to it .*/ + if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) { + if (activei_row < ui_list->list_scroll) { + ui_list->list_scroll = activei_row; + } + else if (activei_row >= ui_list->list_scroll + rows) { + ui_list->list_scroll = activei_row - rows + 1; + } + ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM; + } + + max_scroll = max_ii(0, dyn_data->height - rows); + CLAMP(ui_list->list_scroll, 0, max_scroll); + ui_list->list_last_len = len; + dyn_data->visual_height = rows; + layoutdata->visual_items = rows * columns; + layoutdata->start_idx = ui_list->list_scroll * columns; + layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len); +} + 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) + const char *active_propname, int rows, int maxrows, int layout_type, int columns) { uiListType *ui_list_type; uiList *ui_list = NULL; + uiListDyn *dyn_data; ARegion *ar; uiListDrawItemFunc draw_item; PropertyRNA *prop = NULL, *activeprop; PropertyType type, activetype; StructRNA *ptype; - uiLayout *box, *row, *col, *sub, *overlap; + uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap; uiBlock *block, *subblock; uiBut *but; + uiListLayoutdata layoutdata; char ui_list_id[UI_MAX_NAME_STR]; char numstr[32]; int rnaicon = ICON_NONE, icon = ICON_NONE; int i = 0, activei = 0; int len = 0; - int items; int found; - int min, max; /* validate arguments */ /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ @@ -2592,54 +2651,39 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id)); if (!ui_list) { - ui_list = MEM_callocN(sizeof(uiList), __func__); + ui_list = MEM_callocN(sizeof(uiList), AT); BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id)); BLI_addtail(&ar->ui_lists, ui_list); } + if (!ui_list->dyn_data) { + ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), AT); + } + dyn_data = ui_list->dyn_data; + /* Because we can't actually pass type across save&load... */ ui_list->type = ui_list_type; ui_list->layout_type = layout_type; + if (dataptr->data && prop) + dyn_data->items_len = dyn_data->items_shown = len = RNA_property_collection_length(dataptr, prop); + switch (layout_type) { case UILST_LAYOUT_DEFAULT: - /* default rows */ - if (rows == 0) - rows = 5; - if (maxrows == 0) - maxrows = 5; - if (ui_list->list_grip_size != 0) - rows = ui_list->list_grip_size; - /* layout */ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop); - row = uiLayoutRow(box, FALSE); + glob = uiLayoutColumn(box, TRUE); + row = uiLayoutRow(glob, FALSE); col = uiLayoutColumn(row, TRUE); /* init numbers */ - RNA_property_int_range(active_dataptr, activeprop, &min, &max); - - if (prop) - len = RNA_property_collection_length(dataptr, prop); - items = CLAMPIS(len, rows, MAX2(rows, maxrows)); - - /* if list length changes and active is out of view, scroll to it */ - if ((ui_list->list_last_len != len) && - (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items)) - { - ui_list->list_scroll = activei; - } - - ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items); - ui_list->list_scroll = max_ii(ui_list->list_scroll, 0); - ui_list->list_size = items; - ui_list->list_last_len = len; + prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata); if (dataptr->data && prop) { /* create list items */ RNA_PROP_BEGIN (dataptr, itemptr, prop) { - if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) { + if (i >= layoutdata.start_idx && i < layoutdata.end_idx) { subblock = uiLayoutGetBlock(col); overlap = uiLayoutOverlap(col); @@ -2672,17 +2716,16 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co } /* add dummy buttons to fill space */ - while (i < ui_list->list_scroll + items) { - if (i >= ui_list->list_scroll) - uiItemL(col, "", ICON_NONE); - i++; + for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { + uiItemL(col, "", ICON_NONE); } /* add scrollbar */ - if (len > items) { + if (len > layoutdata.visual_items) { col = uiLayoutColumn(row, FALSE); - uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll, - 0, len - items, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, 0, ""); } break; case UILST_LAYOUT_COMPACT: @@ -2719,19 +2762,24 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co break; case UILST_LAYOUT_GRID: box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop); - col = uiLayoutColumn(box, TRUE); - row = uiLayoutRow(col, FALSE); + glob = uiLayoutColumn(box, TRUE); + row = uiLayoutRow(glob, FALSE); + col = uiLayoutColumn(row, TRUE); + subrow = NULL; /* Quite gcc warning! */ + + prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata); if (dataptr->data && prop) { /* create list items */ RNA_PROP_BEGIN (dataptr, itemptr, prop) { + if (i >= layoutdata.start_idx && i < layoutdata.end_idx) { /* create button */ - if (!(i % 9)) - row = uiLayoutRow(col, FALSE); + if (!(i % columns)) + subrow = uiLayoutRow(col, FALSE); - subblock = uiLayoutGetBlock(row); - overlap = uiLayoutOverlap(row); + subblock = uiLayoutGetBlock(subrow); + overlap = uiLayoutOverlap(subrow); uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM); @@ -2753,13 +2801,41 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co } uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM); - + } i++; } RNA_PROP_END; } + + /* add dummy buttons to fill space */ + for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { + if (!(i % columns)) { + subrow = uiLayoutRow(col, FALSE); + } + uiItemL(subrow, "", ICON_NONE); + } + + /* add scrollbar */ + if (len > layoutdata.visual_items) { + col = uiLayoutColumn(row, FALSE); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, 0, ""); + } break; } + + if (glob) { + row = uiLayoutRow(glob, TRUE); + subblock = uiLayoutGetBlock(row); + uiBlockSetEmboss(subblock, UI_EMBOSSN); + + but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.4f, ui_list, + 0.0, 0.0, 0, -1, ""); + uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + uiBlockSetEmboss(subblock, UI_EMBOSS); + } } /************************* Operator Search Template **************************/ diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index a011657ce51..d00d1e61b0d 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1628,12 +1628,14 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C active_index = RNA_int_get(ptr, "active_input_index"); /* using different collection properties if multilayer format is enabled */ if (multilayer) { - uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0); + uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", + 0, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr); } else { - uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0); + uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", + 0, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr); } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index f95e895bef2..53b373e728e 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -145,13 +145,15 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) split = uiLayoutRow(row, TRUE); col = uiLayoutColumn(split, TRUE); uiItemL(col, IFACE_("Inputs:"), ICON_NONE); - uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", 0, 0, 0); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", + 0, 0, 0, 0); opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_IN); col = uiLayoutColumn(split, TRUE); uiItemL(col, IFACE_("Outputs:"), ICON_NONE); - uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", 0, 0, 0); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", + 0, 0, 0, 0); opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_OUT); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 9d840ad13e8..c15deaeb137 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -112,22 +112,36 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */ void *activedata; /* runtime for panel manipulation */ } Panel; -typedef struct uiList { /* some list UI data need to be saved in file */ +/* uiList dynamic data... */ +/* These two Lines with # tell makesdna this struct can be excluded. */ +# +# +typedef struct uiListDyn { + int height; /* Number of rows needed to draw all elements. */ + int visual_height; /* Actual visual height of the list (in rows). */ + int visual_height_min; /* Minimal visual height of the list (in rows). */ + + int items_len; /* Number of items in collection. */ + int items_shown; /* Number of items actually visible after filtering. */ +} uiListDyn; + +typedef struct uiList { /* some list UI data need to be saved in file */ struct uiList *next, *prev; - struct uiListType *type; /* runtime */ - void *padp; + struct uiListType *type; /* runtime */ - char list_id[64]; /* defined as UI_MAX_NAME_STR */ + char list_id[64]; /* defined as UI_MAX_NAME_STR */ - int layout_type; /* How items are layedout in the list */ - int padi; + int layout_type; /* How items are layedout in the list */ + int flag; int list_scroll; - int list_size; + int list_grip; int list_last_len; - int list_grip_size; -/* char list_search[64]; */ + int padi1; + + /* Dynamic data (runtime). */ + uiListDyn *dyn_data; } uiList; typedef struct ScrArea { @@ -232,13 +246,18 @@ typedef struct ARegion { #define PNL_DEFAULT_CLOSED 1 #define PNL_NO_HEADER 2 -/* uilist layout_type */ +/* uiList layout_type */ enum { UILST_LAYOUT_DEFAULT = 0, UILST_LAYOUT_COMPACT = 1, UILST_LAYOUT_GRID = 2, }; +/* uiList flag */ +enum { + UILST_SCROLL_TO_ACTIVE_ITEM = 1 << 0, /* Scroll list to make active item visible. */ +}; + /* regiontype, first two are the default set */ /* Do NOT change order, append on end. Types are hardcoded needed */ enum { diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 7b90a78811f..d79a40aa615 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -796,9 +796,10 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_string(func, "active_propname", "", 0, "", "Identifier of the integer property in active_data, index of the active item"); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX); - RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX); + RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Default and minimum number of rows to display", 0, INT_MAX); + RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Default maximum number of rows to display", 0, INT_MAX); RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use"); + RNA_def_int(func, "columns", 9, 0, INT_MAX, "", "Number of items to display per row, for GRID layout", 0, INT_MAX); func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); |