UI: support for popups starting with buttons activated
While this could already be done from C, this is now exposed to Python
This commit is contained in:
		@@ -201,6 +201,8 @@ enum {
 | 
				
			|||||||
	UI_BUT_LIST_ITEM       = 1 << 24,
 | 
						UI_BUT_LIST_ITEM       = 1 << 24,
 | 
				
			||||||
	/** edit this button as well as the active button (not just dragging) */
 | 
						/** edit this button as well as the active button (not just dragging) */
 | 
				
			||||||
	UI_BUT_DRAG_MULTI      = 1 << 25,
 | 
						UI_BUT_DRAG_MULTI      = 1 << 25,
 | 
				
			||||||
 | 
						/** Use for popups to start editing the button on initialization. */
 | 
				
			||||||
 | 
						UI_BUT_ACTIVATE_ON_INIT = 1 << 26,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** #uiBut.str contains #UI_SEP_CHAR, used for key shortcuts */
 | 
						/** #uiBut.str contains #UI_SEP_CHAR, used for key shortcuts */
 | 
				
			||||||
	UI_BUT_HAS_SEP_CHAR    = 1 << 27,
 | 
						UI_BUT_HAS_SEP_CHAR    = 1 << 27,
 | 
				
			||||||
@@ -631,6 +633,7 @@ void    UI_but_type_set_menu_from_pulldown(uiBut *but);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* special button case, only draw it when used actively, for outliner etc */
 | 
					/* special button case, only draw it when used actively, for outliner etc */
 | 
				
			||||||
bool    UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
 | 
					bool    UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
 | 
				
			||||||
 | 
					bool    UI_block_active_only_flagged_buttons(const struct bContext *C, struct ARegion *ar, struct uiBlock *block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void    UI_but_execute(const struct bContext *C, uiBut *but);
 | 
					void    UI_but_execute(const struct bContext *C, uiBut *but);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1053,6 +1056,7 @@ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
 | 
					void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext);
 | 
				
			||||||
void uiLayoutSetActive(uiLayout *layout, bool active);
 | 
					void uiLayoutSetActive(uiLayout *layout, bool active);
 | 
				
			||||||
 | 
					void uiLayoutSetActivateInit(uiLayout *layout, bool active);
 | 
				
			||||||
void uiLayoutSetEnabled(uiLayout *layout, bool enabled);
 | 
					void uiLayoutSetEnabled(uiLayout *layout, bool enabled);
 | 
				
			||||||
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert);
 | 
					void uiLayoutSetRedAlert(uiLayout *layout, bool redalert);
 | 
				
			||||||
void uiLayoutSetAlignment(uiLayout *layout, char alignment);
 | 
					void uiLayoutSetAlignment(uiLayout *layout, char alignment);
 | 
				
			||||||
@@ -1068,6 +1072,7 @@ int uiLayoutGetLocalDir(const uiLayout *layout);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int uiLayoutGetOperatorContext(uiLayout *layout);
 | 
					int uiLayoutGetOperatorContext(uiLayout *layout);
 | 
				
			||||||
bool uiLayoutGetActive(uiLayout *layout);
 | 
					bool uiLayoutGetActive(uiLayout *layout);
 | 
				
			||||||
 | 
					bool uiLayoutGetActivateInit(uiLayout *layout);
 | 
				
			||||||
bool uiLayoutGetEnabled(uiLayout *layout);
 | 
					bool uiLayoutGetEnabled(uiLayout *layout);
 | 
				
			||||||
bool uiLayoutGetRedAlert(uiLayout *layout);
 | 
					bool uiLayoutGetRedAlert(uiLayout *layout);
 | 
				
			||||||
int uiLayoutGetAlignment(uiLayout *layout);
 | 
					int uiLayoutGetAlignment(uiLayout *layout);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -823,6 +823,24 @@ bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *b
 | 
				
			|||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *ar, uiBlock *block)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool done = false;
 | 
				
			||||||
 | 
						for (uiBut *but = block->buttons.first; but; but = but->next) {
 | 
				
			||||||
 | 
							if (!done && ui_but_is_editable(but)) {
 | 
				
			||||||
 | 
								if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
 | 
				
			||||||
 | 
									if (UI_but_active_only(C, ar, block, but)) {
 | 
				
			||||||
 | 
										done = true;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return done;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* simulate button click */
 | 
					/* simulate button click */
 | 
				
			||||||
void UI_but_execute(const bContext *C, uiBut *but)
 | 
					void UI_but_execute(const bContext *C, uiBut *but)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -160,6 +160,7 @@ struct uiLayout {
 | 
				
			|||||||
	short space;
 | 
						short space;
 | 
				
			||||||
	bool align;
 | 
						bool align;
 | 
				
			||||||
	bool active;
 | 
						bool active;
 | 
				
			||||||
 | 
						bool activate_init;
 | 
				
			||||||
	bool enabled;
 | 
						bool enabled;
 | 
				
			||||||
	bool redalert;
 | 
						bool redalert;
 | 
				
			||||||
	bool keepaspect;
 | 
						bool keepaspect;
 | 
				
			||||||
@@ -1818,6 +1819,9 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if (layout->redalert)
 | 
							if (layout->redalert)
 | 
				
			||||||
			UI_but_flag_enable(but, UI_BUT_REDALERT);
 | 
								UI_but_flag_enable(but, UI_BUT_REDALERT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (layout->activate_init)
 | 
				
			||||||
 | 
								UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* single button */
 | 
						/* single button */
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
@@ -1831,6 +1835,9 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if (layout->redalert)
 | 
							if (layout->redalert)
 | 
				
			||||||
			UI_but_flag_enable(but, UI_BUT_REDALERT);
 | 
								UI_but_flag_enable(but, UI_BUT_REDALERT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (layout->activate_init)
 | 
				
			||||||
 | 
								UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Mark non-embossed textfields inside a listbox. */
 | 
						/* Mark non-embossed textfields inside a listbox. */
 | 
				
			||||||
@@ -3949,6 +3956,11 @@ void uiLayoutSetActive(uiLayout *layout, bool active)
 | 
				
			|||||||
	layout->active = active;
 | 
						layout->active = active;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void uiLayoutSetActivateInit(uiLayout *layout, bool activate_init)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						layout->activate_init = activate_init;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
 | 
					void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	layout->enabled = enabled;
 | 
						layout->enabled = enabled;
 | 
				
			||||||
@@ -4019,6 +4031,11 @@ bool uiLayoutGetActive(uiLayout *layout)
 | 
				
			|||||||
	return layout->active;
 | 
						return layout->active;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool uiLayoutGetActivateInit(uiLayout *layout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return layout->activate_init;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool uiLayoutGetEnabled(uiLayout *layout)
 | 
					bool uiLayoutGetEnabled(uiLayout *layout)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return layout->enabled;
 | 
						return layout->enabled;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -302,16 +302,24 @@ int UI_popover_panel_invoke(
 | 
				
			|||||||
		return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
 | 
							return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uiBlock *block = NULL;
 | 
				
			||||||
	if (keep_open) {
 | 
						if (keep_open) {
 | 
				
			||||||
		ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt);
 | 
							uiPopupBlockHandle *handle = ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt);
 | 
				
			||||||
 | 
							uiPopover *pup = handle->popup_create_vars.arg;
 | 
				
			||||||
 | 
							block = pup->block;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x);
 | 
							uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x);
 | 
				
			||||||
		layout = UI_popover_layout(pup);
 | 
							layout = UI_popover_layout(pup);
 | 
				
			||||||
		UI_paneltype_draw(C, pt, layout);
 | 
							UI_paneltype_draw(C, pt, layout);
 | 
				
			||||||
		UI_popover_end(C, pup, NULL);
 | 
							UI_popover_end(C, pup, NULL);
 | 
				
			||||||
 | 
							block = pup->block;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (block) {
 | 
				
			||||||
 | 
							UI_block_active_only_flagged_buttons(C, CTX_wm_region(C), block);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return OPERATOR_INTERFACE;
 | 
						return OPERATOR_INTERFACE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -881,6 +881,16 @@ static void rna_UILayout_active_set(PointerRNA *ptr, bool value)
 | 
				
			|||||||
	uiLayoutSetActive(ptr->data, value);
 | 
						uiLayoutSetActive(ptr->data, value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool rna_UILayout_activate_init_get(PointerRNA *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return uiLayoutGetActivateInit(ptr->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rna_UILayout_activate_init_set(PointerRNA *ptr, bool value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uiLayoutSetActivateInit(ptr->data, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool rna_UILayout_alert_get(PointerRNA *ptr)
 | 
					static bool rna_UILayout_alert_get(PointerRNA *ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return uiLayoutGetRedAlert(ptr->data);
 | 
						return uiLayoutGetRedAlert(ptr->data);
 | 
				
			||||||
@@ -1056,6 +1066,13 @@ static void rna_def_ui_layout(BlenderRNA *brna)
 | 
				
			|||||||
	prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
 | 
						prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
 | 
				
			||||||
	RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
 | 
						RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prop = RNA_def_property(srna, "activate_init", PROP_BOOLEAN, PROP_NONE);
 | 
				
			||||||
 | 
						RNA_def_property_boolean_funcs(prop, "rna_UILayout_activate_init_get", "rna_UILayout_activate_init_set");
 | 
				
			||||||
 | 
						RNA_def_property_ui_text(
 | 
				
			||||||
 | 
						        prop, "Activate on Init",
 | 
				
			||||||
 | 
						        "When true, buttons defined in popups will be activated on first display "
 | 
				
			||||||
 | 
						        "(use so you can type into a field without having to click on it first)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
 | 
						prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
 | 
				
			||||||
	RNA_def_property_enum_items(prop, rna_enum_operator_context_items);
 | 
						RNA_def_property_enum_items(prop, rna_enum_operator_context_items);
 | 
				
			||||||
	RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
 | 
						RNA_def_property_enum_funcs(prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1154,6 +1154,8 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
 | 
				
			|||||||
	/* center around the mouse */
 | 
						/* center around the mouse */
 | 
				
			||||||
	UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2});
 | 
						UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UI_block_active_only_flagged_buttons(C, ar, block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return block;
 | 
						return block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1179,6 +1181,8 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	UI_block_bounds_set_popup(block, 4, NULL);
 | 
						UI_block_bounds_set_popup(block, 4, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UI_block_active_only_flagged_buttons(C, ar, block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return block;
 | 
						return block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user