Skip to content

Commit

Permalink
Merge pull request #17467 from dterrahe/leftrightdragindark
Browse files Browse the repository at this point in the history
support swapping left/right panels in darkroom
  • Loading branch information
TurboGit committed Sep 17, 2024
2 parents 3183980 + 4e326c8 commit d188e26
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 106 deletions.
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

0 comments on commit d188e26

Please sign in to comment.