UI: Operator Confirm Dialog Changes
Removal of "confirm" operator callback for confirmation customization, in favor of new method that shares existing operator dialog code and allows python configuration. Pull Request: https://projects.blender.org/blender/blender/pulls/117564
This commit is contained in:
parent
5bd1e0bb22
commit
28366f624f
|
@ -3043,10 +3043,15 @@ void uiItemTabsEnumR_prop(uiLayout *layout,
|
|||
const char *UI_layout_introspect(uiLayout *layout);
|
||||
|
||||
/**
|
||||
* Helper to add a big icon and create a split layout for alert popups.
|
||||
* Helpers to add a big icon and create a split layout for alert popups.
|
||||
* Returns the layout to place further items into the alert box.
|
||||
*/
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block, int size, eAlertIcon icon);
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block,
|
||||
const uiStyle *style,
|
||||
const int dialog_width,
|
||||
const eAlertIcon icon,
|
||||
const int icon_size);
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon);
|
||||
|
||||
/* UI Operators */
|
||||
struct uiDragColorHandle {
|
||||
|
|
|
@ -45,6 +45,7 @@ struct IconTextOverlay {
|
|||
#define PREVIEW_DEFAULT_HEIGHT 128
|
||||
|
||||
enum eAlertIcon {
|
||||
ALERT_ICON_NONE = -1,
|
||||
ALERT_ICON_WARNING = 0,
|
||||
ALERT_ICON_QUESTION = 1,
|
||||
ALERT_ICON_ERROR = 2,
|
||||
|
|
|
@ -6396,12 +6396,12 @@ const char *UI_layout_introspect(uiLayout *layout)
|
|||
/** \name Alert Box with Big Icon
|
||||
* \{ */
|
||||
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block,
|
||||
const uiStyle *style,
|
||||
const int dialog_width,
|
||||
const eAlertIcon icon,
|
||||
const int icon_size)
|
||||
{
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
const short icon_size = 64 * UI_SCALE_FAC;
|
||||
const int text_points_max = std::max(style->widget.points, style->widgetlabel.points);
|
||||
const int dialog_width = icon_size + (text_points_max * size * UI_SCALE_FAC);
|
||||
/* By default, the space between icon and text/buttons will be equal to the 'columnspace',
|
||||
* this extra padding will add some space by increasing the left column width,
|
||||
* making the icon placement more symmetrical, between the block edge and the text. */
|
||||
|
@ -6428,4 +6428,13 @@ uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
|
|||
return layout;
|
||||
}
|
||||
|
||||
uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
|
||||
{
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
const short icon_size = 64 * UI_SCALE_FAC;
|
||||
const int text_points_max = std::max(style->widget.points, style->widgetlabel.points);
|
||||
const int dialog_width = icon_size + (text_points_max * size * UI_SCALE_FAC);
|
||||
return uiItemsAlertBox(block, style, dialog_width, icon, icon_size);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -209,10 +209,22 @@ static void rna_progress_end(wmWindowManager *wm)
|
|||
}
|
||||
|
||||
/* wrap these because of 'const wmEvent *' */
|
||||
static int rna_Operator_confirm(bContext *C, wmOperator *op, wmEvent *event)
|
||||
static int rna_Operator_confirm(bContext *C,
|
||||
wmOperator *op,
|
||||
wmEvent * /*event*/,
|
||||
const char *title,
|
||||
const char *message,
|
||||
const char *confirm_text,
|
||||
const int icon,
|
||||
const char *text_ctxt,
|
||||
const bool translate)
|
||||
{
|
||||
return WM_operator_confirm(C, op, event);
|
||||
title = RNA_translate_ui_text(title, text_ctxt, nullptr, nullptr, translate);
|
||||
message = RNA_translate_ui_text(message, text_ctxt, nullptr, nullptr, translate);
|
||||
confirm_text = RNA_translate_ui_text(confirm_text, text_ctxt, nullptr, nullptr, translate);
|
||||
return WM_operator_confirm_ex(C, op, title, message, confirm_text, icon);
|
||||
}
|
||||
|
||||
static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
return WM_operator_props_popup(C, op, event);
|
||||
|
@ -788,6 +800,16 @@ void RNA_api_window(StructRNA *srna)
|
|||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
const EnumPropertyItem rna_operator_popup_icon_items[] = {
|
||||
{ALERT_ICON_NONE, "NONE", 0, "None", ""},
|
||||
{ALERT_ICON_WARNING, "WARNING", 0, "Warning", ""},
|
||||
{ALERT_ICON_QUESTION, "QUESTION", 0, "Question", ""},
|
||||
{ALERT_ICON_ERROR, "ERROR", 0, "Error", ""},
|
||||
{ALERT_ICON_INFO, "INFO", 0, "Info", ""},
|
||||
{ALERT_ICON_BLENDER, "BLENDER", 0, "Blender", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
void RNA_api_wm(StructRNA *srna)
|
||||
{
|
||||
FunctionRNA *func;
|
||||
|
@ -911,6 +933,24 @@ void RNA_api_wm(StructRNA *srna)
|
|||
"(only to let user confirm the execution, no operator properties shown)");
|
||||
rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN);
|
||||
|
||||
parm = RNA_def_property(func, "title", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(parm, "Title", "Optional text to show as title of the popup");
|
||||
|
||||
parm = RNA_def_property(func, "message", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(parm, "Message", "Optional first line of content text");
|
||||
|
||||
parm = RNA_def_property(func, "confirm_text", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(
|
||||
parm,
|
||||
"Confirm Text",
|
||||
"Optional text to show instead to the default \"OK\" confirmation button text");
|
||||
|
||||
parm = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(parm, rna_operator_popup_icon_items);
|
||||
RNA_def_property_ui_text(parm, "Icon", "Optional icon displayed in the dialog");
|
||||
|
||||
api_ui_item_common_translation(func);
|
||||
|
||||
/* wrap UI_popup_menu_begin */
|
||||
func = RNA_def_function(srna, "popmenu_begin__internal", "rna_PopMenuBegin");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||
|
|
|
@ -685,6 +685,18 @@ int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *event);
|
|||
*/
|
||||
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *event);
|
||||
int WM_operator_confirm_or_exec(bContext *C, wmOperator *op, const wmEvent *event);
|
||||
|
||||
/**
|
||||
* Like WM_operator_confirm, but with more options and can't be used as an invoke directly.
|
||||
*/
|
||||
int WM_operator_confirm_ex(bContext *C,
|
||||
wmOperator *op,
|
||||
const char *title = nullptr,
|
||||
const char *message = nullptr,
|
||||
const char *confirm_text = nullptr,
|
||||
int icon = 0, /* ALERT_ICON_WARNING. */
|
||||
bool cancel_default = false);
|
||||
|
||||
/**
|
||||
* Invoke callback, file selector "filepath" unset + exec.
|
||||
*
|
||||
|
|
|
@ -919,26 +919,14 @@ struct wmTimer {
|
|||
bool sleep;
|
||||
};
|
||||
|
||||
enum wmConfirmSize {
|
||||
WM_WARNING_SIZE_SMALL = 0,
|
||||
WM_WARNING_SIZE_LARGE,
|
||||
enum wmPopupSize {
|
||||
WM_POPUP_SIZE_SMALL = 0,
|
||||
WM_POPUP_SIZE_LARGE,
|
||||
};
|
||||
|
||||
enum wmConfirmPosition {
|
||||
WM_WARNING_POSITION_MOUSE = 0,
|
||||
WM_WARNING_POSITION_CENTER,
|
||||
};
|
||||
|
||||
struct wmConfirmDetails {
|
||||
std::string title;
|
||||
std::string message;
|
||||
std::string message2;
|
||||
std::string confirm_text;
|
||||
int icon;
|
||||
wmConfirmSize size;
|
||||
wmConfirmPosition position;
|
||||
bool cancel_default;
|
||||
bool mouse_move_quit;
|
||||
enum wmPopupPosition {
|
||||
WM_POPUP_POSITION_MOUSE = 0,
|
||||
WM_POPUP_POSITION_CENTER,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1068,11 +1056,6 @@ struct wmOperatorType {
|
|||
*/
|
||||
std::string (*get_description)(bContext *C, wmOperatorType *ot, PointerRNA *ptr);
|
||||
|
||||
/**
|
||||
* If using WM_operator_confirm the following can override all parts of the dialog.
|
||||
*/
|
||||
void (*confirm)(bContext *C, wmOperator *, wmConfirmDetails *details);
|
||||
|
||||
/** RNA for properties */
|
||||
StructRNA *srna;
|
||||
|
||||
|
|
|
@ -3581,15 +3581,15 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
|
|||
/** \name Clear Recent Files List Operator
|
||||
* \{ */
|
||||
|
||||
static void wm_clear_recent_files_confirm(bContext * /*C*/,
|
||||
wmOperator * /*op*/,
|
||||
wmConfirmDetails *confirm)
|
||||
static int wm_clear_recent_files_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
confirm->message = IFACE_("Remove all items from the recent files list");
|
||||
confirm->confirm_text = IFACE_("Remove All");
|
||||
confirm->position = WM_WARNING_POSITION_CENTER;
|
||||
confirm->size = WM_WARNING_SIZE_LARGE;
|
||||
confirm->cancel_default = true;
|
||||
return WM_operator_confirm_ex(C,
|
||||
op,
|
||||
nullptr,
|
||||
IFACE_("Remove all items from the recent files list"),
|
||||
IFACE_("Remove All"),
|
||||
ALERT_ICON_WARNING,
|
||||
false);
|
||||
}
|
||||
|
||||
static int wm_clear_recent_files_exec(bContext * /*C*/, wmOperator * /*op*/)
|
||||
|
@ -3606,9 +3606,8 @@ void WM_OT_clear_recent_files(wmOperatorType *ot)
|
|||
ot->idname = "WM_OT_clear_recent_files";
|
||||
ot->description = "Clear the recent files list";
|
||||
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->invoke = wm_clear_recent_files_invoke;
|
||||
ot->exec = wm_clear_recent_files_exec;
|
||||
ot->confirm = wm_clear_recent_files_confirm;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef WIN32
|
||||
# include "GHOST_C-api.h"
|
||||
|
@ -1186,205 +1188,6 @@ int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/
|
|||
return OPERATOR_INTERFACE;
|
||||
}
|
||||
|
||||
static void wm_operator_block_cancel(bContext *C, void *arg_op, void *arg_block)
|
||||
{
|
||||
wmOperator *op = static_cast<wmOperator *>(arg_op);
|
||||
uiBlock *block = static_cast<uiBlock *>(arg_block);
|
||||
UI_popup_block_close(C, CTX_wm_window(C), block);
|
||||
WM_redraw_windows(C);
|
||||
if (op) {
|
||||
if (op->type->cancel) {
|
||||
op->type->cancel(C, op);
|
||||
}
|
||||
WM_operator_free(op);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_operator_block_confirm(bContext *C, void *arg_op, void *arg_block)
|
||||
{
|
||||
wmOperator *op = static_cast<wmOperator *>(arg_op);
|
||||
uiBlock *block = static_cast<uiBlock *>(arg_block);
|
||||
UI_popup_block_close(C, CTX_wm_window(C), block);
|
||||
WM_redraw_windows(C);
|
||||
if (op) {
|
||||
WM_operator_call_ex(C, op, true);
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *wm_block_confirm_create(bContext *C, ARegion *region, void *arg_op)
|
||||
{
|
||||
wmOperator *op = static_cast<wmOperator *>(arg_op);
|
||||
|
||||
wmConfirmDetails confirm = {{0}};
|
||||
|
||||
confirm.title = WM_operatortype_description(C, op->type, op->ptr);
|
||||
confirm.confirm_text = WM_operatortype_name(op->type, op->ptr);
|
||||
confirm.icon = ALERT_ICON_WARNING;
|
||||
confirm.size = WM_WARNING_SIZE_SMALL;
|
||||
confirm.position = WM_WARNING_POSITION_MOUSE;
|
||||
confirm.cancel_default = false;
|
||||
confirm.mouse_move_quit = false;
|
||||
|
||||
/* uiBlock.flag */
|
||||
int block_flags = UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT;
|
||||
|
||||
if (op->type->confirm) {
|
||||
op->type->confirm(C, op, &confirm);
|
||||
}
|
||||
if (confirm.mouse_move_quit) {
|
||||
block_flags |= UI_BLOCK_MOVEMOUSE_QUIT;
|
||||
}
|
||||
if (confirm.icon < ALERT_ICON_WARNING || confirm.icon >= ALERT_ICON_MAX) {
|
||||
confirm.icon = ALERT_ICON_QUESTION;
|
||||
}
|
||||
|
||||
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||
UI_block_flag_enable(block, block_flags);
|
||||
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
int text_width = std::max(
|
||||
120 * UI_SCALE_FAC,
|
||||
BLF_width(style->widget.uifont_id, confirm.title.c_str(), confirm.title.length()));
|
||||
if (!confirm.message.empty()) {
|
||||
text_width = std::max(text_width,
|
||||
int(BLF_width(style->widget.uifont_id,
|
||||
confirm.message.c_str(),
|
||||
confirm.message.length())));
|
||||
}
|
||||
if (!confirm.message2.empty()) {
|
||||
text_width = std::max(text_width,
|
||||
int(BLF_width(style->widget.uifont_id,
|
||||
confirm.message2.c_str(),
|
||||
confirm.message2.length())));
|
||||
}
|
||||
|
||||
const bool small = confirm.size == WM_WARNING_SIZE_SMALL;
|
||||
const int padding = (small ? 7 : 14) * UI_SCALE_FAC;
|
||||
const short icon_size = (small ? (confirm.message.empty() ? 32 : 48) : 64) * UI_SCALE_FAC;
|
||||
const int dialog_width = icon_size + text_width + (style->columnspace * 2.5);
|
||||
const float split_factor = (float)icon_size / (float)(dialog_width - style->columnspace);
|
||||
|
||||
uiLayout *block_layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, UI_UNIT_Y, 0, style);
|
||||
|
||||
/* Split layout to put alert icon on left side. */
|
||||
uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false);
|
||||
|
||||
/* Alert icon on the left. */
|
||||
uiLayout *layout = uiLayoutRow(split_block, true);
|
||||
/* Using 'align_left' with 'row' avoids stretching the icon along the width of column. */
|
||||
uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_LEFT);
|
||||
uiDefButAlert(block, confirm.icon, 0, 0, icon_size, icon_size);
|
||||
|
||||
/* The rest of the content on the right. */
|
||||
layout = uiLayoutColumn(split_block, true);
|
||||
|
||||
if (!confirm.title.empty()) {
|
||||
if (confirm.message.empty()) {
|
||||
uiItemS(layout);
|
||||
}
|
||||
uiItemL_ex(layout, confirm.title.c_str(), ICON_NONE, true, false);
|
||||
}
|
||||
|
||||
if (!confirm.message.empty()) {
|
||||
uiItemL(layout, confirm.message.c_str(), ICON_NONE);
|
||||
}
|
||||
|
||||
if (!confirm.message2.empty()) {
|
||||
uiItemL(layout, confirm.message2.c_str(), ICON_NONE);
|
||||
}
|
||||
|
||||
uiItemS_ex(layout, small ? 0.5f : 4.0f);
|
||||
|
||||
/* Buttons. */
|
||||
|
||||
#ifdef _WIN32
|
||||
const bool windows_layout = true;
|
||||
#else
|
||||
const bool windows_layout = false;
|
||||
#endif
|
||||
|
||||
uiBut *confirm_but = nullptr;
|
||||
uiBut *cancel_but = nullptr;
|
||||
uiLayout *split = uiLayoutSplit(small ? block_layout : layout, 0.0f, true);
|
||||
uiLayoutSetScaleY(split, small ? 1.1f : 1.2f);
|
||||
uiLayoutColumn(split, false);
|
||||
|
||||
if (windows_layout) {
|
||||
confirm_but = uiDefIconTextBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
0,
|
||||
confirm.confirm_text.c_str(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr);
|
||||
uiLayoutColumn(split, false);
|
||||
}
|
||||
|
||||
cancel_but = uiDefIconTextBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
0,
|
||||
IFACE_("Cancel"),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
if (!windows_layout) {
|
||||
uiLayoutColumn(split, false);
|
||||
confirm_but = uiDefIconTextBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
0,
|
||||
confirm.confirm_text.c_str(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
UI_block_func_set(block, nullptr, nullptr, nullptr);
|
||||
UI_but_func_set(confirm_but, wm_operator_block_confirm, op, block);
|
||||
UI_but_func_set(cancel_but, wm_operator_block_cancel, op, block);
|
||||
UI_but_drawflag_disable(confirm_but, UI_BUT_TEXT_LEFT);
|
||||
UI_but_drawflag_disable(cancel_but, UI_BUT_TEXT_LEFT);
|
||||
UI_but_flag_enable(confirm.cancel_default ? cancel_but : confirm_but, UI_BUT_ACTIVE_DEFAULT);
|
||||
|
||||
if (confirm.position == WM_WARNING_POSITION_MOUSE) {
|
||||
int bounds_offset[2];
|
||||
bounds_offset[0] = uiLayoutGetWidth(layout) * (windows_layout ? -0.33f : -0.66f);
|
||||
bounds_offset[1] = UI_UNIT_Y * (confirm.message[0] ? 3.1 : 2.5);
|
||||
UI_block_bounds_set_popup(block, padding, bounds_offset);
|
||||
}
|
||||
else if (confirm.position == WM_WARNING_POSITION_CENTER) {
|
||||
UI_block_bounds_set_centered(block, padding);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
int WM_operator_confirm_message_ex(bContext *C,
|
||||
wmOperator *op,
|
||||
const char *title,
|
||||
|
@ -1412,11 +1215,6 @@ int WM_operator_confirm_message_ex(bContext *C,
|
|||
|
||||
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
|
||||
{
|
||||
if (op->type->confirm) {
|
||||
UI_popup_block_invoke(C, wm_block_confirm_create, op, nullptr);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
return WM_operator_confirm_message_ex(
|
||||
C, op, IFACE_("OK?"), ICON_QUESTION, message, WM_OP_EXEC_REGION_WIN);
|
||||
}
|
||||
|
@ -1645,11 +1443,10 @@ struct wmOpPopUp {
|
|||
int free_op;
|
||||
std::string title;
|
||||
std::string message;
|
||||
std::string message2;
|
||||
std::string confirm_text;
|
||||
int icon;
|
||||
wmConfirmSize size;
|
||||
wmConfirmPosition position;
|
||||
eAlertIcon icon;
|
||||
wmPopupSize size;
|
||||
wmPopupPosition position;
|
||||
bool cancel_default;
|
||||
bool mouse_move_quit;
|
||||
bool include_properties;
|
||||
|
@ -1699,6 +1496,8 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
wmOpPopUp *data = static_cast<wmOpPopUp *>(user_data);
|
||||
wmOperator *op = data->op;
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
const bool small = data->size == WM_POPUP_SIZE_SMALL;
|
||||
const short icon_size = (small ? 32 : 64) * UI_SCALE_FAC;
|
||||
|
||||
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
|
||||
UI_block_flag_disable(block, UI_BLOCK_LOOP);
|
||||
|
@ -1707,24 +1506,71 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
if (data->mouse_move_quit) {
|
||||
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
|
||||
}
|
||||
if (data->icon < ALERT_ICON_NONE || data->icon >= ALERT_ICON_MAX) {
|
||||
data->icon = ALERT_ICON_QUESTION;
|
||||
}
|
||||
|
||||
UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NUMSELECT);
|
||||
|
||||
uiLayout *layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, 0, 0, style);
|
||||
/* Width based on the text lengths. */
|
||||
int text_width = std::max(
|
||||
120 * UI_SCALE_FAC,
|
||||
BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX));
|
||||
|
||||
uiItemL_ex(layout, data->title.c_str(), ICON_NONE, true, false);
|
||||
uiItemS_ex(layout, 0.3f);
|
||||
/* Break Message into multiple lines. */
|
||||
std::vector<std::string> message_lines;
|
||||
blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim();
|
||||
std::istringstream message_stream(messaged_trimmed);
|
||||
std::string line;
|
||||
while (std::getline(message_stream, line)) {
|
||||
message_lines.push_back(line);
|
||||
text_width = std::max(
|
||||
text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX)));
|
||||
}
|
||||
|
||||
int dialog_width = std::max(text_width + int(style->columnspace * 2.5), data->width);
|
||||
|
||||
/* Adjust width if the button text is long. */
|
||||
const int longest_button_text = std::max(
|
||||
BLF_width(style->widget.uifont_id, data->confirm_text.c_str(), BLF_DRAW_STR_DUMMY_MAX),
|
||||
BLF_width(style->widget.uifont_id, IFACE_("Cancel"), BLF_DRAW_STR_DUMMY_MAX));
|
||||
dialog_width = std::max(dialog_width, 3 * longest_button_text);
|
||||
|
||||
uiLayout *layout;
|
||||
if (data->icon != ALERT_ICON_NONE) {
|
||||
layout = uiItemsAlertBox(
|
||||
block, style, dialog_width + icon_size, eAlertIcon(data->icon), icon_size);
|
||||
}
|
||||
else {
|
||||
layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style);
|
||||
}
|
||||
|
||||
/* Title. */
|
||||
if (!data->title.empty()) {
|
||||
uiItemL_ex(layout, data->title.c_str(), ICON_NONE, true, false);
|
||||
}
|
||||
|
||||
/* Message lines. */
|
||||
for (auto &st : message_lines) {
|
||||
uiItemL(layout, st.c_str(), ICON_NONE);
|
||||
}
|
||||
|
||||
if (data->include_properties) {
|
||||
uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, 0);
|
||||
}
|
||||
|
||||
uiItemS_ex(layout, 0.6f);
|
||||
uiItemS_ex(layout, small ? 0.4f : 2.0f);
|
||||
|
||||
/* clear so the OK button is left alone */
|
||||
UI_block_func_set(block, nullptr, nullptr, nullptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
const bool windows_layout = true;
|
||||
#else
|
||||
const bool windows_layout = false;
|
||||
#endif
|
||||
|
||||
/* new column so as not to interfere with custom layouts #26436. */
|
||||
{
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
|
@ -1733,13 +1579,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
uiBut *cancel_but;
|
||||
|
||||
col = uiLayoutSplit(col, 0.0f, true);
|
||||
uiLayoutSetScaleY(col, 1.2f);
|
||||
|
||||
#ifdef _WIN32
|
||||
const bool windows_layout = true;
|
||||
#else
|
||||
const bool windows_layout = false;
|
||||
#endif
|
||||
uiLayoutSetScaleY(col, small ? 1.0f : 1.2f);
|
||||
|
||||
if (windows_layout) {
|
||||
confirm_but = uiDefBut(col_block,
|
||||
|
@ -1747,7 +1587,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
0,
|
||||
data->confirm_text.c_str(),
|
||||
0,
|
||||
-30,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
|
@ -1759,20 +1599,8 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
uiLayoutColumn(col, false);
|
||||
}
|
||||
|
||||
cancel_but = uiDefBut(col_block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
IFACE_("Cancel"),
|
||||
0,
|
||||
-30,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
cancel_but = uiDefBut(
|
||||
col_block, UI_BTYPE_BUT, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, nullptr, 0, 0, 0, 0, "");
|
||||
|
||||
if (!windows_layout) {
|
||||
uiLayoutColumn(col, false);
|
||||
|
@ -1781,7 +1609,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
0,
|
||||
data->confirm_text.c_str(),
|
||||
0,
|
||||
-30,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
|
@ -1797,14 +1625,17 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
|||
UI_but_flag_enable((data->cancel_default) ? cancel_but : confirm_but, UI_BUT_ACTIVE_DEFAULT);
|
||||
}
|
||||
|
||||
if (data->position == WM_WARNING_POSITION_MOUSE) {
|
||||
int bounds_offset[2];
|
||||
bounds_offset[0] = uiLayoutGetWidth(layout) * -0.66f;
|
||||
bounds_offset[1] = UI_UNIT_Y * 2;
|
||||
UI_block_bounds_set_popup(block, 10 * UI_SCALE_FAC, bounds_offset);
|
||||
const int padding = (small ? 7 : 14) * UI_SCALE_FAC;
|
||||
|
||||
if (data->position == WM_POPUP_POSITION_MOUSE) {
|
||||
const float button_center_x = windows_layout ? -0.33f : -0.66f;
|
||||
const float button_center_y = small ? 1.9f : 3.1f;
|
||||
const int bounds_offset[2] = {int(button_center_x * uiLayoutGetWidth(layout)),
|
||||
int(button_center_y * UI_UNIT_X)};
|
||||
UI_block_bounds_set_popup(block, padding, bounds_offset);
|
||||
}
|
||||
else if (data->position == WM_WARNING_POSITION_CENTER) {
|
||||
UI_block_bounds_set_centered(block, 10 * UI_SCALE_FAC);
|
||||
else if (data->position == WM_POPUP_POSITION_CENTER) {
|
||||
UI_block_bounds_set_centered(block, padding);
|
||||
}
|
||||
|
||||
return block;
|
||||
|
@ -1864,6 +1695,35 @@ static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
|
|||
MEM_delete(data);
|
||||
}
|
||||
|
||||
int WM_operator_confirm_ex(bContext *C,
|
||||
wmOperator *op,
|
||||
const char *title,
|
||||
const char *message,
|
||||
const char *confirm_text,
|
||||
int icon,
|
||||
bool cancel_default)
|
||||
{
|
||||
wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
|
||||
data->op = op;
|
||||
data->width = int(180.0f * UI_SCALE_FAC * UI_style_get()->widgetlabel.points /
|
||||
UI_DEFAULT_TEXT_POINTS);
|
||||
data->free_op = true;
|
||||
data->title = (title == nullptr) ? WM_operatortype_name(op->type, op->ptr) : title;
|
||||
data->message = (message == nullptr) ? std::string() : message;
|
||||
data->confirm_text = (confirm_text == nullptr) ? IFACE_("OK") : confirm_text;
|
||||
data->icon = eAlertIcon(icon);
|
||||
data->size = (message == nullptr) ? WM_POPUP_SIZE_SMALL : WM_POPUP_SIZE_LARGE;
|
||||
data->position = (message == nullptr) ? WM_POPUP_POSITION_MOUSE : WM_POPUP_POSITION_CENTER;
|
||||
data->cancel_default = cancel_default;
|
||||
data->mouse_move_quit = (message == nullptr) ? true : false;
|
||||
data->include_properties = false;
|
||||
|
||||
UI_popup_block_ex(
|
||||
C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
int WM_operator_ui_popup(bContext *C, wmOperator *op, int width)
|
||||
{
|
||||
wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
|
||||
|
@ -1937,14 +1797,17 @@ int WM_operator_props_dialog_popup(
|
|||
{
|
||||
wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
|
||||
data->op = op;
|
||||
data->width = width * UI_SCALE_FAC;
|
||||
data->width = int(float(width) * UI_SCALE_FAC * UI_style_get()->widgetlabel.points /
|
||||
UI_DEFAULT_TEXT_POINTS);
|
||||
data->free_op = true; /* if this runs and gets registered we may want not to free it */
|
||||
data->title = (title == nullptr) ? WM_operatortype_name(op->type, op->ptr) : title;
|
||||
data->confirm_text = (confirm_text == nullptr) ? IFACE_("OK") : confirm_text;
|
||||
data->icon = ALERT_ICON_NONE;
|
||||
data->size = WM_POPUP_SIZE_SMALL;
|
||||
data->position = WM_POPUP_POSITION_MOUSE;
|
||||
data->cancel_default = false;
|
||||
data->mouse_move_quit = false;
|
||||
data->include_properties = true;
|
||||
data->position = WM_WARNING_POSITION_MOUSE;
|
||||
|
||||
/* op is not executed until popup OK but is clicked */
|
||||
UI_popup_block_ex(
|
||||
|
|
Loading…
Reference in New Issue