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

support swapping left/right panels in darkroom #17467

Merged
merged 3 commits into from
Sep 17, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions data/darktableconfig.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,13 @@
<shortdescription>position of the scopes module</shortdescription>
<longdescription>position the scopes at the top-left or top-right of the screen</longdescription>
</dtconfig>
<dtconfig prefs="darkroom" section="modules">
<name>plugins/darkroom/panel_swap</name>
<type>bool</type>
<default>false</default>
<shortdescription>swap the utility and processing modules panels</shortdescription>
<longdescription>move the list of processing modules to the left of the screen</longdescription>
</dtconfig>
<dtconfig>
<name>plugins/darkroom/histogram/histogram</name>
<type>
Expand Down
32 changes: 13 additions & 19 deletions src/develop/imageop.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,18 +532,8 @@ static void _gui_delete_callback(GtkButton *button, dt_iop_module_t *module)
// we remove the plugin effectively
if(!dt_iop_is_hidden(module))
{
// we just hide the module to avoid lots of gtk critical warnings
gtk_widget_hide(module->expander);

// we move the module far away, to avoid problems when reordering instance after that
// FIXME: ?????
gtk_box_reorder_child(dt_ui_get_container(darktable.gui->ui,
DT_UI_CONTAINER_PANEL_RIGHT_CENTER),
module->expander, -1);

dt_iop_gui_cleanup_module(module);
gtk_widget_grab_focus(dt_ui_center(darktable.gui->ui));
gtk_widget_destroy(module->widget);
}

// we remove all references in the history stack and dev->iop
Expand Down Expand Up @@ -1731,7 +1721,6 @@ static void _init_module_so(void *m)
}

dt_iop_gui_cleanup_module(module_instance);
gtk_widget_destroy(module_instance->widget);
dt_iop_cleanup_module(module_instance);

darktable.control->accel_initialising = FALSE;
Expand Down Expand Up @@ -2199,6 +2188,7 @@ void dt_iop_gui_cleanup_module(dt_iop_module_t *module)
g_slist_free_full(module->widget_list, g_free);
module->widget_list = NULL;
module->gui_cleanup(module);
gtk_widget_destroy(module->expander ?: module->widget);
dt_iop_gui_cleanup_blending(module);
}

Expand Down Expand Up @@ -2985,13 +2975,15 @@ GtkWidget *dt_iop_gui_header_button(dt_iop_module_t *module,
static gboolean _on_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, dt_iop_module_t *dest)
{
gdk_drag_status(dc, 0, time);
dtgtk_expander_set_drag_hover(DTGTK_EXPANDER(widget), FALSE, TRUE, time);

GtkWidget *src_widget = gtk_widget_get_ancestor(gtk_drag_get_source_widget(dc),
DTGTK_TYPE_EXPANDER);
GtkWidget *src_header = gtk_drag_get_source_widget(dc);
if(!src_header) return TRUE;
GtkWidget *src_expander = gtk_widget_get_ancestor(src_header, DTGTK_TYPE_EXPANDER);

dt_iop_module_t *src = NULL;
for(GList *iop = darktable.develop->iop; iop; iop = iop->next)
if(((dt_iop_module_t *)iop->data)->expander == src_widget)
if(((dt_iop_module_t *)iop->data)->expander == src_expander)
src = iop->data;
if(!src || dest == src) return TRUE;

Expand All @@ -3011,11 +3003,13 @@ static gboolean _on_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, g

if(x != DND_DROP)
{
gboolean allow = src->iop_order < dest->iop_order
? dt_ioppr_check_can_move_after_iop(darktable.develop->iop, src, dest)
: dt_ioppr_check_can_move_before_iop(darktable.develop->iop, src, dest);
dtgtk_expander_set_drag_hover(DTGTK_EXPANDER(widget), allow, !above);
if(allow) gdk_drag_status(dc, GDK_ACTION_COPY, time);
if(src->iop_order < dest->iop_order
? dt_ioppr_check_can_move_after_iop(darktable.develop->iop, src, dest)
: dt_ioppr_check_can_move_before_iop(darktable.develop->iop, src, dest))
{
dtgtk_expander_set_drag_hover(DTGTK_EXPANDER(widget), TRUE, !above, time);
gdk_drag_status(dc, GDK_ACTION_COPY, time);
}
}
else
{
Expand Down
20 changes: 12 additions & 8 deletions src/dtgtk/expander.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,23 +183,25 @@ static void _expander_resize(GtkWidget *widget, GdkRectangle *allocation, gpoint
+ dt_conf_get_int("darkroom/ui/transition_duration") * 1000), NULL);
}

void dtgtk_expander_set_drag_hover(GtkDarktableExpander *expander, gboolean hover, gboolean below)
void dtgtk_expander_set_drag_hover(GtkDarktableExpander *expander, gboolean allow, gboolean below, guint time)
{
GtkWidget *widget = expander ? GTK_WIDGET(expander) : _drop_widget;
// don't remove drop zone when switching between last expander and empty space to avoid jitter
static guint hovertime;
guint time = gtk_get_current_event_time();
if(!widget || (!hover && widget == _drop_widget && time == hovertime)) return;
static guint last_time;
if(!widget || (!allow && !below && widget == _drop_widget && time == last_time)) return;

dt_gui_remove_class(widget, "module_drop_after");
dt_gui_remove_class(widget, "module_drop_before");

if(hover)
if(allow || below)
{
_drop_widget = widget;
hovertime = time;
_last_expanded = NULL;
last_time = time;

if(below)
if(!allow)
gtk_widget_queue_resize(widget);
else if(below)
dt_gui_add_class(widget, "module_drop_before");
else
dt_gui_add_class(widget, "module_drop_after");
Expand All @@ -211,7 +213,7 @@ static void _expander_drag_leave(GtkDarktableExpander *widget,
guint time,
gpointer user_data)
{
dtgtk_expander_set_drag_hover(widget, FALSE, FALSE);
dtgtk_expander_set_drag_hover(widget, FALSE, FALSE, time);
}

// FIXME: default highlight for the dnd is barely visible
Expand All @@ -226,6 +228,7 @@ static void _expander_drag_begin(GtkWidget *widget, GdkDragContext *context, gpo

// hack to render not transparent
dt_gui_add_class(widget, "module_drag_icon");
gtk_widget_size_allocate(widget, &allocation);
gtk_widget_draw(widget, cr);
dt_gui_remove_class(widget, "module_drag_icon");

Expand All @@ -244,6 +247,7 @@ static void _expander_drag_begin(GtkWidget *widget, GdkDragContext *context, gpo

static void _expander_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
dtgtk_expander_set_drag_hover(NULL, FALSE, FALSE, 0);
_drop_widget = NULL;
gtk_widget_set_opacity(widget, 1.0);
}
Expand Down
2 changes: 1 addition & 1 deletion src/dtgtk/expander.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ GtkWidget *dtgtk_expander_get_body_event_box(GtkDarktableExpander *expander);

void dtgtk_expander_set_expanded(GtkDarktableExpander *expander, gboolean expanded);
gboolean dtgtk_expander_get_expanded(GtkDarktableExpander *expander);
void dtgtk_expander_set_drag_hover(GtkDarktableExpander *expander, gboolean hover, gboolean below);
void dtgtk_expander_set_drag_hover(GtkDarktableExpander *expander, gboolean allow, gboolean below, guint time);

GtkWidget *dtgtk_expander_new(GtkWidget *header, GtkWidget *body);

Expand Down
69 changes: 28 additions & 41 deletions src/gui/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,13 @@ static void _init_main_table(GtkWidget *container)
N_("tabs"), NULL, &_action_def_focus_tabs);
}

void dt_ui_container_swap_left_right(struct dt_ui_t *ui,
gboolean swap)
{
if(swap ^ strcmp("left", gtk_widget_get_name(gtk_widget_get_ancestor(*ui->containers, DTGTK_TYPE_SIDE_PANEL))))
for(GtkWidget **c = ui->containers; c < ui->containers + 3; c++) {GtkWidget *tmp = *c; *c = c[3]; c[3] = tmp;}
}

GtkBox *dt_ui_get_container(struct dt_ui_t *ui,
const dt_ui_container_t c)
{
Expand Down Expand Up @@ -2212,16 +2219,17 @@ static gboolean _ui_init_panel_container_center_scroll_event(GtkWidget *widget,
!= dt_conf_get_bool("darkroom/ui/sidebar_scroll_default"));
}

static gboolean _on_drag_motion_drop(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, gboolean drop)
static gboolean _on_drag_motion_drop(GtkWidget *empty, GdkDragContext *dc, gint x, gint y, guint time, gboolean drop)
{
GtkWidget *widget = gtk_widget_get_parent(empty);
if(drop) gtk_widget_set_opacity(gtk_drag_get_source_widget(dc), 1.0);

gboolean ret = TRUE;
gpointer last = NULL;
for(GList *m = gtk_container_get_children(GTK_CONTAINER(widget)); m; m = g_list_delete_link(m, m))
if(gtk_widget_get_visible(GTK_WIDGET(m->data))) last = m->data;
if(m->data != empty && gtk_widget_get_visible(GTK_WIDGET(m->data))) last = m->data;
if(last)
g_signal_emit_by_name(last, "drag-motion", dc, drop ? -1 : x, y, time, &ret);
g_signal_emit_by_name(last, "drag-motion", dc, drop ? -1 : x, G_MAXINT, time, &ret);
else if(dt_view_get_current() == DT_VIEW_DARKROOM)
gdk_drag_status(dc, 0, time); // don't allow dropping in empty panel on other side
else if(drop)
Expand All @@ -2240,7 +2248,7 @@ static gboolean _on_drag_motion_drop(GtkWidget *widget, GdkDragContext *dc, gint

static void _on_drag_leave(GtkWidget *widget, GdkDragContext *dc, guint time, gpointer user_data)
{
dtgtk_expander_set_drag_hover(NULL, FALSE, FALSE);
dtgtk_expander_set_drag_hover(NULL, FALSE, FALSE, time);
}

static gboolean _remove_modules_visibility(gpointer key,
Expand Down Expand Up @@ -2303,23 +2311,11 @@ static gboolean _side_panel_press(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
if(event->button.button != GDK_BUTTON_SECONDARY
|| !GTK_IS_VIEWPORT(gtk_get_event_widget(event)))
return FALSE;

_add_remove_modules(NULL);
if(event->button.button == GDK_BUTTON_SECONDARY)
_add_remove_modules(NULL);
return TRUE;
}

static gboolean _side_panel_motion(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
gtk_widget_set_tooltip_text(widget, GTK_IS_VIEWPORT(gtk_get_event_widget(event))
? _("right-click to show/hide modules") : NULL);
return FALSE;
}

static gboolean _side_panel_draw(GtkWidget *widget,
cairo_t *cr,
gpointer user_data)
Expand All @@ -2333,15 +2329,9 @@ static GtkWidget *_ui_init_panel_container_center(GtkWidget *container,
const gboolean left)
{
GtkWidget *widget;
GtkAdjustment *a[4];

a[0] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 10, 10));
a[1] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 10, 10));
a[2] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 10, 10));
a[3] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 10, 10));

/* create the scrolled window */
widget = gtk_scrolled_window_new(a[0], a[1]);
widget = gtk_scrolled_window_new(NULL, GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 10, 10)));
gtk_widget_set_can_focus(widget, TRUE);
gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(widget),
left ? GTK_CORNER_TOP_LEFT : GTK_CORNER_TOP_RIGHT);
Expand All @@ -2358,35 +2348,32 @@ static GtkWidget *_ui_init_panel_container_center(GtkWidget *container,
: darktable.gui->widgets.left_border),
"scroll-event", G_CALLBACK(_borders_scrolled), widget);

/* create the scrolled viewport */
container = widget;
widget = gtk_viewport_new(a[2], a[3]);
gtk_viewport_set_shadow_type(GTK_VIEWPORT(widget), GTK_SHADOW_NONE);
gtk_container_add(GTK_CONTAINER(container), widget);

/* avoid scrolling with wheel, it's distracting (you'll end up over
* a control, and scroll it's value) */
g_signal_connect(G_OBJECT(widget), "scroll-event",
G_CALLBACK(_ui_init_panel_container_center_scroll_event),
NULL);
g_signal_connect(widget, "button-press-event", G_CALLBACK(_side_panel_press), NULL);
g_signal_connect(widget, "motion-notify-event", G_CALLBACK(_side_panel_motion), NULL);
gtk_widget_add_events(widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
dt_action_t *ac = dt_action_define(&darktable.control->actions_global, NULL,
N_("show/hide modules"), widget, NULL);
dt_action_register(ac, NULL, _add_remove_modules, 0, 0);

/* create the container */
container = widget;
widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_name(widget, "plugins_vbox_left");
gtk_container_add(GTK_CONTAINER(container), widget);
gtk_drag_dest_set(widget, 0, NULL, 0, GDK_ACTION_COPY);
g_signal_connect(widget, "drag-motion", G_CALLBACK(_on_drag_motion_drop), GINT_TO_POINTER(FALSE));
g_signal_connect(widget, "drag-drop", G_CALLBACK(_on_drag_motion_drop), GINT_TO_POINTER(TRUE));
g_signal_connect(widget, "drag-leave", G_CALLBACK(_on_drag_leave), NULL);
g_signal_connect_swapped(widget, "draw", G_CALLBACK(_side_panel_draw), NULL);

GtkWidget *empty = gtk_event_box_new();
gtk_widget_set_tooltip_text(empty, _("right-click to show/hide modules"));
gtk_box_pack_end(GTK_BOX(widget), empty, TRUE, TRUE, 0);
gtk_drag_dest_set(empty, 0, NULL, 0, GDK_ACTION_COPY);
g_signal_connect(empty, "drag-motion", G_CALLBACK(_on_drag_motion_drop), GINT_TO_POINTER(FALSE));
g_signal_connect(empty, "drag-drop", G_CALLBACK(_on_drag_motion_drop), GINT_TO_POINTER(TRUE));
g_signal_connect(empty, "drag-leave", G_CALLBACK(_on_drag_leave), NULL);
g_signal_connect(empty, "button-press-event", G_CALLBACK(_side_panel_press), NULL);
gtk_widget_add_events(empty, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
dt_action_t *ac = dt_action_define(&darktable.control->actions_global, NULL,
N_("show/hide modules"), empty, NULL);
dt_action_register(ac, NULL, _add_remove_modules, 0, 0);

return widget;
}

Expand Down
7 changes: 3 additions & 4 deletions src/gui/gtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ typedef struct dt_gui_widgets_t
GtkWidget *bottom_border;
GtkWidget *top_border;

/* left panel */
GtkGrid *panel_left; // panel grid 3 rows, top,center,bottom and file on center
GtkGrid *panel_right;

/* resize of left/right panels */
gboolean panel_handle_dragging;
int panel_handle_x, panel_handle_y;
Expand Down Expand Up @@ -324,6 +320,9 @@ typedef enum dt_ui_border_t
DT_UI_BORDER_SIZE
} dt_ui_border_t;

/** \brief swap the container in the left and right panels */
void dt_ui_container_swap_left_right(struct dt_ui_t *ui,
gboolean swap);
/** \brief add's a widget to a defined container */
void dt_ui_container_add_widget(struct dt_ui_t *ui,
const dt_ui_container_t c,
Expand Down
1 change: 0 additions & 1 deletion src/libs/history.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,6 @@ static gboolean _check_deleted_instances(dt_develop_t *dev,
// this is copied from dt_iop_gui_delete_callback(), not sure
// why the above sentence...
dt_iop_gui_cleanup_module(mod);
gtk_widget_destroy(mod->widget);
}

iop_list = g_list_remove_link(iop_list, modules);
Expand Down
11 changes: 6 additions & 5 deletions src/libs/ioporder.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ int position(const dt_lib_module_t *self)
return 880;
}

void update(dt_lib_module_t *self)
static void _update(dt_lib_module_t *self)
{
dt_lib_ioporder_t *d = (dt_lib_ioporder_t *)self->data;

if(self->arrow) gtk_widget_destroy(self->arrow);
self->arrow = NULL;

const dt_iop_order_t kind =
dt_ioppr_get_iop_order_list_kind(darktable.develop->iop_order_list);

Expand Down Expand Up @@ -123,7 +126,7 @@ static void _image_loaded_callback(gpointer instance, gpointer user_data)
if(dt_view_get_current() == DT_VIEW_DARKROOM)
{
dt_lib_module_t *self = (dt_lib_module_t *)user_data;
update(self);
_update(self);
}
}

Expand All @@ -132,8 +135,6 @@ void gui_init(dt_lib_module_t *self)
dt_lib_ioporder_t *d = (dt_lib_ioporder_t *)malloc(sizeof(dt_lib_ioporder_t));

self->data = (void *)d;
self->no_control_widgets = TRUE;

d->current_mode = -1;
d->last_custom_iop_order = NULL;

Expand Down Expand Up @@ -224,7 +225,7 @@ int set_params(dt_lib_module_t *self, const void *params, int size)

dt_dev_pixelpipe_rebuild(darktable.develop);

update(self);
_update(self);

g_list_free_full(iop_order_list, free);
return 0;
Expand Down
Loading
Loading