Blender V5.0
interface_templates.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BKE_library.hh"
10#include "BKE_screen.hh"
11
12#include "BLI_math_color.h"
13#include "BLI_string_ref.hh"
14
15#include "ED_fileselect.hh"
16#include "ED_screen.hh"
17
18#include "RNA_access.hh"
19
21#include "interface_intern.hh"
23
25
26/* -------------------------------------------------------------------- */
29
31{
32 char str[UI_MAX_DRAW_STR];
33 int buf_len = 0;
34
36
37 const char *name = RNA_property_string_get_alloc(ptr, name_prop, str, sizeof(str), &buf_len);
38
39 const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
40 const int margin = UI_UNIT_X * 0.75f;
41 const int estimated_width = UI_fontstyle_string_width(fstyle, name) + margin;
42
43 if (name != str) {
45 }
46
47 /* Clamp to some min/max width. */
48 return std::clamp(
50}
51
56
58 uiLayout *layout,
59 uiBlock *block,
61 PropertyRNA *prop,
62 uiBlockCreateFunc block_func,
63 void *block_argN,
64 const std::optional<blender::StringRef> tip,
65 const bool use_previews,
66 const bool editable,
67 const bool live_icon,
68 uiButArgNFree func_argN_free_fn,
69 uiButArgNCopy func_argN_copy_fn)
70{
71 const PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
72 ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ?
73 static_cast<ID *>(active_ptr.data) :
74 nullptr;
75 const ID *idfrom = ptr->owner_id;
76 const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
77 uiBut *but;
78
79 if (use_previews) {
80 ARegion *region = CTX_wm_region(C);
81 /* Ugly tool header exception. */
82 const bool use_big_size = (region->regiontype != RGN_TYPE_TOOL_HEADER);
83 /* Ugly exception for screens here,
84 * drawing their preview in icon size looks ugly/useless */
85 const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR));
86 const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f);
87 const short height = UI_UNIT_Y * (use_big_size ? 6 : 1);
88 uiLayout *col = nullptr;
89
90 if (use_big_size) {
91 /* Assume column layout here. To be more correct, we should check if the layout passed to
92 * template_id is a column one, but this should work well in practice. */
93 col = &layout->column(true);
94 }
95
96 but = uiDefBlockButN(block,
97 block_func,
98 block_argN,
99 "",
100 0,
101 0,
102 width,
103 height,
104 tip,
105 func_argN_free_fn,
106 func_argN_copy_fn);
107 if (use_preview_icon) {
108 const int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
110 }
111 else {
114 }
115
116 if ((idfrom && !ID_IS_EDITABLE(idfrom)) || !editable) {
118 }
119 if (use_big_size) {
120 (col ? col : layout)->row(true);
121 }
122 }
123 else {
124 but = uiDefBlockButN(block,
125 block_func,
126 block_argN,
127 "",
128 0,
129 0,
130 UI_UNIT_X * 1.6,
131 UI_UNIT_Y,
132 tip,
133 func_argN_free_fn,
134 func_argN_copy_fn);
135
136 if (live_icon) {
137 const int icon = id ? ui_id_icon_get(C, id, false) : RNA_struct_ui_icon(type);
139 }
140 else {
142 }
143 if (id) {
144 /* default dragging of icon for id browse buttons */
145 UI_but_drag_set_id(but, id);
146 }
148
149 if ((idfrom && !ID_IS_EDITABLE(idfrom)) || !editable) {
151 }
152 }
153}
154
156 ARegion *region,
157 uiButSearchUpdateFn search_update_fn,
158 void *search_arg,
159 uiButHandleFunc search_exec_fn,
160 void *active_item,
161 uiButSearchTooltipFn item_tooltip_fn,
162 const int preview_rows,
163 const int preview_cols,
164 float scale)
165{
166 static char search[256];
167 wmWindow *win = CTX_wm_window(C);
168 uiBut *but;
169
170 /* clear initial search string, then all items show */
171 search[0] = 0;
172
173 uiBlock *block = UI_block_begin(C, region, "_popup", blender::ui::EmbossType::Emboss);
176
177 /* preview thumbnails */
178 if (preview_rows > 0 && preview_cols > 0) {
179 const int w = 4 * U.widget_unit * preview_cols * scale;
180 const int h = 5 * U.widget_unit * preview_rows * scale + 2 * UI_SEARCHBOX_TRIA_H -
182
183 /* fake button, it holds space for search items */
184 uiDefBut(block, ButType::Label, 0, "", 0, UI_UNIT_Y, w, h, nullptr, 0, 0, std::nullopt);
185 but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, w, UI_UNIT_Y, "");
186 UI_but_search_preview_grid_size_set(but, preview_rows, preview_cols);
187 }
188 /* list view */
189 else {
190 const int searchbox_width = UI_searchbox_size_x_guess(C, search_update_fn, search_arg);
191 const int searchbox_height = UI_searchbox_size_y();
192 const int search_but_height = UI_UNIT_Y - 1.0f * UI_SCALE_FAC;
193
194 /* fake button, it holds space for search items */
195 uiDefBut(block,
197 0,
198 "",
199 0,
200 search_but_height,
201 searchbox_width,
202 searchbox_height - UI_SEARCHBOX_BOUNDS,
203 nullptr,
204 0,
205 0,
206 std::nullopt);
207 but = uiDefSearchBut(block,
208 search,
209 0,
210 ICON_VIEWZOOM,
211 sizeof(search),
212 0,
213 0,
214 searchbox_width,
215 search_but_height,
216 "");
217 }
220 search_update_fn,
221 search_arg,
222 false,
223 nullptr,
224 search_exec_fn,
225 active_item);
226 UI_but_func_search_set_tooltip(but, item_tooltip_fn);
227
230
231 /* give search-field focus */
233 /* this type of search menu requires undo */
234 but->flag |= UI_BUT_UNDO;
235
236 return block;
237}
238
240
241/* -------------------------------------------------------------------- */
244
246{
247 uiBlock *block = layout->absolute_block();
249}
250
252
253/* -------------------------------------------------------------------- */
256
259 const StringRefNull propname,
260 PointerRNA * /*root_ptr*/,
261 const std::optional<StringRefNull> text)
262{
263 /* check that properties are valid */
264 PropertyRNA *propPath = RNA_struct_find_property(ptr, propname.c_str());
265 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
267 "path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname.c_str());
268 return;
269 }
270
271 /* Start drawing UI Elements using standard defines */
272 uiLayout *row = &layout->row(true);
273
274 /* Path (existing string) Widget */
275 row->prop(ptr, propname, UI_ITEM_NONE, text, ICON_RNA);
276
277 /* TODO: attach something to this to make allow
278 * searching of nested properties to 'build' the path */
279}
280
282
283/* -------------------------------------------------------------------- */
286
287void uiTemplateNodeSocket(uiLayout *layout, bContext * /*C*/, const float color[4])
288{
289 uiBlock *block = layout->block();
291
292 /* XXX using explicit socket colors is not quite ideal.
293 * Eventually it should be possible to use theme colors for this purpose,
294 * but this requires a better design for extendable color palettes in user preferences. */
295 uiBut *but = uiDefBut(
296 block, ButType::NodeSocket, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, nullptr, 0, 0, "");
297 rgba_float_to_uchar(but->col, color);
298
299 UI_block_align_end(block);
300}
301
302/* -------------------------------------------------------------------- */
305
307{
308 bScreen *screen = CTX_wm_screen(C);
309 SpaceFile *sfile = CTX_wm_space_file(C);
310
311 ED_file_path_button(screen, sfile, params, layout->block());
312}
313
bScreen * CTX_wm_screen(const bContext *C)
SpaceFile * CTX_wm_space_file(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
@ ID_SCR
@ RGN_TYPE_TOOL_HEADER
#define UI_SCALE_FAC
void ED_file_path_button(bScreen *screen, const SpaceFile *sfile, FileSelectParams *params, uiBlock *block)
Definition file_draw.cc:77
int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
Definition area.cc:2892
#define RNA_warning(format,...)
@ PROP_STRING
Definition RNA_types.hh:165
#define C
Definition RandGen.cpp:29
#define UI_UNIT_Y
@ UI_BLOCK_SEARCH_MENU
@ UI_BLOCK_LOOP
void UI_block_theme_style_set(uiBlock *block, char theme_style)
void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
@ UI_BUT_UNDO
@ UI_BUT_DISABLED
@ UI_BUT_ICON_PREVIEW
void UI_block_bounds_set_normal(uiBlock *block, int addval)
Definition interface.cc:637
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, bool free_arg, uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
void UI_but_drawflag_enable(uiBut *but, int flag)
void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn)
uiBut * uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxncpy, int x, int y, short width, short height, std::optional< blender::StringRef > tip)
int UI_searchbox_size_x_guess(const bContext *C, const uiButSearchUpdateFn update_fn, void *arg)
void *(*)(const void *argN) uiButArgNCopy
void(*)(void *argN) uiButArgNFree
uiBlock *(*)(bContext *C, ARegion *region, void *arg1) uiBlockCreateFunc
ARegion *(*)(bContext *C, ARegion *region, const rcti *item_rect, void *arg, void *active) uiButSearchTooltipFn
#define UI_SEARCHBOX_BOUNDS
void UI_block_align_begin(uiBlock *block)
int UI_searchbox_size_y()
int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void(*)(const bContext *C, void *arg, const char *str, uiSearchItems *items, bool is_first) uiButSearchUpdateFn
void(*)(bContext *C, void *arg1, void *arg2) uiButHandleFunc
void UI_block_direction_set(uiBlock *block, char direction)
@ UI_BLOCK_THEME_STYLE_POPUP
#define UI_FSTYLE_WIDGET
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
void UI_but_drag_set_id(uiBut *but, ID *id)
@ UI_BUT_ICON_LEFT
void UI_but_search_preview_grid_size_set(uiBut *but, int rows, int cols)
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_flag_enable(uiBut *but, int flag)
uiBut * uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, blender::StringRef str, int x, int y, short width, short height, std::optional< blender::StringRef > tip, uiButArgNFree func_argN_free_fn=MEM_freeN, uiButArgNCopy func_argN_copy_fn=MEM_dupallocN)
@ UI_DIR_DOWN
#define UI_SEARCHBOX_TRIA_H
void UI_block_align_end(uiBlock *block)
#define UI_ITEM_NONE
#define UI_MAX_DRAW_STR
#define U
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr const char * c_str() const
#define str(s)
#define GS(x)
uint col
void ui_def_but_icon(uiBut *but, const int icon, const int flag)
int ui_id_icon_get(const bContext *C, ID *id, const bool big)
ARegion * ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiButSearch *search_but)
@ UI_HAS_ICON
void template_add_button_search_menu(const bContext *C, uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, uiBlockCreateFunc block_func, void *block_argN, const std::optional< blender::StringRef > tip, const bool use_previews, const bool editable, const bool live_icon, uiButArgNFree func_argN_free_fn, uiButArgNCopy func_argN_copy_fn)
void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const StringRefNull propname, PointerRNA *, const std::optional< StringRefNull > text)
void uiTemplateNodeSocket(uiLayout *layout, bContext *, const float color[4])
void uiTemplateFileSelectPath(uiLayout *layout, bContext *C, FileSelectParams *params)
int template_search_textbut_height()
int template_search_textbut_width(PointerRNA *ptr, PropertyRNA *name_prop)
uiBlock * template_common_search_menu(const bContext *C, ARegion *region, uiButSearchUpdateFn search_update_fn, void *search_arg, uiButHandleFunc search_exec_fn, void *active_item, uiButSearchTooltipFn item_tooltip_fn, const int preview_rows, const int preview_cols, float scale)
void uiTemplateHeader(uiLayout *layout, bContext *C)
#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT
#define TEMPLATE_SEARCH_TEXTBUT_MIN_WIDTH
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
const char * name
bool RNA_struct_is_ID(const StructRNA *type)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PropertyType RNA_property_type(PropertyRNA *prop)
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_struct_identifier(const StructRNA *type)
int RNA_struct_ui_icon(const StructRNA *type)
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
uchar col[4]
uiBlock * absolute_block()
uiBlock * block() const
uiLayout & column(bool align)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
PointerRNA * ptr
Definition wm_files.cc:4238