Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add shortcuts for focused module and sliders/combos/buttons and tabs in it #12829

Merged
merged 4 commits into from Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 92 additions & 8 deletions src/bauhaus/bauhaus.c
Expand Up @@ -49,6 +49,9 @@ enum
//DT_ACTION_ELEMENT_BUTTON = 1,
};

static const dt_action_def_t _action_def_slider, _action_def_combo,
_action_def_focus_slider, _action_def_focus_combo, _action_def_focus_button;

// INNER_PADDING is the horizontal space between slider and quad
// and vertical space between labels and slider baseline
static const double INNER_PADDING = 4.0;
Expand Down Expand Up @@ -757,6 +760,10 @@ void dt_bauhaus_init()
g_signal_connect(area, "button-release-event", G_CALLBACK (dt_bauhaus_popup_button_release), NULL);
g_signal_connect(area, "key-press-event", G_CALLBACK(dt_bauhaus_popup_key_press), NULL);
g_signal_connect(area, "scroll-event", G_CALLBACK(dt_bauhaus_popup_scroll), NULL);

dt_action_define(&darktable.control->actions_focus, NULL, N_("sliders"), NULL, &_action_def_focus_slider);
dt_action_define(&darktable.control->actions_focus, NULL, N_("dropdowns"), NULL, &_action_def_focus_combo);
dt_action_define(&darktable.control->actions_focus, NULL, N_("buttons"), NULL, &_action_def_focus_button);
}

void dt_bauhaus_cleanup()
Expand Down Expand Up @@ -925,9 +932,6 @@ float dt_bauhaus_slider_get_default(GtkWidget *widget)
return d->defpos;
}

extern const dt_action_def_t dt_action_def_slider;
extern const dt_action_def_t dt_action_def_combo;

dt_action_t *dt_bauhaus_widget_set_label(GtkWidget *widget, const char *section, const char *label)
{
dt_action_t *ac = NULL;
Expand All @@ -941,7 +945,7 @@ dt_action_t *dt_bauhaus_widget_set_label(GtkWidget *widget, const char *section,
if(!darktable.bauhaus->skip_accel || w->module->type != DT_ACTION_TYPE_IOP_INSTANCE)
{
ac = dt_action_define(w->module, section, label, widget,
w->type == DT_BAUHAUS_SLIDER ? &dt_action_def_slider : &dt_action_def_combo);
w->type == DT_BAUHAUS_SLIDER ? &_action_def_slider : &_action_def_combo);
if(w->module->type != DT_ACTION_TYPE_IOP_INSTANCE) w->module = ac;
}

Expand Down Expand Up @@ -3484,13 +3488,77 @@ static float _action_process_combo(gpointer target, dt_action_element_t element,
return - 1 - value + (value == effect - DT_ACTION_EFFECT_COMBO_SEPARATOR - 1 ? DT_VALUE_PATTERN_ACTIVE : 0);
}

const dt_action_element_def_t _action_elements_slider[]
static gboolean _find_nth_bauhaus(GtkWidget **w, int *num, dt_bauhaus_type_t type)
{
if(!gtk_widget_get_visible(*w))
return FALSE;
if(DT_IS_BAUHAUS_WIDGET(*w))
{
dt_bauhaus_widget_t *bhw = DT_BAUHAUS_WIDGET(*w);
return (bhw->type == type || (type == DT_BAUHAUS_BUTTON && bhw->quad_paint)) && !(*num)--;
}
if(GTK_IS_NOTEBOOK(*w) || GTK_IS_STACK(*w))
{
*w = GTK_IS_NOTEBOOK(*w)
? gtk_notebook_get_nth_page(GTK_NOTEBOOK(*w), gtk_notebook_get_current_page(GTK_NOTEBOOK(*w)))
: gtk_stack_get_visible_child(GTK_STACK(*w));
return _find_nth_bauhaus(w, num, type);
}
if(GTK_IS_CONTAINER(*w))
{
GList *l = gtk_container_get_children(GTK_CONTAINER(*w));
for(GList *c = l; c && *num >= 0; c = c->next)
{
*w = c->data;
_find_nth_bauhaus(w, num, type);
}
g_list_free(l);
}
return *num < 0;
}

static float _action_process_focus_slider(gpointer target, dt_action_element_t element, dt_action_effect_t effect, float move_size)
{
GtkWidget *widget = ((dt_iop_module_t *)target)->widget;
if(_find_nth_bauhaus(&widget, &element, DT_BAUHAUS_SLIDER))
return _action_process_slider(widget, DT_ACTION_ELEMENT_VALUE, effect, move_size);

if(!isnan(move_size)) dt_action_widget_toast(target, NULL, _("not that many sliders"));
return NAN;
}

static float _action_process_focus_combo(gpointer target, dt_action_element_t element, dt_action_effect_t effect, float move_size)
{
GtkWidget *widget = ((dt_iop_module_t *)target)->widget;
if(_find_nth_bauhaus(&widget, &element, DT_BAUHAUS_COMBOBOX))
return _action_process_combo(widget, DT_ACTION_ELEMENT_SELECTION, effect, move_size);

if(!isnan(move_size)) dt_action_widget_toast(target, NULL, _("not that many dropdowns"));
return NAN;
}

static float _action_process_focus_button(gpointer target, dt_action_element_t element, dt_action_effect_t effect, float move_size)
{
GtkWidget *widget = ((dt_iop_module_t *)target)->widget;
if(_find_nth_bauhaus(&widget, &element, DT_BAUHAUS_BUTTON))
{
if(!isnan(move_size))
_action_process_button(widget, effect);

return dt_bauhaus_widget_get_quad_active(widget);
}

if(!isnan(move_size)) dt_action_widget_toast(target, NULL, _("not that many buttons"));
return NAN;
}

static const dt_action_element_def_t _action_elements_slider[]
= { { N_("value"), dt_action_effect_value },
{ N_("button"), dt_action_effect_toggle },
{ N_("force"), dt_action_effect_value },
{ N_("zoom"), dt_action_effect_value },
{ NULL } };
const dt_action_element_def_t _action_elements_combo[]
static const dt_action_element_def_t _action_elements_combo[]
= { { N_("selection"), dt_action_effect_selection },
{ N_("button"), dt_action_effect_toggle },
{ NULL } };
Expand All @@ -3509,17 +3577,33 @@ static const dt_shortcut_fallback_t _action_fallbacks_combo[]
{ .move = DT_SHORTCUT_MOVE_VERTICAL, .effect = DT_ACTION_EFFECT_DEFAULT_MOVE, .speed = -1 },
{ } };

const dt_action_def_t dt_action_def_slider
static const dt_action_def_t _action_def_slider
= { N_("slider"),
_action_process_slider,
_action_elements_slider,
_action_fallbacks_slider };
const dt_action_def_t dt_action_def_combo
static const dt_action_def_t _action_def_combo
= { N_("dropdown"),
_action_process_combo,
_action_elements_combo,
_action_fallbacks_combo };

static const dt_action_def_t _action_def_focus_slider
= { N_("slider"),
_action_process_focus_slider,
DT_ACTION_ELEMENTS_NUM(value),
NULL, TRUE };
static const dt_action_def_t _action_def_focus_combo
= { N_("dropdown"),
_action_process_focus_combo,
DT_ACTION_ELEMENTS_NUM(selection),
NULL, TRUE };
static const dt_action_def_t _action_def_focus_button
= { N_("button"),
_action_process_focus_button,
DT_ACTION_ELEMENTS_NUM(toggle),
NULL, TRUE };

// clang-format off
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
// vim: shiftwidth=2 expandtab tabstop=2 cindent
Expand Down
1 change: 1 addition & 0 deletions src/bauhaus/bauhaus.h
Expand Up @@ -51,6 +51,7 @@ extern GType DT_BAUHAUS_WIDGET_TYPE;

typedef enum dt_bauhaus_type_t
{
DT_BAUHAUS_BUTTON = 0,
DT_BAUHAUS_SLIDER = 1,
DT_BAUHAUS_COMBOBOX = 2,
// TODO: all the fancy color sliders..
Expand Down
5 changes: 4 additions & 1 deletion src/control/control.c
Expand Up @@ -113,11 +113,14 @@ void dt_control_init(dt_control_t *s)
s->actions_format = (dt_action_t){ DT_ACTION_TYPE_SECTION, "format", C_("accel", "format") }; // will be placed under lib/export
s->actions_storage = (dt_action_t){ DT_ACTION_TYPE_SECTION, "storage", C_("accel", "storage")}; // will be placed under lib/export
s->actions_iops = (dt_action_t){ DT_ACTION_TYPE_CATEGORY, "iop", C_("accel", "processing modules"), .next = &s->actions_lua, .target = &s->actions_blend };
s->actions_blend = (dt_action_t){ DT_ACTION_TYPE_BLEND, "blend", C_("accel", "blending"), .owner = &s->actions_iops };
s->actions_blend = (dt_action_t){ DT_ACTION_TYPE_BLEND, "blend", C_("accel", "<blending>"), .owner = &s->actions_iops };
s->actions_lua = (dt_action_t){ DT_ACTION_TYPE_CATEGORY, "lua", C_("accel", "lua scripts"), .next = &s->actions_fallbacks };
s->actions_fallbacks = (dt_action_t){ DT_ACTION_TYPE_CATEGORY, "fallbacks", C_("accel", "fallbacks") };
s->actions = &s->actions_global;

s->actions_focus = (dt_action_t){ DT_ACTION_TYPE_IOP, "focus", C_("accel", "<focused>") };
dt_action_insert_sorted(&s->actions_iops, &s->actions_focus);

s->widgets = g_hash_table_new(NULL, NULL);
s->combo_introspection = g_hash_table_new(NULL, NULL);
s->combo_list = g_hash_table_new(NULL, NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/control/control.h
Expand Up @@ -129,7 +129,7 @@ typedef struct dt_control_t
dt_action_t *actions, actions_global,
actions_views, actions_thumb,
actions_libs, actions_format, actions_storage,
actions_iops, actions_blend,
actions_iops, actions_blend, actions_focus,
actions_lua, actions_fallbacks, *actions_modifiers;

GHashTable *widgets, *combo_introspection, *combo_list;
Expand Down
3 changes: 2 additions & 1 deletion src/develop/imageop.c
Expand Up @@ -2883,7 +2883,8 @@ dt_iop_module_t *dt_iop_get_module_preferred_instance(dt_iop_module_so_t *module
dt_iop_module_t *accel_mod = NULL; // The module to which accelerators are to be attached

// if any instance has focus, use that one
if(prefer_focused && darktable.develop->gui_module && darktable.develop->gui_module->so == module)
if(prefer_focused && darktable.develop->gui_module
&& (darktable.develop->gui_module->so == module || DT_ACTION(module) == &darktable.control->actions_focus))
accel_mod = darktable.develop->gui_module;
else
{
Expand Down
21 changes: 15 additions & 6 deletions src/gui/accelerators.c
Expand Up @@ -1269,10 +1269,10 @@ static void _fill_shortcut_fields(GtkTreeViewColumn *column, GtkCellRenderer *ce
case SHORTCUT_VIEW_EFFECT:
if(_shortcut_is_speed(s)) break;
elements = _action_find_elements(s->action);
if(elements && s->effect >= 0)
if(elements)
{
const gchar *cef = _action_find_effect_combo(s->action, &elements[s->element], s->effect);
if(cef || s->effect > 0 || s->action->type != DT_ACTION_TYPE_FALLBACK)
if(cef || s->effect > 0 || (s->effect == 0 && s->action->type != DT_ACTION_TYPE_FALLBACK))
field_text = g_strdup(Q_(cef ? cef : elements[s->element].effects[s->effect]));
if(s->effect == 0) weight = PANGO_WEIGHT_LIGHT;
editable = TRUE;
Expand Down Expand Up @@ -1302,7 +1302,7 @@ static void _fill_shortcut_fields(GtkTreeViewColumn *column, GtkCellRenderer *ce
{
dt_iop_module_so_t *iop = (dt_iop_module_so_t *)owner;

if(!(iop->flags() & IOP_FLAGS_ONE_INSTANCE))
if(owner != &darktable.control->actions_focus && !(iop->flags() & IOP_FLAGS_ONE_INSTANCE))
{
field_text = abs(s->instance) <= (NUM_INSTANCES - 1) /2
? g_strdup(_(instance_label[abs(s->instance)*2 - (s->instance > 0)]))
Expand Down Expand Up @@ -1614,7 +1614,8 @@ static gboolean _add_actions_to_tree(GtkTreeIter *parent, dt_action_t *action,
if(action->type == DT_ACTION_TYPE_IOP)
{
const dt_iop_module_so_t *module = (dt_iop_module_so_t *)action;
if(module->flags() & (IOP_FLAGS_HIDDEN | IOP_FLAGS_DEPRECATED))
if(action != &darktable.control->actions_focus
&& module->flags() & (IOP_FLAGS_HIDDEN | IOP_FLAGS_DEPRECATED))
continue;
}

Expand Down Expand Up @@ -3067,7 +3068,13 @@ static float _process_action(dt_action_t *action, int instance,
// find module instance
dt_iop_module_so_t *module = (dt_iop_module_so_t *)owner;

if(instance)
if(owner == &darktable.control->actions_focus)
{
action_target = darktable.develop->gui_module;
if(!action_target)
return return_value;
}
else if(instance)
{
int current_instance = abs(instance);

Expand Down Expand Up @@ -3935,7 +3942,9 @@ void dt_action_insert_sorted(dt_action_t *owner, dt_action_t *new_action)
while(*insertion_point
&& strcmp(new_action->id, "preset")
&& (!strcmp((*insertion_point)->id, "preset")
|| g_utf8_collate((*insertion_point)->label, new_action->label) < 0))
|| g_utf8_collate((*insertion_point)->label, new_action->label) <
(*((*insertion_point)->label) == '<' ? 1000 : 0) -
(*( new_action->label) == '<' ? 1000 : 0)))
{
insertion_point = &(*insertion_point)->next;
}
Expand Down
13 changes: 13 additions & 0 deletions src/gui/accelerators.h
Expand Up @@ -125,6 +125,19 @@ typedef struct dt_action_element_def_t
const gchar **effects;
} dt_action_element_def_t;

#define DT_ACTION_ELEMENTS_NUM(effect) \
(dt_action_element_def_t[]) \
{ { N_("1st"), dt_action_effect_##effect }, \
{ N_("2nd"), dt_action_effect_##effect }, \
{ N_("3rd"), dt_action_effect_##effect }, \
{ N_("4th"), dt_action_effect_##effect }, \
{ N_("5th"), dt_action_effect_##effect }, \
{ N_("6th"), dt_action_effect_##effect }, \
{ N_("7th"), dt_action_effect_##effect }, \
{ N_("8th"), dt_action_effect_##effect }, \
{ N_("9th"), dt_action_effect_##effect }, \
{} }

extern const dt_action_element_def_t dt_action_elements_hold[];

typedef struct dt_shortcut_fallback_t
Expand Down
31 changes: 31 additions & 0 deletions src/gui/gtk.c
Expand Up @@ -1438,6 +1438,8 @@ static void _init_widgets(dt_gui_gtk_t *gui)

}

static const dt_action_def_t _action_def_focus_tabs;

static void _init_main_table(GtkWidget *container)
{
GtkWidget *widget;
Expand Down Expand Up @@ -1577,6 +1579,8 @@ static void _init_main_table(GtkWidget *container)

/* initialize right panel */
_ui_init_panel_right(darktable.gui->ui, container);

dt_action_define(&darktable.control->actions_focus, NULL, N_("tabs"), NULL, &_action_def_focus_tabs);
}

GtkBox *dt_ui_get_container(struct dt_ui_t *ui, const dt_ui_container_t c)
Expand Down Expand Up @@ -2830,6 +2834,27 @@ static float _action_process_tabs(gpointer target, dt_action_element_t element,
return -1 - c + (c == element ? DT_VALUE_PATTERN_ACTIVE : 0);
}

static void _find_notebook(GtkWidget *widget, GtkWidget **p)
{
if(*p) return;
if(GTK_IS_NOTEBOOK(widget))
*p = widget;
else if(GTK_IS_CONTAINER(widget))
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)_find_notebook, p);
}

static float _action_process_focus_tabs(gpointer target, dt_action_element_t element, dt_action_effect_t effect, float move_size)
{
GtkWidget *widget = ((dt_iop_module_t *)target)->widget, *notebook = NULL;
_find_notebook(widget, &notebook);

if(notebook)
return _action_process_tabs(notebook, element, effect, move_size);

if(!isnan(move_size)) dt_action_widget_toast(target, NULL, _("does not contain pages"));
return NAN;
}

const gchar *dt_action_effect_tabs[]
= { N_("activate"),
N_("next"),
Expand Down Expand Up @@ -2935,6 +2960,12 @@ const dt_action_def_t dt_action_def_tabs_none
_action_process_tabs,
_action_elements_tabs_all_rgb + 4 };

static const dt_action_def_t _action_def_focus_tabs
= { N_("tabs"),
_action_process_focus_tabs,
DT_ACTION_ELEMENTS_NUM(tabs),
NULL, TRUE };

static gint _get_container_row_heigth(GtkWidget *w)
{
gint height = DT_PIXEL_APPLY_DPI(10);
Expand Down