Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/develop/develop.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ typedef struct dt_develop_t

// this module receives right-drag events if not already claimed
struct dt_iop_module_t *rotate;
// when set, left-click events are forwarded to proxy.rotate (used for fix horizon from quick access)
gboolean forward_left_click;

// modulegroups plugin hooks
struct
Expand Down
20 changes: 20 additions & 0 deletions src/dtgtk/paint.c
Original file line number Diff line number Diff line change
Expand Up @@ -3581,6 +3581,26 @@ void dtgtk_cairo_paint_snapshots_restore(cairo_t *cr, const gint x, const gint y
FINISH
}

void dtgtk_cairo_paint_horizon(cairo_t *cr, const gint x, const gint y, const gint w, const gint h, gint flags, void *data)
{
PREAMBLE(1, 1, 0, 0)

// horizon line (2px tall)
cairo_matrix_t matrix;
cairo_get_matrix(cr, &matrix);
cairo_set_line_width(cr, 2.0 / matrix.yy);
cairo_move_to(cr, 0.0, 0.55);
cairo_line_to(cr, 1.0, 0.55);
cairo_stroke(cr);

// sun half circle above horizon (2px thick, with 1px gap)
cairo_set_line_width(cr, 2.0 / matrix.yy);
cairo_arc_negative(cr, 0.5, 0.55 - 1.0 / matrix.yy, 0.22, 0, -M_PI);
cairo_stroke(cr);

FINISH
}

// 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
2 changes: 2 additions & 0 deletions src/dtgtk/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ void dtgtk_cairo_paint_filtering_menu(cairo_t *cr, gint x, gint y, gint w, gint

/** Paint an icon for snapshots restore button */
void dtgtk_cairo_paint_snapshots_restore(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data);
/** paint a horizon fix icon */
void dtgtk_cairo_paint_horizon(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data);

G_END_DECLS

Expand Down
110 changes: 108 additions & 2 deletions src/iop/ashift.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ typedef struct dt_iop_ashift_gui_data_t
GtkWidget *structure_quad;
GtkWidget *structure_lines;
gboolean straightening;
gboolean straighten_click_mode;
gboolean fix_horizon_active;
float straighten_x;
float straighten_y;
int fitting;
Expand Down Expand Up @@ -4817,10 +4819,52 @@ int button_pressed(dt_iop_module_t *self,
if(!dt_dev_get_preview_size(self->dev, &wd, &ht)) return 1;

// if we start to draw a straightening line
if(!g->lines && which == GDK_BUTTON_SECONDARY)
if(!g->lines
&& (which == GDK_BUTTON_SECONDARY
|| (g->fix_horizon_active && which == GDK_BUTTON_PRIMARY)))
{
dt_control_change_cursor("crosshair");

// click-click mode when fix horizon button is active and right-click
if(g->fix_horizon_active && which == GDK_BUTTON_SECONDARY)
{
if(g->straightening)
{
// second right-click: finalize the straightening
g->straightening = FALSE;
g->straighten_click_mode = FALSE;

const float angle = _calculate_straightening(self, pzx, pzy, g->straighten_x, g->straighten_y, wd, ht, zoom_scale);

dt_bauhaus_widget_set_quad_active(g->rotation, FALSE);
g->fix_horizon_active = FALSE;
darktable.develop->proxy.forward_left_click = FALSE;
dt_control_change_cursor("default");

if(angle != 0.0f)
{
const float n = dt_bauhaus_slider_get(g->rotation) - angle;
dt_bauhaus_slider_set(g->rotation, n);
dt_toast_log(_("rotation adjusted by %3.2f° to %3.2f°"), -angle, n);
}
dt_control_queue_redraw_center();
return TRUE;
}
else
{
// first right-click: record the first point
g->straightening = TRUE;
g->straighten_click_mode = TRUE;
g->straighten_x = pzx;
g->straighten_y = pzy;
dt_control_queue_redraw_center();
return TRUE;
}
}

// drag mode for left-click (with button active) or right-click (without button)
g->straightening = TRUE;
g->straighten_click_mode = FALSE;
g->straighten_x = pzx;
g->straighten_y = pzy;
return TRUE;
Expand Down Expand Up @@ -5059,10 +5103,22 @@ int button_released(dt_iop_module_t *self,

if(g->straightening)
{
// if in click-click mode, do nothing on release (waiting for second click)
if(g->straighten_click_mode) return TRUE;

g->straightening = FALSE;

const float bzx = g->straighten_x, bzy = g->straighten_y;
const float angle = _calculate_straightening(self, pzx, pzy, bzx, bzy, wd, ht, zoom_scale);

if(g->fix_horizon_active)
{
dt_bauhaus_widget_set_quad_active(g->rotation, FALSE);
g->fix_horizon_active = FALSE;
darktable.develop->proxy.forward_left_click = FALSE;
dt_control_change_cursor("default");
}

if(angle == 0.0f) return TRUE;

const float n = dt_bauhaus_slider_get(g->rotation) - angle;
Expand Down Expand Up @@ -5466,6 +5522,31 @@ static int _event_fit_both_button_clicked(GtkWidget *widget,
return FALSE;
}

static void _event_fix_horizon_quad_clicked(GtkWidget *widget,
dt_iop_module_t *self)
{
dt_iop_ashift_gui_data_t *g = self->gui_data;
g->fix_horizon_active = dt_bauhaus_widget_get_quad_active(widget);
if(!g->fix_horizon_active)
{
g->straightening = FALSE;
g->straighten_click_mode = FALSE;
dt_control_change_cursor("default");
}
else
{
if(self->off)
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->off), TRUE);
dt_bauhaus_widget_set_quad_active(widget, TRUE);
g->fix_horizon_active = TRUE;
}
dt_iop_request_focus(self);
dt_control_change_cursor("crosshair");
}
darktable.develop->proxy.forward_left_click = g->fix_horizon_active;
}

static int _event_structure_auto_clicked(GtkWidget *widget,
const GdkEventButton *event,
dt_iop_module_t *self)
Expand Down Expand Up @@ -5820,13 +5901,14 @@ static gboolean _event_draw(GtkWidget *widget,

void gui_focus(dt_iop_module_t *self, const gboolean in)
{
dt_iop_ashift_gui_data_t *g = self->gui_data;

darktable.develop->history_postpone_invalidate = in
&& dt_dev_modulegroups_test_activated(darktable.develop);

if(self->enabled)
{
dt_iop_ashift_params_t *p = self->params;
dt_iop_ashift_gui_data_t *g = self->gui_data;
if(in)
{
_shadow_crop_box(p,g);
Expand All @@ -5839,6 +5921,16 @@ void gui_focus(dt_iop_module_t *self, const gboolean in)
_do_clean_structure(self, p, TRUE);
}
}

if(!in && g->fix_horizon_active)
{
dt_bauhaus_widget_set_quad_active(g->rotation, FALSE);
g->fix_horizon_active = FALSE;
g->straightening = FALSE;
g->straighten_click_mode = FALSE;
darktable.develop->proxy.forward_left_click = FALSE;
dt_control_change_cursor("default");
}
}

static float log2_curve(const float inval, const dt_bauhaus_curve_t dir)
Expand Down Expand Up @@ -5953,6 +6045,8 @@ void gui_init(dt_iop_module_t *self)
g->jobcode = ASHIFT_JOBCODE_NONE;
g->jobparams = 0;
g->adjust_crop = FALSE;
g->fix_horizon_active = FALSE;
g->straighten_click_mode = FALSE;
g->lastx = g->lasty = -1.0f;
g->crop_cx = g->crop_cy = 1.0f;

Expand All @@ -5968,6 +6062,15 @@ void gui_init(dt_iop_module_t *self)
dt_shortcut_register(ac, 0, DT_ACTION_EFFECT_DOWN, GDK_KEY_bracketright, GDK_MOD1_MASK);
dt_shortcut_register(ac, 0, 0, GDK_KEY_r, GDK_MOD1_MASK);

dt_bauhaus_widget_set_quad_paint(g->rotation, dtgtk_cairo_paint_horizon, 0, NULL);
dt_bauhaus_widget_set_quad_toggle(g->rotation, TRUE);
g_signal_connect(G_OBJECT(g->rotation), "quad-pressed",
G_CALLBACK(_event_fix_horizon_quad_clicked), (gpointer)self);
dt_bauhaus_widget_set_quad_tooltip(g->rotation,
_("fix the horizon by drawing a line on the image\n\n"
"left-click and drag on the image\nOR\nright-click "
"to place the first point,\nthen right-click again to finish and rotate the image"));

g->cropmode = dt_bauhaus_combobox_from_params(self, "cropmode");
g_signal_connect(G_OBJECT(g->cropmode), "value-changed",
G_CALLBACK(cropmode_callback), self);
Expand Down Expand Up @@ -6152,7 +6255,10 @@ void gui_init(dt_iop_module_t *self)
void gui_cleanup(dt_iop_module_t *self)
{
if(darktable.develop->proxy.rotate == self)
{
darktable.develop->proxy.rotate = NULL;
darktable.develop->proxy.forward_left_click = FALSE;
}

const dt_iop_ashift_gui_data_t *g = self->gui_data;
if(g->lines) free(g->lines);
Expand Down
47 changes: 46 additions & 1 deletion src/views/darkroom.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,8 @@ void expose(dt_view_t *self,
// if dragging the rotation line, do it and nothing else
if(dev->proxy.rotate
&& (darktable.control->button_down_which == GDK_BUTTON_SECONDARY
|| dmod == dev->proxy.rotate))
|| dmod == dev->proxy.rotate
|| dev->proxy.forward_left_click))
{
// reminder, we want this to be exposed always for guidings
if(dev->proxy.rotate && dev->proxy.rotate->gui_post_expose)
Expand Down Expand Up @@ -3865,6 +3866,34 @@ void mouse_moved(dt_view_t *self,
pressure, which, zoom_scale);
}

// fix horizon: forward to proxy.rotate bypassing basics guard
if(dev->proxy.forward_left_click
&& !handled
&& !darktable.develop->darkroom_skip_mouse_events
&& !dt_iop_color_picker_is_visible(dev)
&& darktable.control->button_down
&& darktable.control->button_down_which == GDK_BUTTON_PRIMARY
&& dev->proxy.rotate)
{
_get_zoom_pos(&dev->full, x, y, &zoom_x, &zoom_y, &zoom_scale);
handled = dev->proxy.rotate->mouse_moved(dev->proxy.rotate, zoom_x, zoom_y,
pressure, which, zoom_scale);
}

// fix horizon click-click: forward mouse moves with no button held
// so the rubber-band line updates between the two right-clicks
if(dev->proxy.forward_left_click
&& !handled
&& !darktable.develop->darkroom_skip_mouse_events
&& !dt_iop_color_picker_is_visible(dev)
&& !darktable.control->button_down
&& dev->proxy.rotate)
{
_get_zoom_pos(&dev->full, x, y, &zoom_x, &zoom_y, &zoom_scale);
handled = dev->proxy.rotate->mouse_moved(dev->proxy.rotate, zoom_x, zoom_y,
pressure, which, zoom_scale);
}

// module
if(dev->gui_module && dev->gui_module->mouse_moved
&& !handled
Expand Down Expand Up @@ -3941,6 +3970,14 @@ int button_released(dt_view_t *self,
which, state, zoom_scale);
if(handled) return handled;
}
// fix horizon: forward to proxy.rotate bypassing basics guard
if(which == GDK_BUTTON_PRIMARY && dev->proxy.forward_left_click && dev->proxy.rotate)
{
_get_zoom_pos(&dev->full, x, y, &zoom_x, &zoom_y, &zoom_scale);
handled = dev->proxy.rotate->button_released(dev->proxy.rotate, zoom_x, zoom_y,
which, state, zoom_scale);
if(handled) return handled;
}
// masks
if(dev->form_visible)
{
Expand Down Expand Up @@ -4130,6 +4167,14 @@ int button_pressed(dt_view_t *self,
pressure, which, type, state);
if(handled) return handled;
}
// fix horizon: forward to proxy.rotate bypassing basics guard
if(dev->proxy.forward_left_click && which == GDK_BUTTON_PRIMARY && dev->proxy.rotate)
{
_get_zoom_pos(&dev->full, x, y, &zoom_x, &zoom_y, &zoom_scale);
handled = dev->proxy.rotate->button_pressed(dev->proxy.rotate, zoom_x, zoom_y,
pressure, which, type, state, zoom_scale);
if(handled) return handled;
}
// module
if(dev->gui_module && dev->gui_module->button_pressed
&& dt_dev_modulegroups_test_activated(darktable.develop))
Expand Down
Loading