Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_layout.c
| Show First 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
| /* uiLayoutRoot */ | /* uiLayoutRoot */ | ||||
| typedef struct uiLayoutRoot { | typedef struct uiLayoutRoot { | ||||
| struct uiLayoutRoot *next, *prev; | struct uiLayoutRoot *next, *prev; | ||||
| int type; | int type; | ||||
| int opcontext; | int opcontext; | ||||
| /** | |||||
| * If true, the root will be removed as part of the property search process. | |||||
| * Necessary for cases like searching the contents of closed panels, where the | |||||
| * block-level tag isn't enough, as there might be visible buttons in the header. | |||||
| */ | |||||
| bool search_only; | |||||
| int emw, emh; | int emw, emh; | ||||
| int padding; | int padding; | ||||
| uiMenuHandleFunc handlefunc; | uiMenuHandleFunc handlefunc; | ||||
| void *argv; | void *argv; | ||||
| const uiStyle *style; | const uiStyle *style; | ||||
| uiBlock *block; | uiBlock *block; | ||||
| ▲ Show 20 Lines • Show All 1,878 Lines • ▼ Show 20 Lines | struct { | ||||
| uiLayout *layout; | uiLayout *layout; | ||||
| uiBut *but; | uiBut *but; | ||||
| } ui_decorate = { | } ui_decorate = { | ||||
| .use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) && use_prop_sep), | .use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) && use_prop_sep), | ||||
| }; | }; | ||||
| #endif /* UI_PROP_DECORATE */ | #endif /* UI_PROP_DECORATE */ | ||||
| UI_block_layout_set_current(block, layout); | UI_block_layout_set_current(block, layout); | ||||
| ui_block_new_button_group(block); | ui_block_new_button_group(block, 0); | ||||
| /* retrieve info */ | /* retrieve info */ | ||||
| const PropertyType type = RNA_property_type(prop); | const PropertyType type = RNA_property_type(prop); | ||||
| const bool is_array = RNA_property_array_check(prop); | const bool is_array = RNA_property_array_check(prop); | ||||
| const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; | const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; | ||||
| const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; | const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; | ||||
| ▲ Show 20 Lines • Show All 721 Lines • ▼ Show 20 Lines | void uiItemPointerR_prop(uiLayout *layout, | ||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||
| PointerRNA *searchptr, | PointerRNA *searchptr, | ||||
| PropertyRNA *searchprop, | PropertyRNA *searchprop, | ||||
| const char *name, | const char *name, | ||||
| int icon) | int icon) | ||||
| { | { | ||||
| const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); | const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); | ||||
| ui_block_new_button_group(uiLayoutGetBlock(layout)); | ui_block_new_button_group(uiLayoutGetBlock(layout), 0); | ||||
| const PropertyType type = RNA_property_type(prop); | const PropertyType type = RNA_property_type(prop); | ||||
| if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { | if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { | ||||
| RNA_warning("Property %s.%s must be a pointer, string or enum", | RNA_warning("Property %s.%s must be a pointer, string or enum", | ||||
| RNA_struct_identifier(ptr->type), | RNA_struct_identifier(ptr->type), | ||||
| RNA_property_identifier(prop)); | RNA_property_identifier(prop)); | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | static uiBut *ui_item_menu(uiLayout *layout, | ||||
| void *argN, | void *argN, | ||||
| const char *tip, | const char *tip, | ||||
| bool force_menu) | bool force_menu) | ||||
| { | { | ||||
| uiBlock *block = layout->root->block; | uiBlock *block = layout->root->block; | ||||
| uiLayout *heading_layout = ui_layout_heading_find(layout); | uiLayout *heading_layout = ui_layout_heading_find(layout); | ||||
| UI_block_layout_set_current(block, layout); | UI_block_layout_set_current(block, layout); | ||||
| ui_block_new_button_group(block); | ui_block_new_button_group(block, 0); | ||||
| if (!name) { | if (!name) { | ||||
| name = ""; | name = ""; | ||||
| } | } | ||||
| if (layout->root->type == UI_LAYOUT_MENU && !icon) { | if (layout->root->type == UI_LAYOUT_MENU && !icon) { | ||||
| icon = ICON_BLANK1; | icon = ICON_BLANK1; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /* label item */ | /* label item */ | ||||
| static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) | static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) | ||||
| { | { | ||||
| uiBlock *block = layout->root->block; | uiBlock *block = layout->root->block; | ||||
| UI_block_layout_set_current(block, layout); | UI_block_layout_set_current(block, layout); | ||||
| ui_block_new_button_group(block); | ui_block_new_button_group(block, 0); | ||||
| if (!name) { | if (!name) { | ||||
| name = ""; | name = ""; | ||||
| } | } | ||||
| if (layout->root->type == UI_LAYOUT_MENU && !icon) { | if (layout->root->type == UI_LAYOUT_MENU && !icon) { | ||||
| icon = ICON_BLANK1; | icon = ICON_BLANK1; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,903 Lines • ▼ Show 20 Lines | |||||
| int uiLayoutGetEmboss(uiLayout *layout) | int uiLayoutGetEmboss(uiLayout *layout) | ||||
| { | { | ||||
| if (layout->emboss == UI_EMBOSS_UNDEFINED) { | if (layout->emboss == UI_EMBOSS_UNDEFINED) { | ||||
| return layout->root->block->emboss; | return layout->root->block->emboss; | ||||
| } | } | ||||
| return layout->emboss; | return layout->emboss; | ||||
| } | } | ||||
| /** | |||||
| * Tags the layout root as search only, meaning the search process will run, but not the rest of | |||||
| * the layout process. Use in situations where part of the block's contents normally wouldn't be | |||||
| * drawn, but must be searched anyway, like the contents of closed panels with headers. | |||||
| */ | |||||
| void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only) | |||||
| { | |||||
| layout->root->search_only = search_only; | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Block Layout Search Filtering | /** \name Block Layout Search Filtering | ||||
| * \{ */ | * \{ */ | ||||
| /* Disabled for performance reasons, but this could be turned on in the future. */ | /* Disabled for performance reasons, but this could be turned on in the future. */ | ||||
| // #define PROPERTY_SEARCH_USE_TOOLTIPS | // #define PROPERTY_SEARCH_USE_TOOLTIPS | ||||
| static bool block_search_panel_label_matches(const uiBlock *block, const char *search_string) | static bool block_search_panel_label_matches(const uiBlock *block, const char *search_string) | ||||
| { | { | ||||
| if ((block->panel != NULL) && (block->panel->type != NULL)) { | if ((block->panel != NULL) && (block->panel->type != NULL)) { | ||||
| if (BLI_strcasestr(block->panel->type->label, search_string)) { | if (BLI_strcasestr(block->panel->type->label, search_string)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /** | /** | ||||
| * Buttons for search only layouts (closed panel sub-panels) have still been added from the | |||||
| * layout functions, but they need to be hidden. Theoretically they could be removed too. | |||||
| */ | |||||
| static void layout_free_and_hide_buttons(uiLayout *layout) | |||||
| { | |||||
| LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) { | |||||
| if (item->type == ITEM_BUTTON) { | |||||
| uiButtonItem *button_item = (uiButtonItem *)item; | |||||
| BLI_assert(button_item->but != NULL); | |||||
| button_item->but->flag |= UI_HIDDEN; | |||||
| MEM_freeN(item); | |||||
| } | |||||
| else { | |||||
| layout_free_and_hide_buttons((uiLayout *)item); | |||||
| } | |||||
| } | |||||
| MEM_freeN(layout); | |||||
| } | |||||
| /** | |||||
| * Remove layouts used only for search and hide their buttons. | |||||
| * (See comment for #uiLayoutRootSetSearchOnly and in #uiLayoutRoot). | |||||
| */ | |||||
| static void block_search_remove_search_only_roots(uiBlock *block) | |||||
| { | |||||
| LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) { | |||||
| if (root->search_only) { | |||||
| layout_free_and_hide_buttons(root->layout); | |||||
| BLI_remlink(&block->layouts, root); | |||||
| MEM_freeN(root); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Returns true if a button or the data / operator it represents matches the search filter. | * Returns true if a button or the data / operator it represents matches the search filter. | ||||
| */ | */ | ||||
| static bool button_matches_search_filter(uiBut *but, const char *search_filter) | static bool button_matches_search_filter(uiBut *but, const char *search_filter) | ||||
| { | { | ||||
| /* Do the shorter checks first for better performance in case there is a match. */ | /* Do the shorter checks first for better performance in case there is a match. */ | ||||
| if (BLI_strcasestr(but->str, search_filter)) { | if (BLI_strcasestr(but->str, search_filter)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter) | ||||
| } | } | ||||
| const bool panel_label_matches = block_search_panel_label_matches(block, search_filter); | const bool panel_label_matches = block_search_panel_label_matches(block, search_filter); | ||||
| const bool has_result = (panel_label_matches) ? | const bool has_result = (panel_label_matches) ? | ||||
| true : | true : | ||||
| block_search_filter_tag_buttons(block, search_filter); | block_search_filter_tag_buttons(block, search_filter); | ||||
| block_search_remove_search_only_roots(block); | |||||
| if (block->panel != NULL) { | if (block->panel != NULL) { | ||||
| if (has_result) { | if (has_result) { | ||||
| ui_panel_tag_search_filter_match(block->panel); | ui_panel_tag_search_filter_match(block->panel); | ||||
| } | } | ||||
| } | } | ||||
| return has_result; | return has_result; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 426 Lines • ▼ Show 20 Lines | void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y) | ||||
| } | } | ||||
| if (r_y) { | if (r_y) { | ||||
| *r_y = 0; | *r_y = 0; | ||||
| } | } | ||||
| block->curlayout = NULL; | block->curlayout = NULL; | ||||
| LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) { | LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) { | ||||
| /* Search only roots should be removed by #UI_block_apply_search_filter. */ | |||||
| BLI_assert(!root->search_only); | |||||
| ui_layout_add_padding_button(root); | ui_layout_add_padding_button(root); | ||||
| /* NULL in advance so we don't interfere when adding button */ | /* NULL in advance so we don't interfere when adding button */ | ||||
| ui_layout_end(block, root->layout, r_x, r_y); | ui_layout_end(block, root->layout, r_x, r_y); | ||||
| ui_layout_free(root->layout); | ui_layout_free(root->layout); | ||||
| MEM_freeN(root); | MEM_freeN(root); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 303 Lines • Show Last 20 Lines | |||||