UI: support enum key shortcut detection

Shows shortcuts in space-selector.
This commit is contained in:
Campbell Barton 2018-11-29 17:32:35 +11:00
parent a740cc53ea
commit 8055871e5b
1 changed files with 81 additions and 22 deletions

View File

@ -90,6 +90,7 @@
/* prototypes. */
static void ui_but_to_pixelrect(struct rcti *rect, const struct ARegion *ar, struct uiBlock *block, struct uiBut *but);
static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *but_p);
/* avoid unneeded calls to ui_but_value_get */
#define UI_BUT_VALUE_UNSET DBL_MAX
@ -1067,12 +1068,35 @@ static bool ui_but_event_property_operator_string(
"WM_OT_context_menu_enum",
NULL
};
const size_t num_ops = sizeof(ctx_toggle_opnames) / sizeof(const char *);
const char *ctx_enum_opnames[] = {
"WM_OT_context_set_enum",
NULL
};
int prop_enum_value = -1;
bool prop_enum_value_ok = false;
PointerRNA *ptr = &but->rnapoin;
PropertyRNA *prop = but->rnaprop;
if ((but->type == UI_BTYPE_BUT_MENU) && (but->block->handle != NULL)) {
uiBut *but_parent = but->block->handle->popup_create_vars.but;
if ((but->type == UI_BTYPE_BUT_MENU) &&
but_parent && (but_parent->menu_create_func == ui_def_but_rna__menu))
{
prop_enum_value = (int)but->hardmin;
ptr = &but->block->handle->popup_create_vars.but->rnapoin;
prop = but->block->handle->popup_create_vars.but->rnaprop;
prop_enum_value_ok = true;
}
}
bool found = false;
/* Don't use the button again. */
but = NULL;
/* this version is only for finding hotkeys for properties (which get set via context using operators) */
if (but->rnaprop) {
if (prop) {
/* to avoid massive slowdowns on property panels, for now, we only check the
* hotkeys for Editor / Scene settings...
*
@ -1081,40 +1105,51 @@ static bool ui_but_event_property_operator_string(
// TODO: value (for enum stuff)?
char *data_path = NULL;
if (but->rnapoin.id.data) {
ID *id = but->rnapoin.id.data;
if (ptr->id.data) {
ID *id = ptr->id.data;
if (GS(id->name) == ID_SCR) {
/* screen/editor property
* NOTE: in most cases, there is actually no info for backwards tracing
* how to get back to ID from the editor data we may be dealing with
*/
if (RNA_struct_is_a(but->rnapoin.type, &RNA_Space)) {
if (RNA_struct_is_a(ptr->type, &RNA_Space)) {
/* data should be directly on here... */
data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(but->rnaprop));
data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop));
}
else if (RNA_struct_is_a(ptr->type, &RNA_Area)) {
/* data should be directly on here... */
const char *prop_id = RNA_property_identifier(prop);
/* Hack since keys access 'type'. */
if (STREQ(prop_id, "ui_type")) {
prop_id = "type";
prop_enum_value >>= 16;
prop = RNA_struct_find_property(ptr, prop_id);
}
data_path = BLI_sprintfN("area.%s", prop_id);
}
else {
/* special exceptions for common nested data in editors... */
if (RNA_struct_is_a(but->rnapoin.type, &RNA_DopeSheet)) {
if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) {
/* dopesheet filtering options... */
data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(but->rnaprop));
data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop));
}
else if (RNA_struct_is_a(but->rnapoin.type, &RNA_FileSelectParams)) {
else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) {
/* Filebrowser options... */
data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(but->rnaprop));
data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop));
}
}
}
else if (GS(id->name) == ID_SCE) {
if (RNA_struct_is_a(but->rnapoin.type, &RNA_ToolSettings)) {
if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) {
/* toolsettings property
* NOTE: toolsettings is usually accessed directly (i.e. not through scene)
*/
data_path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
data_path = RNA_path_from_ID_to_property(ptr, prop);
}
else {
/* scene property */
char *path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop);
char *path = RNA_path_from_ID_to_property(ptr, prop);
if (path) {
data_path = BLI_sprintfN("scene.%s", path);
@ -1123,7 +1158,7 @@ static bool ui_but_event_property_operator_string(
#if 0
else {
printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
__func__, RNA_property_identifier(but->rnaprop));
__func__, RNA_property_identifier(prop));
}
#endif
}
@ -1132,26 +1167,50 @@ static bool ui_but_event_property_operator_string(
//puts("other id");
}
//printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(but->rnaprop), data_path);
//printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path);
}
/* we have a datapath! */
if (data_path) {
size_t i;
/* create a property to host the "datapath" property we're sending to the operators */
IDProperty *prop_path;
IDProperty *prop_path_value;
IDPropertyTemplate val = {0};
prop_path = IDP_New(IDP_GROUP, &val, __func__);
prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1);
IDP_AddToGroup(prop_path, prop_path_value);
IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1));
const char **opnames;
int opnames_len;
if (prop_enum_value_ok && prop && RNA_property_type(prop) == PROP_ENUM) {
opnames_len = ARRAY_SIZE(ctx_enum_opnames) - 1;
opnames = ctx_enum_opnames;
const EnumPropertyItem *item;
bool free;
RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free);
int index = RNA_enum_from_value(item, prop_enum_value);
if (index != -1) {
const char *id = item[index].identifier;
IDP_AddToGroup(prop_path, IDP_NewString(id, "value", strlen(id) + 1));
}
else {
opnames_len = 0; /* Do nothing. */
}
if (free) {
MEM_freeN((void *)item);
}
}
else {
opnames_len = ARRAY_SIZE(ctx_toggle_opnames) - 1;
opnames = ctx_toggle_opnames;
}
/* check each until one works... */
for (i = 0; (i < num_ops) && (ctx_toggle_opnames[i]); i++) {
for (int i = 0; (i < opnames_len) && (opnames[i]); i++) {
if (WM_key_event_operator_string(
C, ctx_toggle_opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false,
C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false,
buf, buf_len))
{
found = true;