101#define SEARCH_ITEMS 10
108 const uint8_t name_prefix_offset)
122 if (poin == items->
active) {
150 if (name_prefix_offset != 0) {
189 for (const int i : range) {
190 const blender::StringRefNull name = items.names[i];
191 const int icon = items.icons ? items.icons[i] : ICON_NONE;
192 const float text_width = BLF_width(BLF_default(), name.c_str(), name.size(), nullptr);
193 const float icon_with_padding = icon == ICON_NONE ? 0.0f : UI_ICON_SIZE + UI_UNIT_X;
194 const float padding = UI_UNIT_X;
195 item_widths[i] = int(text_width + padding + icon_with_padding);
201 for (
const int width : item_widths) {
202 box_width = std::max(box_width, width);
229 update_fn(
C, arg,
"", &items,
true);
264 if (
data->items.totitem == 0) {
267 else if (
data->active >=
data->items.totitem) {
268 if (
data->items.more) {
269 data->items.offset++;
270 data->active =
data->items.totitem - 1;
274 data->active =
data->items.totitem - 1;
277 else if (
data->active < 0) {
278 if (
data->items.offset) {
279 data->items.offset--;
302 *r_rect =
data->bbox;
305 row = itemnr /
data->prv_cols;
310 r_rect->
ymax -= tria_h + row * buth;
317 *r_rect =
data->bbox;
322 r_rect->
ymax =
data->bbox.ymax - tria_h - itemnr * buth;
349 if (
data->active != -1) {
350 const char *name =
data->items.names[
data->active] +
352 (
data->items.name_prefix_offsets ?
353 data->items.name_prefix_offsets[
data->active] :
356 const char *name_sep =
data->use_shortcut_sep ? strrchr(name,
UI_SEP_CHAR) :
nullptr;
376 *r_exit_on_event =
true;
379 for (
const std::unique_ptr<uiBut> &but : block->buttons) {
409 int type =
event->
type, val =
event->val;
410 bool handled =
false;
411 bool tooltip_timer_started =
false;
433 if (
data->active != -1) {
458 for (a = 0; a <
data->items.totitem; a++) {
464 if (
data->active != a) {
476 if (
data->active != -1) {
480 tooltip_timer_started =
true;
489 if (handled && (tooltip_timer_started ==
false)) {
508 const bool is_first_search = !but->
changed;
520 data->items.totitem = 0;
521 data->items.more = 0;
523 data->items.offset_i =
data->items.offset;
526 data->items.offset_i =
data->items.offset = 0;
530 const bool is_first_search = !but->
changed;
534 data->items.active =
nullptr;
537 if (
data->items.totitem) {
539 if (
data->items.offset_i <
data->items.maxitem) {
540 data->active =
data->items.offset_i;
541 data->items.offset_i = 0;
545 if (
data->items.totitem -
data->items.offset_i <=
data->items.maxitem) {
546 data->active =
data->items.offset_i -
data->items.totitem +
data->items.maxitem;
547 data->items.offset_i =
data->items.totitem -
data->items.maxitem;
551 data->items.offset_i -=
data->items.maxitem / 2;
552 data->active =
data->items.maxitem / 2;
556 data->items.offset =
data->items.offset_i;
557 data->items.totitem = 0;
568 for (
int a = 0; a <
data->items.totitem; a++) {
569 const char *name =
data->items.names[a] +
571 (
data->items.name_prefix_offsets ?
data->items.name_prefix_offsets[a] :
573 const char *name_sep =
data->use_shortcut_sep ? strrchr(name,
UI_SEP_CHAR) :
nullptr;
602 maxncpy = strlen(
str) + 1024;
609 data->items.autocpl =
nullptr;
625 const float aspect =
U.inv_scale_factor / zoom;
641 const float aspect =
U.inv_scale_factor / zoom;
654 if (
data->noback ==
false) {
659 if (
data->items.totitem) {
664 for (
int a = 0; a <
data->items.totitem; a++) {
665 const int but_flag = ((a ==
data->active) ?
UI_HOVER : 0) |
data->items.but_flags[a];
676 data->items.names[a],
677 data->items.icons[a],
683 if (
data->items.more ||
data->items.offset) {
684 rcti rect_first_item;
689 if (
data->items.offset) {
691 rect_first_item.
xmax = rect_max_item.
xmax;
695 if (
data->items.more) {
697 rect_max_item.
xmin = rect_first_item.
xmin;
703 const int search_sep_len =
data->sep_string ? strlen(
data->sep_string) : 0;
705 for (
int a = 0; a <
data->items.totitem; a++) {
706 const int but_flag = ((a ==
data->active) ?
UI_HOVER : 0) |
data->items.but_flags[a];
707 const char *name =
data->items.names[a];
708 int icon =
data->items.icons[a];
709 char *name_sep_test =
nullptr;
712 if (
data->use_shortcut_sep) {
723 if ((search_sep_len == 0) ||
724 !(name_sep_test = strstr(
data->items.names[a],
data->sep_string)))
726 if (!icon &&
data->items.has_icon) {
745 char *name_sep =
nullptr;
747 name_sep = name_sep_test;
748 name_sep_test = strstr(name_sep + search_sep_len,
data->sep_string);
749 }
while (name_sep_test !=
nullptr);
751 name_sep += search_sep_len;
752 const char name_sep_prev = *name_sep;
765 *name_sep = name_sep_prev;
766 rect.
xmin += name_width;
769 if (icon == ICON_BLANK1) {
772 if (icon != ICON_NONE) {
790 if (
data->items.more) {
794 if (
data->items.offset) {
808 IFACE_(
"No results found"),
821 for (
int a = 0; a <
data->items.maxitem; a++) {
829 if (
data->items.name_prefix_offsets !=
nullptr) {
840 if (
data->search_listener) {
849 if (
data->size_set) {
867 const float zoom =
data->zoom;
874 data->bbox.ymin = margin;
879 data->bbox.ymin += search_but_h;
882 data->bbox.ymax -= search_but_h;
901 rect_fl.
xmax = rect_fl.
xmin + searchbox_width;
918 if (rect_i.
xmax > winx) {
920 if (rect_i.
xmax > winx + rect_i.
xmin) {
930 if (rect_i.
ymin < 0) {
944 data->bbox.xmin = margin;
946 data->bbox.ymin = margin;
959 data->size_set =
true;
965 const bool use_shortcut_sep)
985 data->search_but = but;
986 data->butregion = butregion;
987 data->size_set =
false;
989 data->zoom = 1.0f / aspect;
1001 data->noback =
true;
1005 data->preview =
true;
1010 if (but->
optype !=
nullptr || use_shortcut_sep) {
1011 data->use_shortcut_sep =
true;
1022 if (
data->preview) {
1030 data->items.totitem = 0;
1032 data->items.pointers = (
void **)
MEM_callocN(
data->items.maxitem *
sizeof(
void *), __func__);
1035 data->items.name_prefix_offsets =
nullptr;
1036 for (
int i = 0;
i <
data->items.maxitem;
i++) {
1056 bool prev_delim =
true;
1058 for (
size_t i = 0; (
i <
len) &&
str[
i];
i++) {
1059 if (
str[
i] >=
'A' &&
str[
i] <=
'Z') {
1060 if (prev_delim ==
false) {
1061 str[
i] +=
'a' -
'A';
1064 else if (
str[
i] ==
'_') {
1079 if (
data->noback ==
false) {
1084 if (
data->items.totitem) {
1088 for (
int a = 0; a <
data->items.totitem; a++) {
1089 rcti rect_pre, rect_post;
1100 const int but_flag = ((a ==
data->active) ?
UI_HOVER : 0) |
data->items.but_flags[a];
1104 const char *text_pre_p = strstr(
ot->idname,
"_OT_");
1105 if (text_pre_p ==
nullptr) {
1112 text_pre,
ot->idname,
min_ii(
sizeof(text_pre), text_pre_p -
ot->idname));
1113 text_pre[text_pre_len] =
':';
1114 text_pre[text_pre_len + 1] =
'\0';
1124 data->items.icons[a],
1133 data->items.names[a],
1142 if (
data->items.more) {
1146 if (
data->items.offset) {
1159 IFACE_(
"No results found"),
1222 else if (items->
more == 0) {
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
#define LISTBASE_FOREACH(type, var, list)
MINLINE int min_ii(int a, int b)
void BLI_rctf_translate(struct rctf *rect, float x, float y)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
void BLI_rcti_translate(struct rcti *rect, int x, int y)
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char char size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STREQLEN(a, b, n)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
void ED_region_floating_init(ARegion *region)
void ED_region_tag_redraw(ARegion *region)
void GPU_blend(eGPUBlend blend)
Read Guarded memory(de)allocation.
void(*)(const bContext *C, void *arg, const char *str, uiSearchItems *items, bool is_first) uiButSearchUpdateFn
ARegion * UI_region_searchbox_region_get(const ARegion *button_region)
#define AUTOCOMPLETE_NO_MATCH
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
const uiStyle * UI_style_get()
void UI_fontstyle_set(const uiFontStyle *fs)
#define UI_SEARCHBOX_BOUNDS
void UI_autocomplete_update_name(AutoComplete *autocpl, blender::StringRef name)
AutoComplete * UI_autocomplete_begin(const char *startname, size_t maxncpy)
void UI_but_flag_enable(uiBut *but, int flag)
void(*)(const wmRegionListenerParams *params, void *arg) uiButSearchListenFn
#define UI_SEARCHBOX_TRIA_H
#define UI_NO_ICON_OVERLAY_TEXT
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border, const IconTextOverlay *text_overlay, const bool inverted=false)
float UI_view2d_view_to_region_y(const View2D *v2d, float y)
void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst) ATTR_NONNULL()
BMesh const char void * data
void reset()
clear internal cached data and reset random seed
IndexRange index_range() const
void copy_utf8_truncated(char *dst, int64_t dst_size) const
constexpr StringRef drop_prefix(int64_t n) const
static bool is_inside(int x, int y, int cols, int rows)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
int ui_but_string_get_maxncpy(uiBut *but)
void ui_fontscale(float *points, float aspect)
void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
#define UI_POPUP_MENU_TOP
void ui_draw_preview_item(const uiFontStyle *fstyle, rcti *rect, float zoom, const char *name, int iconid, int but_flag, eFontStyle_Align text_align)
void ui_draw_widget_menu_back(const rcti *rect, bool use_shadow)
void ui_draw_menu_item(const uiFontStyle *fstyle, rcti *rect, rcti *back_rect, float zoom, bool use_unpadded, const char *name, int iconid, int but_flag, uiMenuItemSeparatorType separator_type, int *r_xmax)
@ UI_MENU_ITEM_SEPARATOR_NONE
@ UI_MENU_ITEM_SEPARATOR_HINT
@ UI_MENU_ITEM_SEPARATOR_SHORTCUT
static void ui_searchbox_draw_clip_tri_up(rcti *rect, const float zoom)
int ui_searchbox_find_index(ARegion *region, const char *name)
void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool reset)
static void str_tolower_titlecaps_ascii(char *str, const size_t len)
static ARegion * ui_searchbox_create_generic_ex(bContext *C, ARegion *butregion, uiButSearch *but, const bool use_shortcut_sep)
void ui_but_search_refresh(uiButSearch *but)
static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr)
static void ui_searchbox_select(bContext *C, ARegion *region, uiBut *but, int step)
ARegion * ui_searchbox_create_operator(bContext *C, ARegion *butregion, uiButSearch *search_but)
ARegion * ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearch *search_but)
ARegion * ui_searchbox_create_menu(bContext *C, ARegion *butregion, uiButSearch *search_but)
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn, void *arg)
void ui_searchbox_free(bContext *C, ARegion *region)
static void ui_searchbox_update_fn(bContext *C, uiButSearch *but, const char *str, uiSearchItems *items)
int UI_searchbox_size_x()
bool ui_searchbox_apply(uiBut *but, ARegion *region)
static void ui_searchbox_region_draw_fn(const bContext *C, ARegion *region)
static int ui_searchbox_size_x_from_items(const uiSearchItems &items)
int UI_search_items_find_index(const uiSearchItems *items, const char *name)
int UI_searchbox_size_y()
static void ui_searchbox_region_draw_cb__menu(const bContext *, ARegion *)
static void ui_searchbox_region_layout_fn(const bContext *C, ARegion *region)
bool ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event)
static void ui_searchbox_draw_clip_tri_down(rcti *rect, const float zoom)
static ARegion * wm_searchbox_tooltip_init(bContext *C, ARegion *region, int *, double *, bool *r_exit_on_event)
static void ui_searchbox_region_draw_cb__operator(const bContext *, ARegion *region)
static void ui_searchbox_region_free_fn(ARegion *region)
bool ui_searchbox_inside(ARegion *region, const int xy[2])
bool UI_search_item_add(uiSearchItems *items, const StringRef name, void *poin, int iconid, const int but_flag, const uint8_t name_prefix_offset)
int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *str)
static void ui_searchbox_region_listen_fn(const wmRegionListenerParams *params)
ARegion * ui_region_temp_add(bScreen *screen)
void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
PropertyType RNA_property_type(PropertyRNA *prop)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* layout)(const bContext *C, ARegion *region)
ARegionRuntimeHandle * runtime
uiButSearchUpdateFn items_update_fn
bool results_are_suggestions
uiButSearchListenFn listen_fn
const char * item_sep_string
uiButSearchTooltipFn item_tooltip_fn
uiButSearchContextMenuFn item_context_menu_fn
uint8_t * name_prefix_offsets
uiButSearchListenFn search_listener
void wmOrtho2_region_pixelspace(const ARegion *region)
int WM_window_native_pixel_x(const wmWindow *win)