UI: use automatic search box width in more places
Most search-boxes still used a hard-coded width. This has the problem that it is
often too wide or too small for its content. This patch builds on top of
bf696320f6 to make the size of more menus adapt
automatically.
In all the cases I've tried, the width-detection code only ran once when the
search is triggered, and not continuously as might happen for some menus as
mentioned in
https://projects.blender.org/blender/blender/pulls/138653#issuecomment-1572027.
Pull Request: https://projects.blender.org/blender/blender/pulls/139423
This commit is contained in:
@@ -1796,7 +1796,7 @@ int UI_searchbox_size_x();
|
||||
* \note When used with a menu that does full refreshes, it might be beneficial to cache this size
|
||||
* because recomputing it is potentially expensive.
|
||||
*/
|
||||
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn);
|
||||
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn, void *arg);
|
||||
/**
|
||||
* Check if a string is in an existing search box.
|
||||
*/
|
||||
|
||||
@@ -179,34 +179,20 @@ int UI_searchbox_size_x()
|
||||
return 12 * UI_UNIT_X;
|
||||
}
|
||||
|
||||
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn)
|
||||
static int ui_searchbox_size_x_from_items(const uiSearchItems &items)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
uiSearchItems items{};
|
||||
/* Upper bound on the number of item names that are checked. */
|
||||
items.maxitem = 1000;
|
||||
items.maxstrlen = 256;
|
||||
|
||||
/* Prepare name buffers. */
|
||||
Array<char> names_buffer(items.maxitem * items.maxstrlen);
|
||||
Array<char *> names(items.maxitem);
|
||||
items.names = names.data();
|
||||
for (int i : IndexRange(items.maxitem)) {
|
||||
names[i] = names_buffer.data() + i * items.maxstrlen;
|
||||
}
|
||||
|
||||
/* Gather the names shown in the search box. */
|
||||
update_fn(C, nullptr, "", &items, true);
|
||||
|
||||
/* Compute the width of each item. */
|
||||
Array<int> item_widths(items.totitem);
|
||||
threading::parallel_for(item_widths.index_range(), 256, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
const blender::StringRefNull name = items.names[i];
|
||||
const int icon = items.icons ? items.icons[i] : ICON_NONE;
|
||||
const float text_width = BLF_width(BLF_default(), name.c_str(), name.size(), nullptr);
|
||||
const float icon_with_padding = icon == ICON_NONE ? 0.0f : UI_ICON_SIZE + UI_UNIT_X;
|
||||
const float padding = UI_UNIT_X;
|
||||
item_widths[i] = int(text_width + padding);
|
||||
item_widths[i] = int(text_width + padding + icon_with_padding);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -220,6 +206,34 @@ int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn updat
|
||||
return box_width;
|
||||
}
|
||||
|
||||
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn, void *arg)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
uiSearchItems items{};
|
||||
/* Upper bound on the number of item names that are checked. */
|
||||
items.maxitem = 1000;
|
||||
items.maxstrlen = 256;
|
||||
|
||||
/* Prepare name buffers. */
|
||||
Array<char> names_buffer(items.maxitem * items.maxstrlen);
|
||||
Array<char *> names(items.maxitem);
|
||||
Array<int> icons(items.maxitem);
|
||||
items.names = names.data();
|
||||
items.icons = icons.data();
|
||||
for (int i : IndexRange(items.maxitem)) {
|
||||
names[i] = names_buffer.data() + i * items.maxstrlen;
|
||||
}
|
||||
|
||||
/* Gather the items shown in the search box. */
|
||||
update_fn(C, arg, "", &items, true);
|
||||
|
||||
/* This is lazy-initialized in #UI_search_item_add. */
|
||||
MEM_SAFE_FREE(items.name_prefix_offsets);
|
||||
|
||||
return ui_searchbox_size_x_from_items(items);
|
||||
}
|
||||
|
||||
int UI_search_items_find_index(const uiSearchItems *items, const char *name)
|
||||
{
|
||||
if (items->name_prefix_offsets != nullptr) {
|
||||
@@ -823,22 +837,6 @@ static void ui_searchbox_region_listen_fn(const wmRegionListenerParams *params)
|
||||
}
|
||||
}
|
||||
|
||||
static uiMenuItemSeparatorType ui_searchbox_item_separator(uiSearchboxData *data)
|
||||
{
|
||||
uiMenuItemSeparatorType separator_type = data->use_shortcut_sep ?
|
||||
UI_MENU_ITEM_SEPARATOR_SHORTCUT :
|
||||
UI_MENU_ITEM_SEPARATOR_NONE;
|
||||
if (separator_type == UI_MENU_ITEM_SEPARATOR_NONE && !data->preview) {
|
||||
for (int a = 0; a < data->items.totitem; a++) {
|
||||
if (data->items.but_flags[a] & UI_BUT_HAS_SEP_CHAR) {
|
||||
separator_type = UI_MENU_ITEM_SEPARATOR_HINT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return separator_type;
|
||||
}
|
||||
|
||||
static void ui_searchbox_region_layout_fn(const bContext *C, ARegion *region)
|
||||
{
|
||||
uiSearchboxData *data = (uiSearchboxData *)region->regiondata;
|
||||
@@ -880,12 +878,7 @@ static void ui_searchbox_region_layout_fn(const bContext *C, ARegion *region)
|
||||
}
|
||||
}
|
||||
else {
|
||||
int searchbox_width = int(float(UI_searchbox_size_x()) * 1.4f);
|
||||
|
||||
/* We should make this wider if there is a path or hint on the right. */
|
||||
if (ui_searchbox_item_separator(data) != UI_MENU_ITEM_SEPARATOR_NONE) {
|
||||
searchbox_width += 12 * data->fstyle.points * UI_SCALE_FAC;
|
||||
}
|
||||
const int searchbox_width = ui_searchbox_size_x_from_items(data->items);
|
||||
|
||||
rctf rect_fl;
|
||||
rect_fl.xmin = but->rect.xmin;
|
||||
|
||||
@@ -187,7 +187,7 @@ uiBlock *template_common_search_menu(const bContext *C,
|
||||
}
|
||||
/* list view */
|
||||
else {
|
||||
const int searchbox_width = int(float(UI_searchbox_size_x()) * 1.4f);
|
||||
const int searchbox_width = UI_searchbox_size_x_guess(C, search_update_fn, search_arg);
|
||||
const int searchbox_height = UI_searchbox_size_y();
|
||||
const int search_but_height = UI_UNIT_Y - 1.0f * UI_SCALE_FAC;
|
||||
|
||||
|
||||
@@ -1367,7 +1367,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_optype)
|
||||
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||
|
||||
const int box_width = UI_searchbox_size_x_guess(C, node_find_update_fn);
|
||||
const int box_width = UI_searchbox_size_x_guess(C, node_find_update_fn, nullptr);
|
||||
|
||||
but = uiDefSearchBut(
|
||||
block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, box_width, UI_UNIT_Y, "");
|
||||
|
||||
Reference in New Issue
Block a user