UI: Operator Props Dialog Changes #117528
|
@ -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);
|
||||
}
|
||||
Harley marked this conversation as resolved
Outdated
|
||||
|
||||
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);
|
||||
Harley marked this conversation as resolved
Brecht Van Lommel
commented
title of the tile -> title of the popup title of the tile -> title of the popup
|
||||
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);
|
||||
|
||||
Harley marked this conversation as resolved
Brecht Van Lommel
commented
I'm not sure it makes sense to have Can we leave this out of the Python API until it's more clear if this is something we actually want to recommend people use? I don't mind having it in C++. I'm not sure it makes sense to have `cancel_default` without also being able to change the text of the cancel button. Or if we want to have popups that do this at all actually.
Can we leave this out of the Python API until it's more clear if this is something we actually want to recommend people use? I don't mind having it in C++.
|
||||
/* 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)
|
||||
Harley marked this conversation as resolved
Guillermo Venegas
commented
this few lines (1687-1700) duplicates this few lines (1687-1700) duplicates `wm_operator_ui_popup_cancel`
|
||||
{
|
||||
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(
|
||||
|
|
Loading…
Reference in New Issue
Misses
nullptr
checks inWM_operator_props_dialog_popup
string params