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

po/colorpicker edit - edit area & point #17051

Merged
merged 3 commits into from
Nov 16, 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
34 changes: 34 additions & 0 deletions src/gui/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -4405,6 +4405,40 @@ void dt_gui_process_events()
continue;
}

void dt_gui_simulate_button_event(GtkWidget *widget,
const GdkEventType eventtype,
const int button)
{
gboolean res = FALSE;

// Create the event GdkEventButton
GdkEventButton event;
memset(&event, 0, sizeof(event));

event.type = eventtype;
event.window = gtk_widget_get_window(widget);
event.send_event = TRUE;
event.time = GDK_CURRENT_TIME;
event.x = 0; // not important in this case
event.y = 0; // not important in this case
event.button = button;
event.device =
gdk_seat_get_pointer(gdk_display_get_default_seat(gdk_display_get_default()));

if (event.window != NULL)
{
g_object_ref(event.window);
}

// send signal
g_signal_emit_by_name(G_OBJECT(widget), "button-press-event", &event, &res, NULL);

if (event.window != NULL)
{
g_object_unref(event.window);
}
}

// 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
5 changes: 5 additions & 0 deletions src/gui/gtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ void dt_gui_cursor_clear_busy();
// (i.e. the current function will do a lot of work before returning)
void dt_gui_process_events();

// Simulate a mouse button event (button is 1, 2, 3 - mouse button) sent to a Widget
void dt_gui_simulate_button_event(GtkWidget *widget,
const GdkEventType eventtype,
const int button);

#ifdef __cplusplus
} // extern "C"
#endif /* __cplusplus */
Expand Down
130 changes: 122 additions & 8 deletions src/libs/colorpicker.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ typedef struct dt_lib_colorpicker_t
GtkWidget *add_sample_button;
GtkWidget *display_samples_check_box;
dt_colorpicker_sample_t primary_sample;
dt_colorpicker_sample_t *target_sample;
} dt_lib_colorpicker_t;

const char *name(dt_lib_module_t *self)
Expand Down Expand Up @@ -91,6 +92,48 @@ int position(const dt_lib_module_t *self)
return 800;
}

#if 0
// kept for debug session
static void _dump_sample(char* ctx, dt_colorpicker_sample_t *sample)
{
const gboolean isbox = sample->size == DT_LIB_COLORPICKER_SIZE_BOX;
printf(">>> %s KIND : %s (%lx)\n", ctx, isbox ? "box" : "point", (uint64_t)sample);
printf(" ");
if(isbox)
{
for(int k = 0; k < 8; k++)
printf("%1.2f ", sample->box[k]);
}
else
{
printf("%1.2f %1.2f", sample->point[0], sample->point[1]);
}
printf("\n");
}

static void _dump(char* ctx, dt_lib_module_t *self)
{
dt_lib_colorpicker_t *data = self->data;

{
char *txt = g_strdup_printf("primary sample (%s)", ctx);
_dump_sample(txt, &data->primary_sample);
g_free(txt);
}

int k = 0;
for(GSList *samples = darktable.lib->proxy.colorpicker.live_samples;
samples;
samples = g_slist_next(samples))
{
char *txt = g_strdup_printf("live sample (%d)", ++k);
dt_colorpicker_sample_t *sample = samples->data;
_dump_sample(txt, sample);
g_free(txt);
}
}
#endif

// GUI callbacks

static gboolean _sample_draw_callback(GtkWidget *widget,
Expand Down Expand Up @@ -121,6 +164,23 @@ static gboolean _sample_draw_callback(GtkWidget *widget,
}
}

// if the sample is locked we want to add a lock
if(sample->copied)
{
const int border = DT_PIXEL_APPLY_DPI(2);
const int icon_width = width - 2 * border;
const int icon_height = height - 2 * border;
if(icon_width > 0 && icon_height > 0)
{
GdkRGBA fg_color;
gtk_style_context_get_color(gtk_widget_get_style_context(widget),
gtk_widget_get_state_flags(widget), &fg_color);

gdk_cairo_set_source_rgba(cr, &fg_color);
dtgtk_cairo_paint_store(cr, border, border, icon_width, icon_height, 0, NULL);
}
}

return FALSE;
}

Expand Down Expand Up @@ -219,6 +279,16 @@ static gboolean _large_patch_toggle(GtkWidget *widget,
static void _picker_button_toggled(GtkToggleButton *button,
dt_lib_colorpicker_t *data)
{
const gboolean is_active = gtk_toggle_button_get_active(button);

// reset copy target
if(!is_active && data->target_sample)
{
gtk_widget_queue_draw(data->target_sample->container);
data->target_sample->copied = FALSE;
data->target_sample = NULL;
}

gtk_widget_set_sensitive(GTK_WIDGET(data->add_sample_button),
gtk_toggle_button_get_active(button));
}
Expand Down Expand Up @@ -458,18 +528,54 @@ static gboolean _live_sample_button(GtkWidget *widget,
// copy to active picker
dt_lib_module_t *self = darktable.lib->proxy.colorpicker.module;
dt_iop_color_picker_t *picker = darktable.lib->proxy.colorpicker.picker_proxy;
dt_lib_colorpicker_t *data = self->data;

// no active picker, too much iffy GTK work to activate a default
if(!picker) return FALSE;
const gboolean is_active =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->picker_button));
const gboolean simulate_event = !is_active || data->target_sample;

if(sample->size == DT_LIB_COLORPICKER_SIZE_POINT)
_set_sample_point(self, sample->point);
else if(sample->size == DT_LIB_COLORPICKER_SIZE_BOX)
_set_sample_box_area(self, sample->box);
if(data->target_sample)
{
// we have a target sample, so we are editing a live sample.
// copy back the edited sample (primary_sample) into the target
// sample on which we clicked.
memcpy(&sample->point,
&data->primary_sample.point,
sizeof(data->primary_sample.point));
memcpy(&sample->box,
&data->primary_sample.box,
sizeof(data->primary_sample.box));

sample->size = data->primary_sample.size;
data->target_sample->copied = FALSE;
data->target_sample = NULL;
}
else
return FALSE;
{
// we don't have a target sample, copy the sample into
// the primary sample to be edited.
data->target_sample = sample;
sample->copied = TRUE;
darktable.lib->proxy.colorpicker.module = self;

if(sample->size == DT_LIB_COLORPICKER_SIZE_POINT)
_set_sample_point(self, sample->point);
else if(sample->size == DT_LIB_COLORPICKER_SIZE_BOX)
_set_sample_box_area(self, sample->box);
}

if(picker->module)
if(simulate_event)
{
dt_gui_simulate_button_event
(data->picker_button,
GDK_BUTTON_PRESS,
/* button 1 to create use a point and 3 for a box */
data->primary_sample.size == DT_LIB_COLORPICKER_SIZE_POINT
? 1
: 3);
}

if(picker && picker->module)
{
picker->module->dev->preview_pipe->status = DT_DEV_PIXELPIPE_DIRTY;
}
Expand All @@ -491,8 +597,16 @@ static void _add_sample(GtkButton *widget,
dt_lib_colorpicker_t *data = self->data;
dt_colorpicker_sample_t *sample = malloc(sizeof(dt_colorpicker_sample_t));

// reset copy target
if(data->target_sample)
{
data->target_sample->copied = FALSE;
data->target_sample = NULL;
}

memcpy(sample, &data->primary_sample, sizeof(dt_colorpicker_sample_t));
sample->locked = FALSE;
sample->copied = FALSE;

sample->container = gtk_event_box_new();
gtk_widget_add_events(sample->container,
Expand Down
2 changes: 1 addition & 1 deletion src/libs/colorpicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef struct dt_colorpicker_sample_t
gboolean pick_output;
// NOTE: only applies to live samples
gboolean locked;
gboolean copied;

/** The actual picked colors */
// picked color in display profile, as picked from preview pixelpipe
Expand All @@ -76,4 +77,3 @@ typedef struct dt_colorpicker_sample_t
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

Loading