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:
authorJulian Eisel <eiseljulian@gmail.com>2019-09-09 17:34:16 +0300
committerYimingWu <xp8110@outlook.com>2019-09-12 04:13:42 +0300
commitf8233e05f5a3bdeb0751f644d33878f37bb27199 (patch)
tree4ad4eb51694df0dbc1b1f29d5beee73524470c1b /source/blender
parentc1c27a2c399aa64ba0c59383f4e8829d82721020 (diff)
UI: Refactor and improve buttton extra icons
Without this patch there could only be one superimposed icon and the operators were hard coded for the button types. This keeps the previous, sort of predefined extra icons working in a rather generic way, but allows adding specific ones for specific case through `UI_but_extra_operator_icon_set()`. Reviewed by: Campbell Barton Differential Revision: https://developer.blender.org/D5730
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/interface/interface.c246
-rw-r--r--source/blender/editors/interface/interface_handlers.c127
-rw-r--r--source/blender/editors/interface/interface_intern.h25
-rw-r--r--source/blender/editors/interface/interface_ops.c29
-rw-r--r--source/blender/editors/interface/interface_widgets.c36
-rw-r--r--source/blender/windowmanager/WM_types.h10
7 files changed, 338 insertions, 140 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index da4097bb544..702d319817f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1598,6 +1598,11 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, void *arg);
+PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon);
+
/* Autocomplete
*
* Tab complete helper functions, for use in uiButCompleteFunc callbacks.
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 7bfd0200362..27a33a38b15 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1469,6 +1469,187 @@ void ui_but_override_flag(uiBut *but)
}
}
+/** \name Button Extra Operator Icons
+ *
+ * Extra icons are shown on the right hand side of buttons. They can be clicked to invoke custom
+ * operators.
+ * There are some predefined here, which get added to buttons automatically based on button data
+ * (type, flags, state, etc).
+ * \{ */
+
+/**
+ * Predefined types for generic extra operator icons (uiButExtraOpIcon).
+ */
+typedef enum PredefinedExtraOpIconType {
+ PREDEFINED_EXTRA_OP_ICON_NONE = 1,
+ PREDEFINED_EXTRA_OP_ICON_CLEAR,
+ PREDEFINED_EXTRA_OP_ICON_EYEDROPPER,
+} PredefinedExtraOpIconType;
+
+static PointerRNA *ui_but_extra_operator_icon_add_ptr(uiBut *but,
+ wmOperatorType *optype,
+ short opcontext,
+ int icon)
+{
+ uiButExtraOpIcon *extra_op_icon = MEM_mallocN(sizeof(*extra_op_icon), __func__);
+
+ extra_op_icon->icon = (BIFIconID)icon;
+ extra_op_icon->optype_params = MEM_callocN(sizeof(*extra_op_icon->optype_params),
+ "uiButExtraOpIcon.optype_hook");
+ extra_op_icon->optype_params->optype = optype;
+ extra_op_icon->optype_params->opptr = MEM_callocN(sizeof(*extra_op_icon->optype_params->opptr),
+ "uiButExtraOpIcon.optype_hook.opptr");
+ WM_operator_properties_create_ptr(extra_op_icon->optype_params->opptr,
+ extra_op_icon->optype_params->optype);
+ extra_op_icon->optype_params->opcontext = opcontext;
+
+ BLI_addtail(&but->extra_op_icons, extra_op_icon);
+
+ return extra_op_icon->optype_params->opptr;
+}
+
+static void ui_but_extra_operator_icon_free(uiButExtraOpIcon *extra_icon)
+{
+ WM_operator_properties_free(extra_icon->optype_params->opptr);
+ MEM_freeN(extra_icon->optype_params->opptr);
+ MEM_freeN(extra_icon->optype_params);
+ MEM_freeN(extra_icon);
+}
+
+void ui_but_extra_operator_icons_free(uiBut *but)
+{
+
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.first, *op_icon_next; op_icon;
+ op_icon = op_icon_next) {
+ op_icon_next = op_icon->next;
+ ui_but_extra_operator_icon_free(op_icon);
+ }
+ BLI_listbase_clear(&but->extra_op_icons);
+}
+
+PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
+ const char *opname,
+ short opcontext,
+ int icon)
+{
+ wmOperatorType *optype = WM_operatortype_find(opname, false);
+
+ if (optype) {
+ return ui_but_extra_operator_icon_add_ptr(but, optype, opcontext, icon);
+ }
+
+ return NULL;
+}
+
+static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_TEXT);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
+}
+
+static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
+{
+ BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
+ return ((but->editstr == NULL) && (but->drawstr[0] != '\0') && (but->flag & UI_BUT_VALUE_CLEAR));
+}
+
+static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
+{
+ StructRNA *type;
+ short idcode;
+
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
+
+ if (but->rnaprop == NULL) {
+ return false;
+ }
+
+ type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ idcode = RNA_type_to_ID_code(type);
+
+ return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
+}
+
+static PredefinedExtraOpIconType ui_but_icon_extra_get(uiBut *but)
+{
+ switch (but->type) {
+ case UI_BTYPE_TEXT:
+ if (ui_but_icon_extra_is_visible_text_clear(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_CLEAR;
+ }
+ break;
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_CLEAR;
+ }
+ else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
+ return PREDEFINED_EXTRA_OP_ICON_EYEDROPPER;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return PREDEFINED_EXTRA_OP_ICON_NONE;
+}
+
+/**
+ * While some extra operator icons have to be set explicitly upon button creating, this code adds
+ * some generic ones based on button data. Currently these are mutually exclusive, so there's only
+ * ever one predefined extra icon.
+ */
+static void ui_but_predefined_extra_operator_icons_add(uiBut *but)
+{
+ PredefinedExtraOpIconType extra_icon = ui_but_icon_extra_get(but);
+ wmOperatorType *optype = NULL;
+ BIFIconID icon = ICON_NONE;
+
+ switch (extra_icon) {
+ case PREDEFINED_EXTRA_OP_ICON_EYEDROPPER: {
+ static wmOperatorType *id_eyedropper_ot = NULL;
+ if (!id_eyedropper_ot) {
+ id_eyedropper_ot = WM_operatortype_find("UI_OT_eyedropper_id", false);
+ }
+ BLI_assert(id_eyedropper_ot);
+
+ optype = id_eyedropper_ot;
+ icon = ICON_EYEDROPPER;
+
+ break;
+ }
+ case PREDEFINED_EXTRA_OP_ICON_CLEAR: {
+ static wmOperatorType *clear_ot = NULL;
+ if (!clear_ot) {
+ clear_ot = WM_operatortype_find("UI_OT_button_string_clear", false);
+ }
+ BLI_assert(clear_ot);
+
+ optype = clear_ot;
+ icon = ICON_PANEL_CLOSE;
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (optype) {
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.first; op_icon; op_icon = op_icon->next) {
+ if ((op_icon->optype_params->optype == optype) && (op_icon->icon == icon)) {
+ /* Don't add the same operator icon twice (happens if button is kept alive while active).
+ */
+ return;
+ }
+ }
+ ui_but_extra_operator_icon_add_ptr(but, optype, WM_OP_INVOKE_DEFAULT, (int)icon);
+ }
+}
+
+/** \} */
+
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
@@ -1541,6 +1722,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
if (UI_but_is_decorator(but)) {
ui_but_anim_decorate_update_from_flag(but);
}
+ ui_but_predefined_extra_operator_icons_add(but);
}
/* handle pending stuff */
@@ -2281,69 +2463,6 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
return but_iter;
}
-/** \name Check to show extra icons
- *
- * Extra icons are shown on the right hand side of buttons.
- * This could (should!) definitely become more generic, but for now this is good enough.
- * \{ */
-
-static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
-{
- BLI_assert(but->type == UI_BTYPE_TEXT);
- return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
-}
-
-static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
-{
- BLI_assert(ELEM(but->type, UI_BTYPE_SEARCH_MENU));
- return ((but->editstr == NULL) && (but->drawstr[0] != '\0') && (but->flag & UI_BUT_VALUE_CLEAR));
-}
-
-static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
-{
- StructRNA *type;
- short idcode;
-
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
-
- if (but->rnaprop == NULL) {
- return false;
- }
-
- type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
- idcode = RNA_type_to_ID_code(type);
-
- return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
-}
-
-uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
-{
- switch (but->type) {
- case UI_BTYPE_TEXT:
- if (ui_but_icon_extra_is_visible_text_clear(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- break;
- case UI_BTYPE_SEARCH_MENU:
- if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
- /* pass */
- }
- else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
- return UI_BUT_ICONEXTRA_CLEAR;
- }
- else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
- return UI_BUT_ICONEXTRA_EYEDROPPER;
- }
- break;
- default:
- break;
- }
-
- return UI_BUT_ICONEXTRA_NONE;
-}
-
-/** \} */
-
static double ui_get_but_scale_unit(uiBut *but, double value)
{
UnitSettings *unit = but->block->unit;
@@ -3087,6 +3206,7 @@ static void ui_but_free(const bContext *C, uiBut *but)
if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) {
MEM_freeN(but->dragpoin);
}
+ ui_but_extra_operator_icons_free(but);
BLI_assert(UI_butstore_is_registered(but->block, but) == false);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9a16cc6d41f..65655c74ee9 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2673,15 +2673,19 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR],
/** \name Button Text Selection/Editing
* \{ */
-static void ui_textedit_string_clear_and_exit(bContext *C, uiBut *but, uiHandleButtonData *data)
+void ui_but_active_string_clear_and_exit(bContext *C, uiBut *but)
{
+ if (!but->active) {
+ return;
+ }
+
/* most likely NULL, but let's check, and give it temp zero string */
- if (!data->str) {
- data->str = MEM_callocN(1, "temp str");
+ if (!but->active->str) {
+ but->active->str = MEM_callocN(1, "temp str");
}
- data->str[0] = 0;
+ but->active->str[0] = 0;
- ui_apply_but_TEX(C, but, data);
+ ui_apply_but_TEX(C, but, but->active);
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -3768,6 +3772,19 @@ static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
ED_region_tag_redraw(data->region);
}
+static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtraOpIcon *op_icon)
+{
+ WM_operator_name_call_ptr(C,
+ op_icon->optype_params->optype,
+ op_icon->optype_params->opcontext,
+ op_icon->optype_params->opptr);
+
+ /* Force recreation of extra operator icons (pseudo update). */
+ ui_but_extra_operator_icons_free(but);
+
+ WM_event_add_mousemove(C);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -3911,6 +3928,46 @@ static uiBut *ui_but_list_row_text_activate(bContext *C,
/** \name Events for Various Button Types
* \{ */
+static uiButExtraOpIcon *ui_but_extra_operator_icon_mouse_over_get(uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ float xmax = but->rect.xmax;
+ const float icon_size = BLI_rctf_size_y(&but->rect);
+ int x = event->x, y = event->y;
+
+ ui_window_to_block(data->region, but->block, &x, &y);
+ if (!BLI_rctf_isect_pt(&but->rect, x, y)) {
+ return NULL;
+ }
+
+ /* Inverse order, from right to left. */
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.last; op_icon; op_icon = op_icon->prev) {
+ if ((x > (xmax - icon_size)) && x < xmax) {
+ return op_icon;
+ }
+ xmax -= icon_size;
+ }
+
+ return NULL;
+}
+
+static bool ui_do_but_extra_operator_icon(bContext *C,
+ uiBut *but,
+ uiHandleButtonData *data,
+ const wmEvent *event)
+{
+ uiButExtraOpIcon *op_icon = ui_but_extra_operator_icon_mouse_over_get(but, data, event);
+
+ if (op_icon) {
+ ui_but_extra_operator_icon_apply(C, but, op_icon);
+ button_activate_exit(C, but, data, false, false);
+ return true;
+ }
+
+ return false;
+}
+
#ifdef USE_DRAG_TOGGLE
/* Shared by any button that supports drag-toggle. */
static bool ui_do_but_ANY_drag_toggle(
@@ -4098,23 +4155,6 @@ static int ui_do_but_KEYEVT(bContext *C,
return WM_UI_HANDLER_CONTINUE;
}
-static bool ui_but_is_mouse_over_icon_extra(const ARegion *region,
- uiBut *but,
- const int mouse_xy[2])
-{
- int x = mouse_xy[0], y = mouse_xy[1];
- rcti icon_rect;
-
- BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
-
- ui_window_to_block(region, but->block, &x, &y);
-
- BLI_rcti_rctf_copy(&icon_rect, &but->rect);
- icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
-
- return BLI_rcti_isect_pt(&icon_rect, x, y);
-}
-
static int ui_do_but_TAB(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
@@ -4168,17 +4208,11 @@ static int ui_do_but_TEX(
else if (but->dt == UI_EMBOSS_NONE && !event->ctrl) {
/* pass */
}
- else {
- const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
-
- if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
- }
- return WM_UI_HANDLER_BREAK;
+ else if (!ui_but_extra_operator_icon_mouse_over_get(but, data, event)) {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
}
+
+ return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_TEXT_EDITING) {
@@ -4196,27 +4230,12 @@ static int ui_do_but_TEX(
static int ui_do_but_SEARCH_UNLINK(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
- const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
-
/* unlink icon is on right */
- if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && (has_icon_extra == true) &&
- (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true)) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) {
/* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
- if (event->val == KM_RELEASE) {
- /* unlink */
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- ui_textedit_string_clear_and_exit(C, but, data);
- }
- /* eyedropper */
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
- }
- else {
- BLI_assert(0);
- }
+ if ((event->val == KM_RELEASE) && ui_do_but_extra_operator_icon(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
}
- return WM_UI_HANDLER_BREAK;
}
return ui_do_but_TEX(C, block, but, data, event);
}
@@ -6976,6 +6995,14 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (event->type == EVT_DROP) {
ui_but_drop(C, event, but, data);
}
+
+ if ((data->state == BUTTON_STATE_HIGHLIGHT) &&
+ ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) &&
+ (event->val == KM_RELEASE) &&
+ /* Only returns true if the event was handled. */
+ ui_do_but_extra_operator_icon(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
}
if (but->flag & UI_BUT_DISABLED) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 9705f0fa161..5c73b41b778 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -78,14 +78,6 @@ enum {
/* warn: rest of uiBut->flag in UI_interface.h */
};
-/* some buttons display icons only under special conditions
- * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
-typedef enum uiButExtraIconType {
- UI_BUT_ICONEXTRA_NONE = 1,
- UI_BUT_ICONEXTRA_CLEAR,
- UI_BUT_ICONEXTRA_EYEDROPPER,
-} uiButExtraIconType;
-
/* uiBut->dragflag */
enum {
UI_BUT_DRAGPOIN_FREE = (1 << 0),
@@ -262,6 +254,8 @@ struct uiBut {
short opcontext;
uchar menu_key; /* 'a'-'z', always lower case */
+ ListBase extra_op_icons; /* uiButExtraOpIcon */
+
/* Draggable data, type is WM_DRAG_... */
char dragtype;
short dragflag;
@@ -293,6 +287,16 @@ typedef struct uiButTab {
struct MenuType *menu;
} uiButTab;
+/**
+ * Additional, superimposed icon for a button, invoking an operator.
+ */
+typedef struct uiButExtraOpIcon {
+ struct uiButExtraOpIcon *next, *prev;
+
+ BIFIconID icon;
+ struct wmOperatorCallParams *optype_params;
+} uiButExtraOpIcon;
+
typedef struct ColorPicker {
struct ColorPicker *next, *prev;
/** Color data, may be HSV or HSL. */
@@ -497,14 +501,17 @@ extern bool ui_but_string_set_eval_num(struct bContext *C,
const char *str,
double *value) ATTR_NONNULL();
extern int ui_but_string_get_max_length(uiBut *but);
+/* Clear & exit the active button's string. */
+extern void ui_but_active_string_clear_and_exit(struct bContext *C, uiBut *but) ATTR_NONNULL();
extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
void ui_def_but_icon(uiBut *but, const int icon, const int flag);
void ui_def_but_icon_clear(uiBut *but);
-extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
+void ui_but_extra_operator_icons_free(uiBut *but);
+
extern void ui_but_rna_menu_convert_to_panel_type(struct uiBut *but, const char *panel_type);
extern void ui_but_rna_menu_convert_to_menu_type(struct uiBut *but, const char *menu_type);
extern bool ui_but_menu_draw_as_popover(const uiBut *but);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 68d21e88211..b3c46dda4c3 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1590,6 +1590,34 @@ static void UI_OT_button_execute(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Text Button Clear Operator
+ * \{ */
+
+static int button_string_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but) {
+ ui_but_active_string_clear_and_exit(C, but);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_button_string_clear(wmOperatorType *ot)
+{
+ ot->name = "Clear Button String";
+ ot->idname = "UI_OT_button_string_clear";
+ ot->description = "Unsets the text of the active button";
+
+ ot->poll = ED_operator_regionactive;
+ ot->exec = button_string_clear_exec;
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Drop Color Operator
* \{ */
@@ -1714,6 +1742,7 @@ void ED_operatortypes_ui(void)
#endif
WM_operatortype_append(UI_OT_reloadtranslation);
WM_operatortype_append(UI_OT_button_execute);
+ WM_operatortype_append(UI_OT_button_string_clear);
/* external */
WM_operatortype_append(UI_OT_eyedropper_color);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index d3d95401851..a0bb4de96ea 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2371,13 +2371,29 @@ static BIFIconID widget_icon_id(uiBut *but)
}
}
+static void widget_draw_extra_icons(const uiWidgetColors *wcol,
+ uiBut *but,
+ rcti *rect,
+ float alpha)
+{
+ /* inverse order, from right to left. */
+ for (uiButExtraOpIcon *op_icon = but->extra_op_icons.last; op_icon; op_icon = op_icon->prev) {
+ rcti temp = *rect;
+
+ temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
+
+ widget_draw_icon(but, op_icon->icon, alpha, &temp, wcol->text);
+
+ rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
+ }
+}
+
/* draws text and icons for buttons */
static void widget_draw_text_icon(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
uiBut *but,
rcti *rect)
{
- const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
@@ -2499,23 +2515,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
}
/* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
- if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
- rcti temp = *rect;
-
- temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
-
- if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, wcol->text);
- }
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, wcol->text);
- }
- else {
- BLI_assert(0);
- }
-
- rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
- }
+ widget_draw_extra_icons(wcol, but, rect, alpha);
/* clip but->drawstr to fit in available space */
if (but->editstr && but->pos >= 0) {
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index b3507c7e57e..5ecd3191bfb 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -775,6 +775,16 @@ typedef struct wmOperatorType {
} wmOperatorType;
+/**
+ * Wrapper to reference a wmOperatorType together with some set properties and othere relevant
+ * information to invoke the operator in a customizable way.
+ */
+typedef struct wmOperatorCallParams {
+ struct wmOperatorType *optype;
+ struct PointerRNA *opptr;
+ short opcontext;
+} wmOperatorCallParams;
+
#ifdef WITH_INPUT_IME
/* *********** Input Method Editor (IME) *********** */
/**