UI: Operator Props Dialog Changes
Changes to WM_operator_props_dialog_popup to allow configuration, including via python, and with a look consistent with new confirms. Pull Request: https://projects.blender.org/blender/blender/pulls/117528
This commit is contained in:
committed by
Harley Acheson
parent
ac61dad14f
commit
0d6aec1c21
@@ -240,6 +240,8 @@ bool rna_AnimaData_override_apply(struct Main *bmain,
|
||||
void rna_def_animviz_common(struct StructRNA *srna);
|
||||
void rna_def_motionpath_common(struct StructRNA *srna);
|
||||
|
||||
void api_ui_item_common_translation(FunctionRNA *func);
|
||||
|
||||
/**
|
||||
* Settings for curved bbone settings.
|
||||
*/
|
||||
|
||||
@@ -973,21 +973,26 @@ static void api_ui_item_common_heading(FunctionRNA *func)
|
||||
func, "translate", true, "", "Translate the given heading, when UI translation is enabled");
|
||||
}
|
||||
|
||||
void api_ui_item_common_translation(FunctionRNA *func)
|
||||
{
|
||||
PropertyRNA *prop = RNA_def_string(func,
|
||||
"text_ctxt",
|
||||
nullptr,
|
||||
0,
|
||||
"",
|
||||
"Override automatic translation context of the given text");
|
||||
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_boolean(
|
||||
func, "translate", true, "", "Translate the given text, when UI translation is enabled");
|
||||
}
|
||||
|
||||
static void api_ui_item_common_text(FunctionRNA *func)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string(func, "text", nullptr, 0, "", "Override automatic text of the item");
|
||||
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL);
|
||||
prop = RNA_def_string(func,
|
||||
"text_ctxt",
|
||||
nullptr,
|
||||
0,
|
||||
"",
|
||||
"Override automatic translation context of the given text");
|
||||
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_boolean(
|
||||
func, "translate", true, "", "Translate the given text, when UI translation is enabled");
|
||||
api_ui_item_common_translation(func);
|
||||
}
|
||||
|
||||
static void api_ui_item_common(FunctionRNA *func)
|
||||
|
||||
@@ -218,6 +218,19 @@ static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event)
|
||||
return WM_operator_props_popup(C, op, event);
|
||||
}
|
||||
|
||||
static int rna_Operator_props_dialog_popup(bContext *C,
|
||||
wmOperator *op,
|
||||
const int width,
|
||||
const char *title,
|
||||
const char *confirm_text,
|
||||
const char *text_ctxt,
|
||||
const bool translate)
|
||||
{
|
||||
title = RNA_translate_ui_text(title, text_ctxt, nullptr, nullptr, translate);
|
||||
confirm_text = RNA_translate_ui_text(confirm_text, text_ctxt, nullptr, nullptr, translate);
|
||||
return WM_operator_props_dialog_popup(C, op, width, title, confirm_text);
|
||||
}
|
||||
|
||||
static int keymap_item_modifier_flag_from_args(bool any, int shift, int ctrl, int alt, int oskey)
|
||||
{
|
||||
int modifier = 0;
|
||||
@@ -859,13 +872,22 @@ void RNA_api_wm(StructRNA *srna)
|
||||
rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN);
|
||||
|
||||
/* invoked dialog opens popup with OK button, does not auto-exec operator. */
|
||||
func = RNA_def_function(srna, "invoke_props_dialog", "WM_operator_props_dialog_popup");
|
||||
func = RNA_def_function(srna, "invoke_props_dialog", "rna_Operator_props_dialog_popup");
|
||||
RNA_def_function_ui_description(
|
||||
func,
|
||||
"Operator dialog (non-autoexec popup) invoke "
|
||||
"(show operator properties and only execute it on click on OK button)");
|
||||
rna_generic_op_invoke(func, WM_GEN_INVOKE_SIZE | 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, "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");
|
||||
api_ui_item_common_translation(func);
|
||||
|
||||
/* invoke enum */
|
||||
func = RNA_def_function(srna, "invoke_search_popup", "rna_Operator_enum_search_invoke");
|
||||
RNA_def_function_ui_description(
|
||||
|
||||
@@ -708,7 +708,13 @@ int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *
|
||||
*/
|
||||
int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *event);
|
||||
int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *event);
|
||||
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width);
|
||||
|
||||
int WM_operator_props_dialog_popup(bContext *C,
|
||||
wmOperator *op,
|
||||
int width,
|
||||
const char *title = nullptr,
|
||||
const char *confirm_text = nullptr);
|
||||
|
||||
int WM_operator_redo_popup(bContext *C, wmOperator *op);
|
||||
int WM_operator_ui_popup(bContext *C, wmOperator *op, int width);
|
||||
|
||||
|
||||
@@ -1642,8 +1642,17 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
|
||||
struct wmOpPopUp {
|
||||
wmOperator *op;
|
||||
int width;
|
||||
int height;
|
||||
int free_op;
|
||||
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;
|
||||
bool include_properties;
|
||||
};
|
||||
|
||||
/* Only invoked by OK button in popups created with wm_block_dialog_create() */
|
||||
@@ -1655,7 +1664,7 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
|
||||
* In this case, wm_operator_ui_popup_cancel won't run. */
|
||||
wmOpPopUp *data = static_cast<wmOpPopUp *>(arg1);
|
||||
op = data->op;
|
||||
MEM_freeN(data);
|
||||
MEM_delete(data);
|
||||
}
|
||||
|
||||
uiBlock *block = static_cast<uiBlock *>(arg2);
|
||||
@@ -1672,6 +1681,18 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
|
||||
WM_operator_call_ex(C, op, true);
|
||||
}
|
||||
|
||||
static void wm_operator_ui_popup_cancel(bContext *C, void *user_data);
|
||||
|
||||
/* Only invoked by Cancel button in popups created with wm_block_dialog_create() */
|
||||
static void dialog_cancel_cb(bContext *C, void *arg1, void *arg2)
|
||||
{
|
||||
wm_operator_ui_popup_cancel(C, arg1);
|
||||
uiBlock *block = static_cast<uiBlock *>(arg2);
|
||||
UI_popup_menu_retval_set(block, UI_RETURN_CANCEL, true);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
UI_popup_block_close(C, win, block);
|
||||
}
|
||||
|
||||
/* Dialogs are popups that require user verification (click OK) before exec */
|
||||
static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_data)
|
||||
{
|
||||
@@ -1681,17 +1702,25 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
||||
|
||||
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
|
||||
UI_block_flag_disable(block, UI_BLOCK_LOOP);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||
|
||||
if (data->mouse_move_quit) {
|
||||
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
|
||||
}
|
||||
|
||||
/* Intentionally don't use #UI_BLOCK_MOVEMOUSE_QUIT, some dialogs have many items
|
||||
* where quitting by accident is very annoying. */
|
||||
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, data->height, 0, style);
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, 0, 0, style);
|
||||
|
||||
uiTemplateOperatorPropertyButs(
|
||||
C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
|
||||
uiItemL_ex(layout, data->title.c_str(), ICON_NONE, true, false);
|
||||
uiItemS_ex(layout, 0.3f);
|
||||
|
||||
if (data->include_properties) {
|
||||
uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, 0);
|
||||
}
|
||||
|
||||
uiItemS_ex(layout, 0.6f);
|
||||
|
||||
/* clear so the OK button is left alone */
|
||||
UI_block_func_set(block, nullptr, nullptr, nullptr);
|
||||
@@ -1700,16 +1729,83 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_
|
||||
{
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiBlock *col_block = uiLayoutGetBlock(col);
|
||||
/* Create OK button, the callback of which will execute op */
|
||||
uiBut *but = uiDefBut(
|
||||
col_block, UI_BTYPE_BUT, 0, IFACE_("OK"), 0, -30, 0, UI_UNIT_Y, nullptr, 0, 0, 0, 0, "");
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
|
||||
UI_but_func_set(but, dialog_exec_cb, data, col_block);
|
||||
uiBut *confirm_but;
|
||||
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
|
||||
|
||||
if (windows_layout) {
|
||||
confirm_but = uiDefBut(col_block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
data->confirm_text.c_str(),
|
||||
0,
|
||||
-30,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
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,
|
||||
"");
|
||||
|
||||
if (!windows_layout) {
|
||||
uiLayoutColumn(col, false);
|
||||
confirm_but = uiDefBut(col_block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
data->confirm_text.c_str(),
|
||||
0,
|
||||
-30,
|
||||
0,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
}
|
||||
|
||||
UI_but_func_set(confirm_but, dialog_exec_cb, data, col_block);
|
||||
UI_but_func_set(cancel_but, dialog_cancel_cb, data, col_block);
|
||||
UI_but_flag_enable((data->cancel_default) ? cancel_but : confirm_but, UI_BUT_ACTIVE_DEFAULT);
|
||||
}
|
||||
|
||||
/* center around the mouse */
|
||||
UI_block_bounds_set_popup(
|
||||
block, 6 * UI_SCALE_FAC, blender::int2{data->width / -2, data->height / 2});
|
||||
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);
|
||||
}
|
||||
else if (data->position == WM_WARNING_POSITION_CENTER) {
|
||||
UI_block_bounds_set_centered(block, 10 * UI_SCALE_FAC);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
@@ -1726,7 +1822,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *region, void *user_d
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_REGULAR);
|
||||
|
||||
uiLayout *layout = UI_block_layout(
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
|
||||
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, 0, 0, style);
|
||||
|
||||
/* since ui is defined the auto-layout args are not used */
|
||||
uiTemplateOperatorPropertyButs(C, layout, op, UI_BUT_LABEL_ALIGN_COLUMN, 0);
|
||||
@@ -1753,7 +1849,7 @@ static void wm_operator_ui_popup_cancel(bContext *C, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(data);
|
||||
MEM_delete(data);
|
||||
}
|
||||
|
||||
static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
|
||||
@@ -1765,17 +1861,14 @@ static void wm_operator_ui_popup_ok(bContext *C, void *arg, int retval)
|
||||
WM_operator_call_ex(C, op, true);
|
||||
}
|
||||
|
||||
MEM_freeN(data);
|
||||
MEM_delete(data);
|
||||
}
|
||||
|
||||
int WM_operator_ui_popup(bContext *C, wmOperator *op, int width)
|
||||
{
|
||||
wmOpPopUp *data = static_cast<wmOpPopUp *>(
|
||||
MEM_callocN(sizeof(wmOpPopUp), "WM_operator_ui_popup"));
|
||||
wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
|
||||
data->op = op;
|
||||
data->width = width * UI_SCALE_FAC;
|
||||
/* Actual used height depends on the content. */
|
||||
data->height = 0;
|
||||
data->free_op = true; /* if this runs and gets registered we may want not to free it */
|
||||
UI_popup_block_ex(C, wm_operator_ui_create, nullptr, wm_operator_ui_popup_cancel, data, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
@@ -1839,16 +1932,20 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent * /*event
|
||||
return wm_operator_props_popup_ex(C, op, false, true);
|
||||
}
|
||||
|
||||
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width)
|
||||
int WM_operator_props_dialog_popup(
|
||||
bContext *C, wmOperator *op, int width, const char *title, const char *confirm_text)
|
||||
{
|
||||
wmOpPopUp *data = static_cast<wmOpPopUp *>(
|
||||
MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"));
|
||||
|
||||
wmOpPopUp *data = MEM_new<wmOpPopUp>(__func__);
|
||||
data->op = op;
|
||||
data->width = width * UI_SCALE_FAC;
|
||||
/* Actual height depends on the content. */
|
||||
data->height = 0;
|
||||
data->free_op = true; /* if this runs and gets registered we may want not to free it */
|
||||
data->title = (title == nullptr) ? WM_operatortype_description(C, op->type, op->ptr) : title;
|
||||
data->confirm_text = (confirm_text == nullptr) ? WM_operatortype_name(op->type, op->ptr) :
|
||||
confirm_text;
|
||||
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(
|
||||
|
||||
Reference in New Issue
Block a user