Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-04-03 00:17:48 +0300
committerHans Goudey <h.goudey@me.com>2022-04-03 00:17:48 +0300
commit4537eb0c3b1678a623510570fb7528bf53174b2f (patch)
tree6d91005449c641b5116cbbf96780159e540b13a1 /source/blender/editors/interface/interface_utils.c
parent351c00d29ab1d41867bfbae77b92625e5bf442e6 (diff)
Cleanup: Remove interface region files to C++
Moves all `interface_region*` files to C++ except for the tooptip region which is slightly more complicated. Also move a few other files as well. This helps to simplify and speed up code, especially through the use of better C++ data structures. This change builds on all platforms on the buildbot.
Diffstat (limited to 'source/blender/editors/interface/interface_utils.c')
-rw-r--r--source/blender/editors/interface/interface_utils.c1014
1 files changed, 0 insertions, 1014 deletions
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
deleted file mode 100644
index 728d42a9353..00000000000
--- a/source/blender/editors/interface/interface_utils.c
+++ /dev/null
@@ -1,1014 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright 2009 Blender Foundation. All rights reserved. */
-
-/** \file
- * \ingroup edinterface
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "DNA_object_types.h"
-#include "DNA_screen_types.h"
-
-#include "ED_screen.h"
-
-#include "BLI_alloca.h"
-#include "BLI_listbase.h"
-#include "BLI_math.h"
-#include "BLI_string.h"
-#include "BLI_string_search.h"
-#include "BLI_utildefines.h"
-
-#include "BLT_translation.h"
-
-#include "BKE_context.h"
-#include "BKE_lib_id.h"
-#include "BKE_report.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "RNA_access.h"
-
-#include "UI_interface.h"
-#include "UI_interface_icons.h"
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "interface_intern.h"
-
-/*************************** RNA Utilities ******************************/
-
-uiBut *uiDefAutoButR(uiBlock *block,
- PointerRNA *ptr,
- PropertyRNA *prop,
- int index,
- const char *name,
- int icon,
- int x,
- int y,
- int width,
- int height)
-{
- uiBut *but = NULL;
-
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN: {
- if (RNA_property_array_check(prop) && index == -1) {
- return NULL;
- }
-
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else {
- but = uiDefButR_prop(block,
- UI_BTYPE_CHECKBOX,
- 0,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- break;
- }
- case PROP_INT:
- case PROP_FLOAT: {
- if (RNA_property_array_check(prop) && index == -1) {
- if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) {
- but = uiDefButR_prop(block,
- UI_BTYPE_COLOR,
- 0,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- }
- else {
- return NULL;
- }
- }
- else if (RNA_property_subtype(prop) == PROP_PERCENTAGE ||
- RNA_property_subtype(prop) == PROP_FACTOR) {
- but = uiDefButR_prop(block,
- UI_BTYPE_NUM_SLIDER,
- 0,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else {
- but = uiDefButR_prop(
- block, UI_BTYPE_NUM, 0, name, x, y, width, height, ptr, prop, index, 0, 0, 0, 0, NULL);
- }
-
- if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
- UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
- }
- break;
- }
- case PROP_ENUM:
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block,
- UI_BTYPE_MENU,
- 0,
- icon,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_MENU,
- 0,
- icon,
- NULL,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else {
- but = uiDefButR_prop(block,
- UI_BTYPE_MENU,
- 0,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- break;
- case PROP_STRING:
- if (icon && name && name[0] == '\0') {
- but = uiDefIconButR_prop(block,
- UI_BTYPE_TEXT,
- 0,
- icon,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else if (icon) {
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_TEXT,
- 0,
- icon,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
- else {
- but = uiDefButR_prop(block,
- UI_BTYPE_TEXT,
- 0,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- }
-
- if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
- /* TEXTEDIT_UPDATE is usually used for search buttons. For these we also want
- * the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
- UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE | UI_BUT_VALUE_CLEAR);
- }
- break;
- case PROP_POINTER: {
- if (icon == 0) {
- const PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
- icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
- }
- if (icon == ICON_DOT) {
- icon = 0;
- }
-
- but = uiDefIconTextButR_prop(block,
- UI_BTYPE_SEARCH_MENU,
- 0,
- icon,
- name,
- x,
- y,
- width,
- height,
- ptr,
- prop,
- index,
- 0,
- 0,
- -1,
- -1,
- NULL);
- ui_but_add_search(but, ptr, prop, NULL, NULL);
- break;
- }
- case PROP_COLLECTION: {
- char text[256];
- BLI_snprintf(
- text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x, y, width, height, NULL, 0, 0, 0, 0, NULL);
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- break;
- }
- default:
- but = NULL;
- break;
- }
-
- return but;
-}
-
-void uiDefAutoButsArrayR(uiBlock *block,
- PointerRNA *ptr,
- PropertyRNA *prop,
- const int icon,
- const int x,
- const int y,
- const int tot_width,
- const int height)
-{
- const int len = RNA_property_array_length(ptr, prop);
- if (len == 0) {
- return;
- }
-
- const int item_width = tot_width / len;
-
- UI_block_align_begin(block);
- for (int i = 0; i < len; i++) {
- uiDefAutoButR(block, ptr, prop, i, "", icon, x + i * item_width, y, item_width, height);
- }
- UI_block_align_end(block);
-}
-
-eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
- PointerRNA *ptr,
- bool (*check_prop)(PointerRNA *ptr,
- PropertyRNA *prop,
- void *user_data),
- void *user_data,
- PropertyRNA *prop_activate_init,
- const eButLabelAlign label_align,
- const bool compact)
-{
- eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
- uiLayout *col;
- const char *name;
-
- RNA_STRUCT_BEGIN (ptr, prop) {
- const int flag = RNA_property_flag(prop);
-
- if (flag & PROP_HIDDEN) {
- continue;
- }
- if (check_prop && check_prop(ptr, prop, user_data) == 0) {
- return_info |= UI_PROP_BUTS_ANY_FAILED_CHECK;
- continue;
- }
-
- const PropertyType type = RNA_property_type(prop);
- switch (label_align) {
- case UI_BUT_LABEL_ALIGN_COLUMN:
- case UI_BUT_LABEL_ALIGN_SPLIT_COLUMN: {
- const bool is_boolean = (type == PROP_BOOLEAN && !RNA_property_array_check(prop));
-
- name = RNA_property_ui_name(prop);
-
- if (label_align == UI_BUT_LABEL_ALIGN_COLUMN) {
- col = uiLayoutColumn(layout, true);
-
- if (!is_boolean) {
- uiItemL(col, name, ICON_NONE);
- }
- }
- else {
- BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN);
- col = uiLayoutColumn(layout, true);
- /* Let uiItemFullR() create the split layout. */
- uiLayoutSetPropSep(col, true);
- }
-
- break;
- }
- case UI_BUT_LABEL_ALIGN_NONE:
- default:
- col = layout;
- name = NULL; /* no smart label alignment, show default name with button */
- break;
- }
-
- /* Only buttons that can be edited as text. */
- const bool use_activate_init = ((prop == prop_activate_init) &&
- (ELEM(type, PROP_STRING, PROP_INT, PROP_FLOAT)));
-
- if (use_activate_init) {
- uiLayoutSetActivateInit(col, true);
- }
-
- uiItemFullR(col, ptr, prop, -1, 0, compact ? UI_ITEM_R_COMPACT : 0, name, ICON_NONE);
- return_info &= ~UI_PROP_BUTS_NONE_ADDED;
-
- if (use_activate_init) {
- uiLayoutSetActivateInit(col, false);
- }
- }
- RNA_STRUCT_END;
-
- return return_info;
-}
-
-/* *** RNA collection search menu *** */
-
-typedef struct CollItemSearch {
- struct CollItemSearch *next, *prev;
- void *data;
- char *name;
- int index;
- int iconid;
- bool is_id;
- int name_prefix_offset;
- uint has_sep_char : 1;
-} CollItemSearch;
-
-static bool add_collection_search_item(CollItemSearch *cis,
- const bool requires_exact_data_name,
- const bool has_id_icon,
- uiSearchItems *items)
-{
- char name_buf[UI_MAX_DRAW_STR];
-
- /* If no item has an own icon to display, libraries can use the library icons rather than the
- * name prefix for showing the library status. */
- int name_prefix_offset = cis->name_prefix_offset;
- if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
- cis->iconid = UI_icon_from_library(cis->data);
- /* No need to re-allocate, string should be shorter than before (lib status prefix is
- * removed). */
- BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR, &name_prefix_offset);
- BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
- strcpy(cis->name, name_buf);
- }
-
- return UI_search_item_add(items,
- cis->name,
- cis->data,
- cis->iconid,
- cis->has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0,
- name_prefix_offset);
-}
-
-void ui_rna_collection_search_update_fn(const struct bContext *C,
- void *arg,
- const char *str,
- uiSearchItems *items,
- const bool is_first)
-{
- uiRNACollectionSearch *data = arg;
- const int flag = RNA_property_flag(data->target_prop);
- ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
- const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER);
- /* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to
- * match the RNA name exactly. So only for pointer properties, the name can be modified to add
- * further UI hints. */
- const bool requires_exact_data_name = !is_ptr_target;
- const bool skip_filter = is_first;
- char name_buf[UI_MAX_DRAW_STR];
- char *name;
- bool has_id_icon = false;
-
- StringSearch *search = skip_filter ? NULL : BLI_string_search_new();
-
- /* build a temporary list of relevant items first */
- int item_index = 0;
- RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
-
- if (flag & PROP_ID_SELF_CHECK) {
- if (itemptr.data == data->target_ptr.owner_id) {
- continue;
- }
- }
-
- /* use filter */
- if (is_ptr_target) {
- if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0) {
- continue;
- }
- }
-
- int name_prefix_offset = 0;
- int iconid = ICON_NONE;
- bool has_sep_char = false;
- const bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
-
- if (is_id) {
- iconid = ui_id_icon_get(C, itemptr.data, false);
- if (!ELEM(iconid, 0, ICON_BLANK1)) {
- has_id_icon = true;
- }
-
- if (requires_exact_data_name) {
- name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
- }
- else {
- const ID *id = itemptr.data;
- BKE_id_full_name_ui_prefix_get(
- name_buf, itemptr.data, true, UI_SEP_CHAR, &name_prefix_offset);
- BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI,
- "Name string buffer should be big enough to hold full UI ID name");
- name = name_buf;
- has_sep_char = ID_IS_LINKED(id);
- }
- }
- else {
- name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
- }
-
- if (name) {
- CollItemSearch *cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
- cis->data = itemptr.data;
- cis->name = BLI_strdup(name);
- cis->index = item_index;
- cis->iconid = iconid;
- cis->is_id = is_id;
- cis->name_prefix_offset = name_prefix_offset;
- cis->has_sep_char = has_sep_char;
- if (!skip_filter) {
- BLI_string_search_add(search, name, cis, 0);
- }
- BLI_addtail(items_list, cis);
- if (name != name_buf) {
- MEM_freeN(name);
- }
- }
-
- item_index++;
- }
- RNA_PROP_END;
-
- if (skip_filter) {
- LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
- if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
- break;
- }
- }
- }
- else {
- CollItemSearch **filtered_items;
- int filtered_amount = BLI_string_search_query(search, str, (void ***)&filtered_items);
-
- for (int i = 0; i < filtered_amount; i++) {
- CollItemSearch *cis = filtered_items[i];
- if (!add_collection_search_item(cis, requires_exact_data_name, has_id_icon, items)) {
- break;
- }
- }
-
- MEM_freeN(filtered_items);
- BLI_string_search_free(search);
- }
-
- LISTBASE_FOREACH (CollItemSearch *, cis, items_list) {
- MEM_freeN(cis->name);
- }
- BLI_freelistN(items_list);
- MEM_freeN(items_list);
-}
-
-int UI_icon_from_id(const ID *id)
-{
- if (id == NULL) {
- return ICON_NONE;
- }
-
- /* exception for objects */
- if (GS(id->name) == ID_OB) {
- Object *ob = (Object *)id;
-
- if (ob->type == OB_EMPTY) {
- return ICON_EMPTY_DATA;
- }
- return UI_icon_from_id(ob->data);
- }
-
- /* otherwise get it through RNA, creating the pointer
- * will set the right type, also with subclassing */
- PointerRNA ptr;
- RNA_id_pointer_create((ID *)id, &ptr);
-
- return (ptr.type) ? RNA_struct_ui_icon(ptr.type) : ICON_NONE;
-}
-
-int UI_icon_from_report_type(int type)
-{
- if (type & RPT_ERROR_ALL) {
- return ICON_CANCEL;
- }
- if (type & RPT_WARNING_ALL) {
- return ICON_ERROR;
- }
- if (type & RPT_INFO_ALL) {
- return ICON_INFO;
- }
- if (type & RPT_DEBUG_ALL) {
- return ICON_SYSTEM;
- }
- if (type & RPT_PROPERTY) {
- return ICON_OPTIONS;
- }
- if (type & RPT_OPERATOR) {
- return ICON_CHECKMARK;
- }
- return ICON_INFO;
-}
-
-int UI_icon_colorid_from_report_type(int type)
-{
- if (type & RPT_ERROR_ALL) {
- return TH_INFO_ERROR;
- }
- if (type & RPT_WARNING_ALL) {
- return TH_INFO_WARNING;
- }
- if (type & RPT_INFO_ALL) {
- return TH_INFO_INFO;
- }
- if (type & RPT_DEBUG_ALL) {
- return TH_INFO_DEBUG;
- }
- if (type & RPT_PROPERTY) {
- return TH_INFO_PROPERTY;
- }
- if (type & RPT_OPERATOR) {
- return TH_INFO_OPERATOR;
- }
- return TH_INFO_WARNING;
-}
-
-int UI_text_colorid_from_report_type(int type)
-{
- if (type & RPT_ERROR_ALL) {
- return TH_INFO_ERROR_TEXT;
- }
- if (type & RPT_WARNING_ALL) {
- return TH_INFO_WARNING_TEXT;
- }
- if (type & RPT_INFO_ALL) {
- return TH_INFO_INFO_TEXT;
- }
- if (type & RPT_DEBUG_ALL) {
- return TH_INFO_DEBUG_TEXT;
- }
- if (type & RPT_PROPERTY) {
- return TH_INFO_PROPERTY_TEXT;
- }
- if (type & RPT_OPERATOR) {
- return TH_INFO_OPERATOR_TEXT;
- }
- return TH_INFO_WARNING_TEXT;
-}
-
-/********************************** Misc **************************************/
-
-int UI_calc_float_precision(int prec, double value)
-{
- static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {
- 1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6};
- static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */
-
- BLI_assert(prec <= UI_PRECISION_FLOAT_MAX);
- BLI_assert(fabs(pow10_neg[prec] - pow(10, -prec)) < 1e-16);
-
- /* Check on the number of decimal places need to display the number,
- * this is so 0.00001 is not displayed as 0.00,
- * _but_, this is only for small values as 10.0001 will not get the same treatment.
- */
- value = fabs(value);
- if ((value < pow10_neg[prec]) && (value > (1.0 / max_pow))) {
- int value_i = (int)((value * max_pow) + 0.5);
- if (value_i != 0) {
- const int prec_span = 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */
- int test_prec;
- int prec_min = -1;
- int dec_flag = 0;
- int i = UI_PRECISION_FLOAT_MAX;
- while (i && value_i) {
- if (value_i % 10) {
- dec_flag |= 1 << i;
- prec_min = i;
- }
- value_i /= 10;
- i--;
- }
-
- /* even though its a small value, if the second last digit is not 0, use it */
- test_prec = prec_min;
-
- dec_flag = (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1);
-
- while (dec_flag) {
- test_prec++;
- dec_flag = dec_flag >> 1;
- }
-
- if (test_prec > prec) {
- prec = test_prec;
- }
- }
- }
-
- CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX);
-
- return prec;
-}
-
-bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
-{
- if (but->rnapoin.owner_id && but->rnapoin.data && but->rnaprop) {
- BLI_snprintf(r_str,
- maxlength,
- "%s.%s",
- RNA_struct_identifier(but->rnapoin.type),
- RNA_property_identifier(but->rnaprop));
- return true;
- }
- if (but->optype) {
- WM_operator_py_idname(r_str, but->optype->idname);
- return true;
- }
-
- *r_str = '\0';
- return false;
-}
-
-bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength)
-{
- uiBut *but = UI_context_active_but_get(C);
-
- if (but) {
- return UI_but_online_manual_id(but, r_str, maxlength);
- }
-
- *r_str = '\0';
- return false;
-}
-
-/* -------------------------------------------------------------------- */
-
-static rctf ui_but_rect_to_view(const uiBut *but, const ARegion *region, const View2D *v2d)
-{
- rctf region_rect;
- ui_block_to_region_rctf(region, but->block, &region_rect, &but->rect);
-
- rctf view_rect;
- UI_view2d_region_to_view_rctf(v2d, &region_rect, &view_rect);
-
- return view_rect;
-}
-
-/**
- * To get a margin (typically wanted), add the margin to \a rect directly.
- *
- * Based on #file_ensure_inside_viewbounds(), could probably share code.
- *
- * \return true if anything changed.
- */
-static bool ui_view2d_cur_ensure_rect_in_view(View2D *v2d, const rctf *rect)
-{
- const float rect_width = BLI_rctf_size_x(rect);
- const float rect_height = BLI_rctf_size_y(rect);
-
- rctf *cur = &v2d->cur;
- const float cur_width = BLI_rctf_size_x(cur);
- const float cur_height = BLI_rctf_size_y(cur);
-
- bool changed = false;
-
- /* Snap to bottom edge. Also use if rect is higher than view bounds (could be a parameter). */
- if ((cur->ymin > rect->ymin) || (rect_height > cur_height)) {
- cur->ymin = rect->ymin;
- cur->ymax = cur->ymin + cur_height;
- changed = true;
- }
- /* Snap to upper edge. */
- else if (cur->ymax < rect->ymax) {
- cur->ymax = rect->ymax;
- cur->ymin = cur->ymax - cur_height;
- changed = true;
- }
- /* Snap to left edge. Also use if rect is wider than view bounds. */
- else if ((cur->xmin > rect->xmin) || (rect_width > cur_width)) {
- cur->xmin = rect->xmin;
- cur->xmax = cur->xmin + cur_width;
- changed = true;
- }
- /* Snap to right edge. */
- else if (cur->xmax < rect->xmax) {
- cur->xmax = rect->xmax;
- cur->xmin = cur->xmax - cur_width;
- changed = true;
- }
- else {
- BLI_assert(BLI_rctf_inside_rctf(cur, rect));
- }
-
- return changed;
-}
-
-void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but)
-{
- View2D *v2d = &region->v2d;
- /* Uninitialized view or region that doesn't use View2D. */
- if ((v2d->flag & V2D_IS_INIT) == 0) {
- return;
- }
-
- rctf rect = ui_but_rect_to_view(but, region, v2d);
-
- const int margin = UI_UNIT_X * 0.5f;
- BLI_rctf_pad(&rect, margin, margin);
-
- const bool changed = ui_view2d_cur_ensure_rect_in_view(v2d, &rect);
- if (changed) {
- UI_view2d_curRect_changed(C, v2d);
- ED_region_tag_redraw_no_rebuild(region);
- }
-}
-
-/* -------------------------------------------------------------------- */
-/** \name Button Store
- *
- * Modal Button Store API.
- *
- * Store for modal operators & handlers to register button pointers
- * which are maintained while drawing or NULL when removed.
- *
- * This is needed since button pointers are continuously freed and re-allocated.
- *
- * \{ */
-
-struct uiButStore {
- struct uiButStore *next, *prev;
- uiBlock *block;
- ListBase items;
-};
-
-struct uiButStoreElem {
- struct uiButStoreElem *next, *prev;
- uiBut **but_p;
-};
-
-uiButStore *UI_butstore_create(uiBlock *block)
-{
- uiButStore *bs_handle = MEM_callocN(sizeof(uiButStore), __func__);
-
- bs_handle->block = block;
- BLI_addtail(&block->butstore, bs_handle);
-
- return bs_handle;
-}
-
-void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
-{
- /* Workaround for button store being moved into new block,
- * which then can't use the previous buttons state
- * ('ui_but_update_from_old_block' fails to find a match),
- * keeping the active button in the old block holding a reference
- * to the button-state in the new block: see T49034.
- *
- * Ideally we would manage moving the 'uiButStore', keeping a correct state.
- * All things considered this is the most straightforward fix - Campbell.
- */
- if (block != bs_handle->block && bs_handle->block != NULL) {
- block = bs_handle->block;
- }
-
- BLI_freelistN(&bs_handle->items);
- BLI_assert(BLI_findindex(&block->butstore, bs_handle) != -1);
- BLI_remlink(&block->butstore, bs_handle);
-
- MEM_freeN(bs_handle);
-}
-
-bool UI_butstore_is_valid(uiButStore *bs)
-{
- return (bs->block != NULL);
-}
-
-bool UI_butstore_is_registered(uiBlock *block, uiBut *but)
-{
- LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
- if (*bs_elem->but_p == but) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p)
-{
- uiButStoreElem *bs_elem = MEM_callocN(sizeof(uiButStoreElem), __func__);
- BLI_assert(*but_p);
- bs_elem->but_p = but_p;
-
- BLI_addtail(&bs_handle->items, bs_elem);
-}
-
-void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p)
-{
- LISTBASE_FOREACH_MUTABLE (uiButStoreElem *, bs_elem, &bs_handle->items) {
- if (bs_elem->but_p == but_p) {
- BLI_remlink(&bs_handle->items, bs_elem);
- MEM_freeN(bs_elem);
- }
- }
-
- BLI_assert(0);
-}
-
-bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src)
-{
- bool found = false;
-
- LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
- if (*bs_elem->but_p == but_src) {
- *bs_elem->but_p = but_dst;
- found = true;
- }
- }
- }
-
- return found;
-}
-
-void UI_butstore_clear(uiBlock *block)
-{
- LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- bs_handle->block = NULL;
- LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
- *bs_elem->but_p = NULL;
- }
- }
-}
-
-void UI_butstore_update(uiBlock *block)
-{
- /* move this list to the new block */
- if (block->oldblock) {
- if (block->oldblock->butstore.first) {
- BLI_movelisttolist(&block->butstore, &block->oldblock->butstore);
- }
- }
-
- if (LIKELY(block->butstore.first == NULL)) {
- return;
- }
-
- /* warning, loop-in-loop, in practice we only store <10 buttons at a time,
- * so this isn't going to be a problem, if that changes old-new mapping can be cached first */
- LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- BLI_assert(ELEM(bs_handle->block, NULL, block) ||
- (block->oldblock && block->oldblock == bs_handle->block));
-
- if (bs_handle->block == block->oldblock) {
- bs_handle->block = block;
-
- LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
- if (*bs_elem->but_p) {
- uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
-
- /* can be NULL if the buttons removed,
- * NOTE: we could allow passing in a callback when buttons are removed
- * so the caller can cleanup */
- *bs_elem->but_p = but_new;
- }
- }
- }
- }
-}
-
-/** \} */