58#define DT_IOPORDER_GRAPH_NODE_WIDTH DT_PIXEL_APPLY_DPI(260)
59#define DT_IOPORDER_GRAPH_NODE_STEP DT_PIXEL_APPLY_DPI(300)
60#define DT_IOPORDER_GRAPH_LEFT_MARGIN DT_PIXEL_APPLY_DPI(60)
61#define DT_IOPORDER_GRAPH_TOP_MARGIN DT_PIXEL_APPLY_DPI(68)
62#define DT_IOPORDER_GRAPH_MIN_WIDTH DT_PIXEL_APPLY_DPI(640)
63#define DT_IOPORDER_GRAPH_HEIGHT DT_PIXEL_APPLY_DPI(540)
64#define DT_IOPORDER_BAND_HEIGHT DT_PIXEL_APPLY_DPI(26)
65#define DT_IOPORDER_MASK_ARROW_OFFSET DT_PIXEL_APPLY_DPI(12)
66#define DT_IOPORDER_MASK_BOTTOM_MARGIN DT_PIXEL_APPLY_DPI(56)
122 GtkSelectionData *selection_data, guint info, guint time,
127 guint time, gpointer user_data);
129 guint time, gpointer user_data);
132 GtkSelectionData *selection_data, guint info, guint time,
151 for(GList *history = g_list_last(
dt_dev_get_global()->history); history; history = g_list_previous(history))
154 if(hitem && hitem->module == module)
return TRUE;
190 for(GList *nodes =
dt_dev_get_global()->preview_pipe->nodes; nodes; nodes = g_list_next(nodes))
193 if(piece && piece->module == module)
return piece;
210 return _(
"32-bit float");
212 return _(
"16-bit integer");
214 return _(
"8-bit integer");
217 return _(
"unknown type");
236 return _(
"Display RGB");
248 return _(
"unknown colorspace");
260 if(
IS_NULL_PTR(dsc))
return g_strdup(_(
"no runtime descriptor"));
264 if(dsc->
filters == 9u)
return g_strdup(_(
"X-Trans passthrough"));
265 if(dsc->
filters != 0u)
return g_strdup(_(
"Bayer passthrough"));
266 return g_strdup(_(
"no RAW flags"));
269 if(dsc->
filters == 9u)
return g_strdup(_(
"RAW X-Trans"));
270 if(dsc->
filters != 0u)
return g_strdup(_(
"RAW Bayer"));
271 return g_strdup(_(
"RAW monochrome"));
286 const char *display_colorspace)
289 return g_strdup_printf(_(
"%s:\n- runtime descriptor unavailable"), prefix);
292 gchar *text = g_strdup_printf(_(
"%s:\n\t- %s\n\t- %u channels\n\t- %s\n"
293 "\t- max RGB:\n\t\t%.3f\n\t\t%.3f\n\t\t%.3f\n\t- %s"),
295 display_colorspace ? display_colorspace : _(
"runtime unavailable"),
317 const gboolean colorin_crossed,
320 const gboolean after_module)
329 const gboolean in_pipeline_rgb = colorin_crossed || (after_module && !strcmp(module->
op,
"colorin"));
354 return _(
"Sensor RGB");
356 return _(
"Pipeline RGB");
358 return _(
"Display RGB");
360 return _(
"CIE Lab 1976");
362 return _(
"runtime unavailable");
367 return _(
"runtime unavailable");
384 *
color = (GdkRGBA){ 0.30, 0.30, 0.30, 0.90 };
387 *
color = (GdkRGBA){ 0.14, 0.56, 0.20, 0.96 };
390 *
color = (GdkRGBA){ 0.10, 0.38, 0.78, 0.96 };
393 *
color = (GdkRGBA){ 0.78, 0.38, 0.10, 0.96 };
396 *
color = (GdkRGBA){ 0.72, 0.54, 0.10, 0.96 };
402 *
color = (GdkRGBA){ 0.38, 0.38, 0.38, 0.90 };
421 if(profile_a == profile_b)
return TRUE;
442 const gboolean colorin_crossed,
445 const gboolean after_module)
453 const gboolean in_pipeline_rgb = colorin_crossed || (after_module && !strcmp(module->
op,
"colorin"));
475 if(
IS_NULL_PTR(label))
return g_strdup(_(
"runtime unavailable"));
479 if(
IS_NULL_PTR(profile_name) || profile_name[0] ==
'\0')
return g_strdup(label);
481 return g_strdup_printf(
"%s - %s", label, profile_name);
507 d->current_mode =
kind;
520 for(GList *l = presets; l; l = g_list_next(l))
523 const char *params = (
const char *)pr->
op_params;
525 const char *preset_name = pr->
name;
532 if(!g_strcmp0(iop_order_list, preset_text))
534 d->current_mode = index;
535 name = g_strdup(preset_name);
563 if(!
d->preset_combo ||
IS_NULL_PTR(
d->toolbar_label))
return;
567 gtk_label_set_text(GTK_LABEL(
d->toolbar_label), current_name);
569 d->refreshing_toolbar =
TRUE;
570 gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(
d->preset_combo));
571 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(
d->preset_combo),
"__custom__", _(
"custom order"));
573 gchar *active_id = g_strdup(
"__custom__");
578 for(GList *l = presets; l; l = g_list_next(l))
581 const char *preset_name = pr->
name;
582 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(
d->preset_combo), preset_name, preset_name);
583 if(!g_strcmp0(current_name, preset_name))
586 active_id = g_strdup(preset_name);
591 gtk_combo_box_set_active_id(GTK_COMBO_BOX(
d->preset_combo), active_id);
592 d->refreshing_toolbar =
FALSE;
607 GList *children = gtk_container_get_children(GTK_CONTAINER(
d->graph_fixed));
608 for(GList *iter = children; iter; iter = g_list_next(iter))
610 gtk_widget_destroy(GTK_WIDGET(iter->data));
612 g_list_free(children);
640 d->toolbar_label = NULL;
641 d->preset_combo = NULL;
642 d->graph_scroll = NULL;
643 d->graph_overlay = NULL;
644 d->graph_drawing = NULL;
645 d->graph_fixed = NULL;
646 d->drag_source = NULL;
702 if(!node || !node->module->gui || !GTK_IS_TOGGLE_BUTTON(node->module->gui->off))
return;
704 const gboolean active = gtk_toggle_button_get_active(togglebutton);
705 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(node->module->gui->off)) != active)
706 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(node->module->gui->off), active);
718 if(!node || !node->module->gui || !GTK_IS_TOGGLE_BUTTON(node->module->gui->mask_indicator))
return;
720 const gboolean active = gtk_toggle_button_get_active(togglebutton);
721 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(node->module->gui->mask_indicator)) != active)
722 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(node->module->gui->mask_indicator), active);
734 if(!node || !node->module)
return;
738 GDK_GRAVITY_SOUTH_EAST, GDK_GRAVITY_NORTH_EAST);
752 const char *display_in,
753 const char *display_out)
756 node->module =
module;
759 GtkWidget *event_box = gtk_event_box_new();
764 gchar **split_name = g_strsplit(clean_name,
"-", -1);
765 gchar *module_name = g_strjoinv(
" ", split_name);
766 GtkWidget *label = gtk_label_new(module_name);
768 GtkWidget *instance = gtk_label_new(instance_name);
775 gtk_widget_set_name(body,
"module-header");
779 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
782 gtk_widget_set_hexpand(event_box,
FALSE);
783 gtk_widget_set_halign(event_box, GTK_ALIGN_START);
786 gtk_label_set_text(GTK_LABEL(label), module_name);
787 gtk_widget_set_halign(label, GTK_ALIGN_START);
788 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
789 gtk_label_set_xalign(GTK_LABEL(label), 0.0f);
790 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
791 gtk_widget_set_name(label,
"iop-panel-label");
793 gtk_widget_set_halign(instance, GTK_ALIGN_START);
794 gtk_widget_set_visible(instance, instance_name[0] !=
'\0');
795 gtk_label_set_xalign(GTK_LABEL(instance), 0.0f);
796 gtk_label_set_ellipsize(GTK_LABEL(instance), PANGO_ELLIPSIZE_MIDDLE);
797 gtk_label_set_line_wrap(GTK_LABEL(instance),
FALSE);
800 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
enable), module->
enabled);
802 gtk_widget_set_valign(
enable, GTK_ALIGN_CENTER);
804 const gboolean show_masks = (
module->flags() & IOP_FLAGS_SUPPORTS_BLENDING) == IOP_FLAGS_SUPPORTS_BLENDING
805 && module->blend_params
806 && module->blend_params->mask_mode > DEVELOP_MASK_ENABLED;
807 const gboolean show_mask_preview =
module->request_mask_display
808 & (DT_DEV_PIXELPIPE_DISPLAY_MASK | DT_DEV_PIXELPIPE_DISPLAY_CHANNEL);
809 gtk_widget_set_visible(mask, show_masks);
810 gtk_widget_set_sensitive(mask, show_masks && module->
enabled);
811 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mask), show_mask_preview);
812 gtk_widget_set_valign(mask, GTK_ALIGN_CENTER);
813 gtk_widget_set_valign(presets, GTK_ALIGN_CENTER);
815 gtk_widget_set_tooltip_text(
enable, _(
"toggle module"));
816 gtk_widget_set_tooltip_text(mask, _(
"display mask"));
817 gtk_widget_set_tooltip_text(presets, _(
"module presets"));
820 gtk_box_pack_start(GTK_BOX(header), label,
TRUE,
TRUE, 0);
821 gtk_box_pack_end(GTK_BOX(header), presets,
FALSE,
FALSE, 0);
822 gtk_box_pack_end(GTK_BOX(header), mask,
FALSE,
FALSE, 0);
826 GtkWidget *info_in = gtk_label_new(text_in);
827 GtkWidget *info_out = gtk_label_new(text_out);
831 g_strfreev(split_name);
835 gtk_label_set_xalign(GTK_LABEL(info_in), 0.0f);
836 gtk_label_set_xalign(GTK_LABEL(info_out), 0.0f);
837 gtk_label_set_line_wrap(GTK_LABEL(info_in),
TRUE);
838 gtk_label_set_line_wrap(GTK_LABEL(info_out),
TRUE);
839 gtk_label_set_justify(GTK_LABEL(info_in), GTK_JUSTIFY_LEFT);
840 gtk_label_set_justify(GTK_LABEL(info_out), GTK_JUSTIFY_LEFT);
842 gtk_box_pack_start(GTK_BOX(body), header,
FALSE,
FALSE, 0);
843 gtk_box_pack_start(GTK_BOX(body), instance,
FALSE,
FALSE, 0);
844 gtk_box_pack_start(GTK_BOX(body), info_in,
FALSE,
FALSE, 0);
845 gtk_box_pack_start(GTK_BOX(body), info_out,
FALSE,
FALSE, 0);
846 gtk_container_add(GTK_CONTAINER(frame), body);
847 gtk_container_add(GTK_CONTAINER(event_box), frame);
860 g_object_set_data(G_OBJECT(event_box),
"dt-ioporder-module", module);
880 GtkWidget *event_box = gtk_event_box_new();
887 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
889 gtk_widget_set_halign(event_box, GTK_ALIGN_START);
890 gtk_widget_set_valign(event_box, GTK_ALIGN_CENTER);
895 gtk_widget_set_name(body,
"ioporder-endpoint");
899 gtk_widget_set_halign(title, GTK_ALIGN_CENTER);
900 gtk_widget_set_valign(title, GTK_ALIGN_CENTER);
901 gtk_label_set_xalign(GTK_LABEL(title), 0.5f);
902 gtk_widget_set_name(title,
"iop-panel-label");
904 gtk_box_pack_start(GTK_BOX(body), title,
TRUE,
TRUE, 0);
905 gtk_container_add(GTK_CONTAINER(frame), body);
906 gtk_container_add(GTK_CONTAINER(event_box), frame);
933 int visible_count = 0;
935 gboolean colorin_crossed =
FALSE;
937 const int base_x =
x;
940 int module_header_center_y = 0;
953 const char *display_in
956 const char *display_out
960 d->nodes = g_list_append(
d->nodes, node);
964 gtk_drag_dest_set(node->
event_box, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
976 if(module_header_center_y == 0)
978 GtkRequisition minimum = { 0 }, natural = { 0 };
979 gtk_widget_get_preferred_size(node->
header, &minimum, &natural);
985 if(!strcmp(module->op,
"colorin")) colorin_crossed =
TRUE;
988 if(module_header_center_y > 0)
989 endpoint_y = module_header_center_y - endpoint_height / 2;
992 d->nodes = g_list_prepend(
d->nodes, base_node);
993 gtk_fixed_put(GTK_FIXED(
d->graph_fixed), base_node->
event_box, base_x, endpoint_y);
994 gtk_widget_show_all(base_node->
event_box);
999 d->nodes = g_list_append(
d->nodes, screen_node);
1000 gtk_fixed_put(GTK_FIXED(
d->graph_fixed), screen_node->
event_box, screen_x, endpoint_y);
1001 gtk_widget_show_all(screen_node->
event_box);
1011 if(
d->window &&
d->graph_scroll)
1013 GdkDisplay *display = gtk_widget_get_display(
d->window);
1014 GdkWindow *
window = gtk_widget_get_window(
d->window);
1018 GdkMonitor *monitor = (display &&
window) ? gdk_display_get_monitor_at_window(display,
window) : NULL;
1021 monitor = gdk_display_get_primary_monitor(display);
1022 if(
IS_NULL_PTR(monitor) && gdk_display_get_n_monitors(display) > 0)
1023 monitor = gdk_display_get_monitor(display, 0);
1028 gdk_monitor_get_workarea(monitor, &
geometry);
1032 const int graph_width =
MIN(total_width, viewport_width);
1037 gtk_widget_set_size_request(
d->graph_scroll, graph_width, graph_height);
1038 gtk_window_resize(GTK_WINDOW(
d->window), wanted_width, wanted_height);
1040 gtk_widget_queue_draw(
d->graph_drawing);
1054 const double width,
const double height,
const double radius)
1058 cairo_new_sub_path(cr);
1059 cairo_arc(cr,
x +
width -
r, y +
r,
r, -M_PI_2, 0.0);
1062 cairo_arc(cr,
x +
r, y +
r,
r,
M_PI, 3.0 * M_PI_2);
1063 cairo_close_path(cr);
1079 PangoLayout *layout = gtk_widget_create_pango_layout(widget, text);
1080 cairo_move_to(cr,
x, y);
1081 pango_cairo_show_layout(cr, layout);
1082 g_object_unref(layout);
1095 const double x2,
const double y2)
1097 cairo_move_to(cr, x1, y1);
1098 cairo_line_to(cr, x2, y2);
1101 const double angle = atan2(y2 - y1, x2 - x1);
1104 cairo_move_to(cr, x2, y2);
1105 cairo_line_to(cr, x2 - arrow * cos(angle -
M_PI / 6.0), y2 - arrow * sin(angle -
M_PI / 6.0));
1106 cairo_move_to(cr, x2, y2);
1107 cairo_line_to(cr, x2 - arrow * cos(angle +
M_PI / 6.0), y2 - arrow * sin(angle +
M_PI / 6.0));
1122 const double dx,
const double dy)
1124 GtkAllocation area = { 0 };
1125 gtk_widget_get_allocation(widget, &area);
1127 const double span = fabs(dx - sx);
1130 const double c1x = sx + (dx - sx) * 0.25;
1131 const double c2x = sx + (dx - sx) * 0.75;
1133 cairo_move_to(cr, sx, sy);
1134 cairo_curve_to(cr, c1x, cy, c2x, cy, dx, dy);
1138 const double tx = dx - c2x;
1139 const double ty = dy - cy;
1140 const double angle = atan2(ty, tx);
1142 cairo_move_to(cr, dx, dy);
1143 cairo_line_to(cr, dx - arrow * cos(angle -
M_PI / 6.0), dy - arrow * sin(angle -
M_PI / 6.0));
1144 cairo_move_to(cr, dx, dy);
1145 cairo_line_to(cr, dx - arrow * cos(angle +
M_PI / 6.0), dy - arrow * sin(angle +
M_PI / 6.0));
1148 const double mx = (sx + dx) * 0.5;
1151 cairo_set_source_rgba(cr, 0.12, 0.12, 0.12, 0.85);
1155 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1177 GtkAllocation area = { 0 };
1178 gtk_widget_get_allocation(widget, &area);
1180 gtk_render_background(gtk_widget_get_style_context(widget), cr, 0.0, 0.0, area.width, area.height);
1184 cairo_set_source_rgb(cr, 0.85, 0.85, 0.85);
1186 _(
"No active or history modules are currently available."));
1194 gboolean colorin_crossed =
FALSE;
1198 gchar *segment_label = NULL;
1199 GdkRGBA segment_color = { 0 };
1200 double segment_x = 0.0;
1201 double segment_width = 0.0;
1204 for(GList *iter =
d->nodes; iter; iter = g_list_next(iter))
1208 GtkAllocation alloc = { 0 };
1209 gtk_widget_get_allocation(node->
event_box, &alloc);
1218 GdkRGBA band_color = { 0 };
1226 cairo_set_source_rgba(cr, segment_color.red, segment_color.green, segment_color.blue, segment_color.alpha);
1230 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1235 segment_kind = band_kind;
1237 segment_profile = profile_info;
1238 segment_label = band_text;
1239 segment_color = band_color;
1240 segment_x = alloc.x;
1241 segment_width = alloc.width;
1246 segment_width = alloc.x + alloc.width - segment_x;
1248 if(!strcmp(node->module->op,
"colorin")) colorin_crossed =
TRUE;
1253 cairo_set_source_rgba(cr, segment_color.red, segment_color.green, segment_color.blue, segment_color.alpha);
1257 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1262 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.22);
1266 for(GList *iter =
d->nodes; iter; iter = g_list_next(iter))
1271 GtkAllocation alloc = { 0 };
1272 gtk_widget_get_allocation(node->
event_box, &alloc);
1279 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.90);
1284 for(GList *iter =
d->nodes; iter && g_list_next(iter); iter = g_list_next(iter))
1288 GtkAllocation alloc_a = { 0 }, alloc_b = { 0 }, head_a = { 0 }, head_b = { 0 };
1289 gtk_widget_get_allocation(node_a->
event_box, &alloc_a);
1290 gtk_widget_get_allocation(node_b->
event_box, &alloc_b);
1291 gtk_widget_get_allocation(node_a->
header, &head_a);
1292 gtk_widget_get_allocation(node_b->
header, &head_b);
1293 const double arrow_y_a = node_a->
is_endpoint ? alloc_a.y + alloc_a.height * 0.5
1294 : alloc_a.y + head_a.y + head_a.height * 0.5;
1295 const double arrow_y_b = node_b->
is_endpoint ? alloc_b.y + alloc_b.height * 0.5
1296 : alloc_b.y + head_b.y + head_b.height * 0.5;
1304 cairo_set_source_rgba(cr, 0.95, 0.54, 0.13, 0.92);
1308 for(GList *iter =
d->nodes; iter; iter = g_list_next(iter))
1311 if(source->
is_endpoint || !source->module)
continue;
1312 GtkAllocation source_alloc = { 0 };
1313 gtk_widget_get_allocation(source->
event_box, &source_alloc);
1315 for(GList *consumers =
d->nodes; consumers; consumers = g_list_next(consumers))
1319 if(sink->module->raster_mask.sink.source != source->module)
continue;
1321 GtkAllocation sink_alloc = { 0 };
1322 gtk_widget_get_allocation(sink->
event_box, &sink_alloc);
1325 source_alloc.x + source_alloc.width * 0.5,
1327 sink_alloc.x + sink_alloc.width * 0.5,
1332 if(
d->drag_source &&
d->drag_dest &&
d->drag_source !=
d->drag_dest)
1334 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.95);
1338 for(GList *iter =
d->nodes; iter; iter = g_list_next(iter))
1341 if(node->module !=
d->drag_dest)
continue;
1343 GtkAllocation alloc = { 0 };
1344 gtk_widget_get_allocation(node->
event_box, &alloc);
1345 const double x =
d->drag_source->iop_order <
d->drag_dest->iop_order
1369 GtkSelectionData *selection_data, guint info, guint time,
1373 gtk_selection_data_set(selection_data, gdk_atom_intern(
"ioporder-node",
TRUE), 32,
1374 (
const guchar *)&
value, 1);
1388 d->drag_source = (
dt_iop_module_t *)g_object_get_data(G_OBJECT(widget),
"dt-ioporder-module");
1389 d->drag_dest = NULL;
1390 gtk_widget_queue_draw(
d->graph_drawing);
1404 d->drag_source = NULL;
1405 d->drag_dest = NULL;
1406 gtk_widget_queue_draw(
d->graph_drawing);
1421 guint time, gpointer user_data)
1428 gboolean can_move =
FALSE;
1429 if(module_src && module_dest && module_src != module_dest)
1437 d->drag_dest = can_move ? module_dest : NULL;
1438 gtk_widget_queue_draw(
d->graph_drawing);
1439 gdk_drag_status(dc, can_move ? GDK_ACTION_COPY : 0, time);
1455 guint time, gpointer user_data)
1457 gtk_drag_get_data(widget, dc, gdk_atom_intern(
"ioporder-node",
TRUE), time);
1473 d->drag_dest = NULL;
1474 gtk_widget_queue_draw(
d->graph_drawing);
1494 GtkSelectionData *selection_data, guint info, guint time,
1502 if(module_src && module_dest && module_src != module_dest)
1511 d->drag_source = NULL;
1512 d->drag_dest = NULL;
1528 GtkWidget *dialog = gtk_dialog_new_with_buttons(_(
"save module order preset"), parent,
1529 GTK_DIALOG_DESTROY_WITH_PARENT,
1530 _(
"_cancel"), GTK_RESPONSE_CANCEL,
1531 _(
"_save"), GTK_RESPONSE_ACCEPT, NULL);
1532 GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1535 gtk_entry_set_activates_default(GTK_ENTRY(entry),
TRUE);
1536 gtk_widget_set_hexpand(entry,
TRUE);
1537 gtk_widget_set_tooltip_text(entry, _(
"preset name"));
1539 gtk_widget_show_all(dialog);
1541 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
1544 if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1546 const char *preset_name = gtk_entry_get_text(GTK_ENTRY(entry));
1547 if(preset_name && preset_name[0] !=
'\0')
1550 void *params = self->get_params(self, &
size);
1557 gtk_widget_destroy(dialog);
1570 self->gui_reset(self);
1584 if(
d->refreshing_toolbar)
return;
1586 const gchar *preset_name = gtk_combo_box_get_active_id(combo);
1587 if(!preset_name || !strcmp(preset_name,
"__custom__"))
1606 if(
d->window)
return;
1613 GtkWidget *preset_combo = gtk_combo_box_text_new();
1615 GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
1617 GtkWidget *drawing = gtk_drawing_area_new();
1620 gtk_window_set_title(GTK_WINDOW(
window), _(
"module order"));
1623 gtk_window_set_destroy_with_parent(GTK_WINDOW(
window),
TRUE);
1626 gtk_widget_set_halign(label, GTK_ALIGN_START);
1627 gtk_label_set_xalign(GTK_LABEL(label), 0.0f);
1629 gtk_widget_set_hexpand(preset_combo,
TRUE);
1630 gtk_widget_set_hexpand(scroll,
TRUE);
1631 gtk_widget_set_vexpand(scroll,
TRUE);
1632 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1633 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN);
1639 gtk_box_pack_start(GTK_BOX(toolbar), label,
FALSE,
FALSE, 0);
1641 gtk_box_pack_start(GTK_BOX(toolbar), preset_combo,
TRUE,
TRUE, 0);
1644 gtk_overlay_add_overlay(GTK_OVERLAY(overlay), fixed);
1645 gtk_container_add(GTK_CONTAINER(overlay), drawing);
1646 gtk_container_add(GTK_CONTAINER(scroll), overlay);
1648 gtk_box_pack_start(GTK_BOX(root), toolbar,
FALSE,
FALSE, 0);
1649 gtk_box_pack_start(GTK_BOX(root), scroll,
TRUE,
TRUE, 0);
1650 gtk_container_add(GTK_CONTAINER(
window), root);
1652 g_signal_connect(
window,
"delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
1660 d->toolbar_label = label;
1661 d->preset_combo = preset_combo;
1662 d->graph_scroll = scroll;
1663 d->graph_overlay = overlay;
1664 d->graph_drawing = drawing;
1665 d->graph_fixed = fixed;
1686 gtk_widget_show_all(
d->window);
1687 gtk_window_present(GTK_WINDOW(
d->window));
1714 const char *changed_module = (
const char *)module_name;
1715 if(changed_module && strcmp(changed_module, self->
plugin_name) != 0)
return;
1723 return _(
"module order");
1728 static const char *
v[] = {
"special", NULL };
1750 self->
data = (
void *)
d;
1752 d->current_mode = -1;
1778 if(
d->window) gtk_widget_destroy(
d->window);
1800 char *params = NULL;
1856 *
size = (int)p_size;
GtkWidget * dt_gui_main_window(void)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static const dt_adaptation_t kind
static void add_preset(dt_iop_module_so_t *self, const char *name, const char *pi, const int version, const char *bpi, const int blendop_version)
const char * dt_colorspaces_get_name(dt_colorspaces_color_profile_type_t type, const char *filename)
Printable name for a profile identity, without touching the profile list.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
void reset(dt_view_t *self)
struct dt_develop_t * dt_dev_get_global(void)
struct dt_gui_gtk_t * dt_gui_get_global(void)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_input_profile_info(const struct dt_dev_pixelpipe_t *pipe)
gchar * dt_dev_get_multi_name(const struct dt_iop_module_t *module)
GtkWidget * geometry
its size, under the preview
void dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
static gboolean enable(const dt_image_t *image)
gboolean dt_iop_is_hidden(dt_iop_module_t *module)
gboolean dt_iop_gui_move_module_before(dt_iop_module_t *module, dt_iop_module_t *module_next, const char *reason)
Move a module before another one and commit the GUI-side effects.
gboolean dt_iop_gui_move_module_after(dt_iop_module_t *module, dt_iop_module_t *module_prev, const char *reason)
Move a module after another one and commit the GUI-side effects.
gboolean dt_iop_gui_commit_iop_order_change(dt_develop_t *dev, dt_iop_module_t *module, gboolean enable, gboolean write_history, const char *reason)
Commit the GUI-side consequences of an IOP-order change.
void * dt_ioppr_serialize_iop_order_list(GList *iop_order_list, size_t *size)
Serialize an order list into a binary blob (used for presets).
GList * dt_ioppr_get_iop_order_list_version(dt_iop_order_t version)
Return the built-in order list for a given version.
gboolean dt_ioppr_check_can_move_before_iop(GList *iop_list, dt_iop_module_t *module, dt_iop_module_t *module_next)
Validate whether module can be moved before module_next.
gboolean dt_ioppr_check_can_move_after_iop(GList *iop_list, dt_iop_module_t *module, dt_iop_module_t *module_prev)
Validate whether module can be moved after module_prev.
dt_iop_order_t dt_ioppr_get_iop_order_list_kind(GList *iop_order_list)
Determine the kind of an order list by inspecting its content.
char * dt_ioppr_serialize_text_iop_order_list(GList *iop_order_list)
Serialize an order list to a text representation.
const char * dt_iop_order_string(const dt_iop_order_t order)
Return the human-readable name for an IOP order enum value.
GList * dt_ioppr_deserialize_iop_order_list(const char *buf, size_t size)
Deserialize an order list from a binary blob.
void dt_ioppr_change_iop_order(struct dt_develop_t *dev, const int32_t imgid, GList *new_iop_list)
Replace the current order list with a new one and persist it.
static gboolean _ioporder_drag_drop(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, gpointer user_data)
Request the drag payload when dropping on a graph node.
static gchar * _ioporder_descriptor_to_text(const char *prefix, const dt_iop_buffer_dsc_t *dsc, const char *display_colorspace)
Build the descriptor list shown below each module node.
#define DT_IOPORDER_GRAPH_HEIGHT
static void _ioporder_free_graph_node(gpointer data)
Release one graph node descriptor.
void gui_reset(dt_lib_module_t *self)
#define DT_IOPORDER_GRAPH_LEFT_MARGIN
int set_params(dt_lib_module_t *self, const void *params, int size)
static gboolean _ioporder_module_in_history(const dt_iop_module_t *module)
Return TRUE when a module already exists in history.
void * get_params(dt_lib_module_t *self, int *size)
#define DT_IOPORDER_MASK_ARROW_OFFSET
static gchar * _ioporder_get_current_order_name(dt_lib_module_t *self)
Retrieve the display name of the current pipeline order.
static void _ioporder_add_preset(GtkButton *button, gpointer user_data)
Save the current pipeline order as a named preset.
static void _ioporder_init_popup(dt_lib_module_t *self)
Build the popup window lazily on first use.
#define DT_IOPORDER_BAND_HEIGHT
static dt_ioporder_runtime_band_kind_t _ioporder_runtime_band_kind(const gboolean raw_input, const gboolean colorin_crossed, const dt_iop_module_t *module, const dt_iop_buffer_dsc_t *dsc, const gboolean after_module)
Classify one runtime descriptor into a stable band kind.
static gboolean _ioporder_same_runtime_profile(const dt_iop_order_iccprofile_info_t *profile_a, const dt_iop_order_iccprofile_info_t *profile_b)
Compare two profile descriptors for lifecycle segment merging.
static const char * _ioporder_colorspace_to_string(const dt_iop_colorspace_type_t cst)
Return a human-readable colorspace string for a pixel descriptor.
#define DT_IOPORDER_MASK_BOTTOM_MARGIN
static void _ioporder_reset_order(GtkButton *button, gpointer user_data)
Reset the current order to the default v3.0 order.
static void _ioporder_set_enable_button_icon(GtkWidget *widget, dt_iop_module_t *module)
Apply the same enable-button icon policy used by module headers.
static void _ioporder_refresh_callback(gpointer instance, gpointer user_data)
Central refresh callback for develop-side state changes.
dt_ioporder_runtime_band_kind_t
@ DT_IOPORDER_RUNTIME_BAND_UNAVAILABLE
@ DT_IOPORDER_RUNTIME_BAND_LAB
@ DT_IOPORDER_RUNTIME_BAND_NONE
@ DT_IOPORDER_RUNTIME_BAND_PIPELINE_RGB
@ DT_IOPORDER_RUNTIME_BAND_RAW
@ DT_IOPORDER_RUNTIME_BAND_SENSOR_RGB
@ DT_IOPORDER_RUNTIME_BAND_DISPLAY_RGB
@ DT_IOPORDER_RUNTIME_BAND_OTHER
static void _ioporder_draw_rounded_rect(cairo_t *cr, const double x, const double y, const double width, const double height, const double radius)
Draw a filled rounded rectangle.
static void _ioporder_draw_label(GtkWidget *widget, cairo_t *cr, const double x, const double y, const char *text)
Draw a short label with the widget font on the graph background.
void show_popup(dt_lib_module_t *self)
Open the popup window owned by the ioporder lib.
static void _ioporder_draw_sequence_arrow(cairo_t *cr, const double x1, const double y1, const double x2, const double y2)
Draw a straight sequence arrow between two consecutive module nodes.
static void _ioporder_refresh_toolbar(dt_lib_module_t *self)
Refresh the preset combo and status label in the popup toolbar.
void gui_cleanup(dt_lib_module_t *self)
static void _ioporder_node_toggle_enable(GtkToggleButton *togglebutton, gpointer user_data)
Proxy the module enable state through the real darkroom header widget.
static void _ioporder_apply_preset(GtkComboBox *combo, gpointer user_data)
Apply the preset selected in the popup toolbar combo box.
static gboolean _ioporder_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, guint time, gpointer user_data)
Validate the potential drop target while dragging across graph nodes.
static dt_dev_pixelpipe_iop_t * _ioporder_get_preview_piece(dt_iop_module_t *module)
Map a module instance to its preview-pipe piece.
static void _ioporder_drag_leave(GtkWidget *widget, GdkDragContext *dc, guint time, gpointer user_data)
Clear drop feedback when leaving a graph node during drag.
static void _ioporder_runtime_band_color(const dt_ioporder_runtime_band_kind_t kind, GdkRGBA *color)
Pick the color used by the colorspace lifecycle band.
static dt_ioporder_graph_node_t * _ioporder_create_graph_node(dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, const char *display_in, const char *display_out)
Create one interactive graph node mirroring a module header.
static const char * _ioporder_type_to_string(const dt_iop_buffer_type_t datatype)
Return a human-readable datatype string for a pixel descriptor.
static const dt_iop_order_iccprofile_info_t * _ioporder_runtime_band_profile_info(const gboolean raw_input, const gboolean colorin_crossed, const dt_iop_module_t *module, const dt_iop_buffer_dsc_t *dsc, const gboolean after_module)
Pick the RGB profile metadata that matches one runtime band segment.
static void _ioporder_clear_graph(dt_lib_ioporder_t *d)
Destroy every node widget and free the node descriptors.
void init_presets(dt_lib_module_t *self)
#define DT_IOPORDER_GRAPH_NODE_STEP
static void _ioporder_rebuild_graph(dt_lib_module_t *self)
Refresh the full graph contents from the current darkroom pipeline.
static gchar * _ioporder_raw_flags_to_string(const dt_iop_buffer_dsc_t *dsc)
Format the RAW-specific flags carried by a pixel descriptor.
uint32_t container(dt_lib_module_t *self)
gboolean preset_autoapply(dt_lib_module_t *self)
static void _ioporder_draw_mask_arrow(GtkWidget *widget, cairo_t *cr, const double sx, const double sy, const double dx, const double dy)
Draw a curved raster-mask dependency arrow between two nodes.
static gchar * _ioporder_runtime_band_text(const char *label, const dt_iop_order_iccprofile_info_t *profile_info)
Build the text shown in one colorspace-band segment.
static dt_ioporder_graph_node_t * _ioporder_create_endpoint_node(const char *label)
Create a compact endpoint node used for the graph boundaries.
static void _ioporder_node_toggle_mask(GtkToggleButton *togglebutton, gpointer user_data)
Proxy raster/drawn mask preview toggling through the real module header.
static void _ioporder_node_show_presets(GtkButton *button, gpointer user_data)
Open the standard module preset popup from a graph node.
static const guint _ioporder_target_count
void gui_init(dt_lib_module_t *self)
#define DT_IOPORDER_GRAPH_MIN_WIDTH
const char ** views(dt_lib_module_t *self)
static void _ioporder_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
Track the module being dragged from the graph.
static void _ioporder_presets_changed_callback(gpointer instance, gpointer module_name, gpointer user_data)
Refresh the preset toolbar when ioporder presets change.
int expandable(dt_lib_module_t *self)
#define DT_IOPORDER_GRAPH_NODE_WIDTH
static gboolean _ioporder_module_is_graph_visible(const dt_iop_module_t *module)
Apply the active-pipe visibility policy used by modulegroups.
#define DT_IOPORDER_GRAPH_TOP_MARGIN
@ DT_IOPORDER_DND_TARGET_NODE
static gboolean _ioporder_graph_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
Paint the graph background, runtime bands, fences, and arrows.
static const char * _ioporder_runtime_band_label(const dt_ioporder_runtime_band_kind_t kind, const dt_iop_buffer_dsc_t *dsc)
Return the user-visible label for one runtime band kind.
static void _ioporder_popup_destroy(GtkWidget *widget, gpointer user_data)
Drop cached popup widget pointers once GTK destroys the popup.
static void _ioporder_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
Reset drag feedback when the source drag ends.
static void _ioporder_drag_data_received(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data)
Commit a module reorder after dropping on another graph node.
static const GtkTargetEntry _ioporder_target_list[]
static void _ioporder_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data)
Handle drag-data export for the graph node drag and drop.
gchar * delete_underscore(const char *s)
gboolean dt_handle_dialog_enter(GtkWidget *widget, GdkEventKey *event, gpointer data)
void dt_lib_presets_add(const char *name, const char *plugin_name, const int32_t version, const void *params, const int32_t params_size, gboolean readonly)
gboolean dt_lib_presets_apply(const gchar *preset, const gchar *module_name, int module_version)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
void dt_module_preset_free(gpointer data)
Release one dt_module_preset_t. Suits g_list_free_full().
GList * dt_preset_repository_list_all_versions(const char *operation)
Every preset of operation at ANY version, with rowid and op_version filled in, SHIPPED FIRST then by ...
GList * dt_preset_repository_list_for_version(const char *operation, const int op_version)
As above, restricted to one op_version. Same columns, same order.
data.presets: a module's saved parameters, with the conditions under which it auto-applies.
@ DT_COLORSPACE_NONE
No profile / "take it from the image settings". Never matches a list entry.
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_DEVELOP_INITIALIZE
This signal is raised when darktable.develop is initialized.
@ DT_SIGNAL_DEVELOP_HISTORY_CHANGE
This signal is raised when develop history is changed no param, no returned value.
@ DT_SIGNAL_DEVELOP_IMAGE_CHANGED
This signal is raised when image is changed in darkroom.
@ DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED
This signal is raised when develop preview pipe process is finished no param, no returned value.
@ DT_SIGNAL_DEVELOP_MODULE_MOVED
This signal is raised when order of modules in pipeline is changed.
@ DT_SIGNAL_PRESETS_CHANGED
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
static const dt_aligned_pixel_simd_t value
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_iop_buffer_type_t datatype
dt_aligned_pixel_t processed_maximum
int32_t hide_enable_button
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
dt_colorspaces_color_profile_type_t type
Profile identity, half of the memo key. DT_COLORSPACE_NONE means "unset" and makes every apply functi...
char filename[DT_IOP_COLOR_ICC_LEN]
ICC file name, the other half of the memo key; "" for every built-in. Compared with strcmp,...
dt_iop_module_t *dt_dev_pixelpipe_iop_t * piece
GtkWidget * toolbar_label
dt_iop_module_t * drag_dest
GtkWidget * graph_drawing
GtkWidget * graph_overlay
dt_iop_module_t * drag_source
gboolean refreshing_toolbar
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER