70#ifdef GDK_WINDOWING_WAYLAND
71#include <gdk/gdkwayland.h>
73#ifdef GDK_WINDOWING_QUARTZ
168 int formid, gboolean cursor_at_end);
173 return _(
"Shape Manager");
181 static const char *
v[] = {
"special", NULL};
227 if(G_VALUE_TYPE(&gv) == G_TYPE_POINTER)
228 *
module = (dt_iop_module_t *)g_value_get_pointer(&gv);
236 *groupid = g_value_get_int(&gv);
244 *formid = g_value_get_int(&gv);
257 = (
dt_masks_type_t)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item),
"masks-shape-type"));
267 if(!
IS_NULL_PTR(item)) g_object_set_data(G_OBJECT(item),
"masks-shape-type", GINT_TO_POINTER(
type));
284 for(
const GList *
m = owners;
m;
m = g_list_next(
m))
294 const int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),
"formid"));
321 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
322 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
325 GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
326 for(
const GList *
row = rows;
row;
row = g_list_next(
row))
329 if(!gtk_tree_model_get_iter(
model, &iter, (GtkTreePath *)
row->data))
continue;
333 if(
id > 0 &&
IS_NULL_PTR(g_list_find(ids, GINT_TO_POINTER(
id)))) ids = g_list_prepend(ids, GINT_TO_POINTER(
id));
335 g_list_free_full(rows, (GDestroyNotify)gtk_tree_path_free);
337 return g_list_reverse(ids);
362 g_snprintf(mask->name,
sizeof(mask->name),
"Group %u",
371 for(
const GList *
id = ids; id;
id = g_list_next(
id))
399 g_strlcat(str, form->
name, str_size);
403 for(
const GList *modules =
dt_dev_get_global()->iop; modules; modules = g_list_next(modules))
409 for(
const GList *pts = grp->
points; pts; pts = g_list_next(pts))
415 if(nbuse == 0) g_strlcat(str,
" (", str_size);
416 g_strlcat(str,
" ", str_size);
418 g_strlcat(str, module_label, str_size);
424 if(nbuse > 0) g_strlcat(str,
" )", str_size);
429 GtkTreeModel *
model, GtkTreeIter *iter,
int index)
437 g_snprintf(str,
sizeof(str),
"%s %d%%",
438 form->
name, (
int)(opacity * 100));
442 g_strlcpy(str, form->
name,
sizeof(str));
445 GdkPixbuf *icop = NULL;
446 GdkPixbuf *icinv = NULL;
536 = (
dt_masks_state_t)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item),
"masks-operation"));
543 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
544 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
546 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
547 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
549 GtkTreePath *item = (GtkTreePath *)items_iter->data;
551 if(gtk_tree_model_get_iter(
model, &iter, item))
571 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
596 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
597 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
599 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
600 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
602 GtkTreePath *item = (GtkTreePath *)items_iter->data;
604 if(gtk_tree_model_get_iter(
model, &iter, item))
615 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
636 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
637 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
639 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
640 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
642 GtkTreePath *item = (GtkTreePath *)items_iter->data;
644 if(gtk_tree_model_get_iter(
model, &iter, item))
655 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
676 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
677 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
680 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
681 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
683 GtkTreePath *item = (GtkTreePath *)items_iter->data;
685 if(gtk_tree_model_get_iter(
model, &iter, item))
695 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
720 while(gtk_tree_model_iter_parent(
model, &parent, &iter))
733 GtkTreeModel *
model = NULL;
734 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
735 GList *rows = gtk_tree_selection_get_selected_rows(selection, &
model);
740 if(gtk_tree_model_get_iter(
model, &iter, (GtkTreePath *)rows->data))
743 g_list_free_full(rows, (GDestroyNotify)gtk_tree_path_free);
758 if(group_id <= 0 || fid <= 0)
return FALSE;
774 gboolean has_shapes =
FALSE;
803 const int group_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item),
"group-formid"));
808 gboolean added =
FALSE;
809 for(
const GList *
id = ids; id;
id = g_list_next(
id))
811 const int fid = GPOINTER_TO_INT(id->data);
839 GtkTreeModel *
model, GtkTreeIter *iter, gpointer data)
843 gboolean on_row =
FALSE;
845 g_object_set(renderer,
"visible", on_row, NULL);
849 gtk_cell_renderer_set_sensitive(renderer, available);
852 if(!
IS_NULL_PTR(icon)) g_object_set(renderer,
"pixbuf", icon, NULL);
861 gtk_widget_queue_draw(list->
treeview);
875 const gboolean had_focus = gtk_window_is_active(GTK_WINDOW(lm->
popup_window));
891 if(GTK_IS_EDITABLE(editable)) gtk_editable_set_position(GTK_EDITABLE(editable), -1);
895 GtkCellEditable *editable,
const gchar *path
__attribute__((unused)),
920 GtkTreeIter *iter, GtkTreePath *path,
const gboolean cursor_at_end)
925 gboolean editable =
FALSE;
927 if(!editable)
return;
933 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(list->
treeview), path, list->
name_col,
952 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
953 if(!GTK_IS_TREE_MODEL(
model))
return G_SOURCE_REMOVE;
956 if(!gtk_tree_model_get_iter_first(
model, &iter))
return G_SOURCE_REMOVE;
962 if(fid != formid)
continue;
964 GtkTreePath *path = gtk_tree_model_get_path(
model, &iter);
968 gtk_tree_path_free(path);
970 return G_SOURCE_REMOVE;
971 }
while(gtk_tree_model_iter_next(
model, &iter));
973 return G_SOURCE_REMOVE;
987 const int formid,
const gboolean cursor_at_end)
1017 const gchar *path_string, GtkListStore *
store)
1020 if(!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(
store), &iter, path_string))
return;
1022 gboolean checked =
FALSE;
1023 gboolean sensitive =
TRUE;
1028 if(!sensitive)
return;
1035 GtkListStore *
store)
1037 if(event->type != GDK_BUTTON_PRESS || event->button != GDK_BUTTON_PRIMARY)
return FALSE;
1039 GtkTreePath *path = NULL;
1040 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path,
1044 gchar *path_string = gtk_tree_path_to_string(path);
1045 gtk_tree_path_free(path);
1064 if(event->type != GDK_BUTTON_PRESS)
return FALSE;
1066 const GdkWindow *
const toplevel = gtk_widget_get_window(dialog);
1067 for(GdkWindow *w = event->window; !
IS_NULL_PTR(w); w = gdk_window_get_parent(w))
1068 if(w == toplevel)
return FALSE;
1070 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
1080 for(gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(
store), &iter); valid;
1081 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(
store), &iter))
1083 gboolean checked =
FALSE;
1084 gboolean was_checked =
FALSE;
1089 if(
IS_NULL_PTR(module) || checked == was_checked)
continue;
1091 GList **target = checked ? to_attach : to_detach;
1092 *target = g_list_prepend(*target, module);
1095 *to_attach = g_list_reverse(*to_attach);
1096 *to_detach = g_list_reverse(*to_detach);
1131 G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
1134 const char *noun = info.
is_group ? _(
"group") : _(
"shape");
1136 gboolean any =
FALSE;
1137 for(
const GList *iops = g_list_last(
dt_dev_get_global()->iop); iops; iops = g_list_previous(iops))
1142 const int own_id =
module->blend_params->mask_id;
1148 const gboolean is_self_mask = (own_id == info.
formid);
1151 const gboolean attached
1161 gboolean sensitive =
TRUE;
1166 note = g_strdup(_(
"this is the module's own mask"));
1178 note = g_strdup_printf(_(
"Already in '%s'"), holder_name);
1180 note = g_strdup(_(
"this group holds the module's own mask"));
1182 note = g_strdup(_(
"the module already applies every shape of this group"));
1187 gtk_list_store_append(
store, &iter);
1199 g_object_unref(
store);
1200 dt_control_log(_(
"No module in the pipeline can carry a drawn mask."));
1207 gchar *title = g_strdup_printf(_(
"Modules using this %s"), noun);
1208 GtkWidget *dialog = gtk_dialog_new_with_buttons(title, parent,
1209 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1210 _(
"Cancel"), GTK_RESPONSE_CANCEL,
1211 _(
"Apply"), GTK_RESPONSE_ACCEPT, NULL);
1213 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
1217 gtk_window_set_keep_above(GTK_WINDOW(dialog),
TRUE);
1219 gtk_widget_add_events(dialog, GDK_BUTTON_PRESS_MASK);
1222 GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1226 gchar *intro = g_strdup_printf(_(
"Tick the modules that should use the %s '%s', untick the ones "
1227 "that should stop."), noun, info.
name);
1230 gtk_box_pack_start(GTK_BOX(content), label,
FALSE,
FALSE, 0);
1232 GtkWidget *treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(
store));
1233 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview),
FALSE);
1234 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_NONE);
1236 GtkTreeViewColumn *col = gtk_tree_view_column_new();
1237 gtk_tree_view_column_set_expand(col,
TRUE);
1239 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
1240 g_object_set(renderer,
"activatable",
TRUE, NULL);
1242 gtk_tree_view_column_pack_start(col, renderer,
FALSE);
1246 renderer = gtk_cell_renderer_text_new();
1247 gtk_tree_view_column_pack_start(col, renderer,
TRUE);
1248 gtk_tree_view_column_add_attribute(col, renderer,
"text",
MODCHOOSER_NAME);
1254 renderer = gtk_cell_renderer_text_new();
1255 g_object_set(renderer,
"style", PANGO_STYLE_ITALIC,
"xalign", 1.0f, NULL);
1256 gtk_cell_renderer_set_sensitive(renderer,
FALSE);
1257 gtk_tree_view_column_pack_end(col, renderer,
FALSE);
1258 gtk_tree_view_column_add_attribute(col, renderer,
"text",
MODCHOOSER_NOTE);
1260 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
1264 gtk_box_pack_start(GTK_BOX(content),
1269 gtk_widget_show_all(dialog);
1270 const gint response = gtk_dialog_run(GTK_DIALOG(dialog));
1274 gtk_widget_destroy(dialog);
1275 g_object_unref(
store);
1278 return response == GTK_RESPONSE_ACCEPT;
1291 *own_id = own_info.
formid;
1333 GList *to_attach = NULL;
1334 GList *to_detach = NULL;
1337 gboolean changed =
FALSE;
1341 for(
const GList *
m = to_detach;
m;
m = g_list_next(
m))
1353 for(
const GList *
m = to_attach;
m;
m = g_list_next(
m))
1356 int own_id =
module->blend_params->mask_id;
1378 g_list_free(to_attach);
1379 g_list_free(to_detach);
1380 if(!changed)
return;
1460 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
1461 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
1462 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
1464 GtkTreePath *item = (GtkTreePath *)
items->data;
1466 if(gtk_tree_model_get_iter(
model, &iter, item))
1496 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
1505 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
1507 if(!gtk_tree_model_get_iter_from_string(
model, &iter, path_string))
return;
1517 const gchar *text = strlen(new_text) == 0 ?
" " : new_text;
1521 g_strlcpy(form->
name, text,
sizeof(form->
name));
1549 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bd->
masks_edit),
TRUE);
1571 const int nb = gtk_tree_selection_count_selected_rows(selection);
1580 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
1583 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
1584 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
1586 GtkTreePath *item = (GtkTreePath *)items_iter->data;
1588 if(!gtk_tree_model_get_iter(
model, &iter, item))
continue;
1597 if(nb == 1) selected_form = form;
1603 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
1635 GList *children = gtk_container_get_children(GTK_CONTAINER(menu));
1636 const GList *last = g_list_last(children);
1637 const gboolean needed = !
IS_NULL_PTR(last) && !GTK_IS_SEPARATOR_MENU_ITEM(last->data);
1638 g_list_free(children);
1640 if(needed) gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1648 GtkWidget *add_item = gtk_menu_item_new_with_label(_(
"Add new shape ..."));
1649 gtk_menu_item_set_submenu(GTK_MENU_ITEM(add_item), add_menu);
1650 gtk_menu_shell_append(menu, add_item);
1666 gboolean any =
FALSE;
1667 GtkWidget *shapes_menu = gtk_menu_new();
1669 for(
const GList *forms =
dt_dev_get_global()->forms; forms; forms = g_list_next(forms))
1677 char str[10000] =
"";
1680 GtkWidget *item = gtk_menu_item_new_with_label(str);
1681 g_object_set_data(G_OBJECT(item),
"formid", GUINT_TO_POINTER(info.
formid));
1682 g_signal_connect(G_OBJECT(item),
"activate", G_CALLBACK(
_tree_add_exist), grp);
1684 gtk_menu_shell_append(GTK_MENU_SHELL(shapes_menu), item);
1690 gtk_widget_destroy(shapes_menu);
1694 GtkWidget *item = gtk_menu_item_new_with_label(_(
"Attach shape ..."));
1695 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), shapes_menu);
1696 gtk_menu_shell_append(menu, item);
1717 GtkWidget *groups_menu = gtk_menu_new();
1718 gboolean any =
FALSE;
1719 for(guint
g = 0;
g < count;
g++)
1723 gboolean joinable =
FALSE;
1724 for(
const GList *
id = ids;
id && !joinable;
id = g_list_next(
id))
1728 g_object_set_data(G_OBJECT(item),
"group-formid", GINT_TO_POINTER(
groups[
g].formid));
1730 gtk_widget_set_sensitive(item, joinable);
1731 gtk_menu_shell_append(GTK_MENU_SHELL(groups_menu), item);
1737 GtkWidget *item = gtk_menu_item_new_with_label(_(
"Attach to the group"));
1738 gtk_menu_shell_append(menu, item);
1740 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), groups_menu);
1743 gtk_widget_destroy(groups_menu);
1744 gtk_widget_set_sensitive(item,
FALSE);
1766 GtkWidget *item = gtk_menu_item_new_with_label(_(
"Operation"));
1768 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), op_submenu);
1769 gtk_menu_shell_append(menu, item);
1771 item = gtk_menu_item_new_with_label(_(
"Invert shape"));
1774 gtk_menu_shell_append(GTK_MENU_SHELL(op_submenu), item);
1779 gtk_menu_shell_append(GTK_MENU_SHELL(op_submenu), gtk_separator_menu_item_new());
1780 for(
size_t i = 0;
i <
sizeof(combine) /
sizeof(combine[0]);
i++)
1782 item = gtk_menu_item_new_with_label(_(combine[
i].label));
1783 g_object_set_data(G_OBJECT(item),
"masks-operation", GINT_TO_POINTER(combine[
i].
state));
1785 gtk_menu_shell_append(GTK_MENU_SHELL(op_submenu), item);
1789 gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1790 item = gtk_menu_item_new_with_label(_(
"Move up"));
1791 g_signal_connect(item,
"activate", (GCallback)
_tree_moveup, list);
1792 gtk_menu_shell_append(menu, item);
1793 item = gtk_menu_item_new_with_label(_(
"Move down"));
1794 g_signal_connect(item,
"activate", (GCallback)
_tree_movedown, list);
1795 gtk_menu_shell_append(menu, item);
1796 gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1803 GtkMenuShell *menu = GTK_MENU_SHELL(gtk_menu_new());
1807 const int nb = gtk_tree_selection_count_selected_rows(selection);
1816 GList *
selected = gtk_tree_selection_get_selected_rows(selection, NULL);
1817 GtkTreePath *it0 = (GtkTreePath *)
selected->data;
1818 depth = gtk_tree_path_get_depth(it0);
1821 if(nb == 1 && gtk_tree_model_get_iter(
model, &iter, it0))
1823 g_list_free_full(
selected, (GDestroyNotify)gtk_tree_path_free);
1826 if(depth > 1) from_group = 1;
1836 gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1839 if(nb == 1 && grp_is_group)
1852 const int holding_group = from_group ? parentid
1855 if(holding_group != 0)
1859 gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1870 item = gtk_menu_item_new_with_label(_(
"New group from selection"));
1871 g_signal_connect(item,
"activate", (GCallback)
_tree_group, list);
1872 gtk_menu_shell_append(menu, item);
1877 if(!from_group && !grp_is_group && nb == 1)
1879 item = gtk_menu_item_new_with_label(_(
"Duplicate shape"));
1881 gtk_menu_shell_append(menu, item);
1882 gtk_menu_shell_append(menu, gtk_separator_menu_item_new());
1885 if(!from_group && nb > 0)
1888 item = gtk_menu_item_new_with_label(grp_is_group ? _(
"Delete group") : _(
"Delete shape"));
1890 gtk_menu_shell_append(menu, item);
1892 else if(nb > 0 && depth < 3)
1894 item = gtk_menu_item_new_with_label(_(
"Remove shape from mask"));
1896 gtk_menu_shell_append(menu, item);
1899 item = gtk_menu_item_new_with_label(_(
"Delete unused shapes"));
1901 gtk_menu_shell_append(menu, item);
1903 return GTK_WIDGET(menu);
1914 const GdkEventButton *event, GtkTreePath *mouse_path)
1918 gtk_tree_selection_unselect_all(selection);
1924 if(gtk_tree_selection_path_is_selected(selection, mouse_path))
1925 gtk_tree_selection_unselect_path(selection, mouse_path);
1927 gtk_tree_selection_select_path(selection, mouse_path);
1933 GtkTreePath *anchor = NULL;
1934 gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeview), &anchor, NULL);
1937 gtk_tree_selection_select_range(selection, anchor, mouse_path);
1938 gtk_tree_path_free(anchor);
1941 gtk_tree_selection_select_path(selection, mouse_path);
1957 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
1958 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
1960 GtkTreePath *mouse_path = NULL;
1961 GtkTreeViewColumn *mouse_col = NULL;
1963 gboolean on_row =
FALSE;
1969 if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &mouse_path,
1970 &mouse_col, NULL, NULL)
1971 && gtk_tree_model_get_iter(
model, &iter, mouse_path))
1977 if(event->type == GDK_BUTTON_PRESS && event->button == 1)
1983 gtk_tree_path_free(mouse_path);
1994 gtk_tree_path_free(mouse_path);
2001 gtk_tree_path_free(mouse_path);
2008 else if(event->type == GDK_BUTTON_PRESS && event->button == 3)
2011 if(!
IS_NULL_PTR(mouse_path) && !gtk_tree_selection_path_is_selected(selection, mouse_path))
2014 gtk_tree_selection_select_path(selection, mouse_path);
2020 gtk_widget_show_all(menu);
2022 gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent *)event);
2029 if(mouse_path) gtk_tree_path_free(mouse_path);
2039 if(column != list->
name_col)
return;
2041 GtkTreeModel *
model = gtk_tree_view_get_model(treeview);
2043 if(!gtk_tree_model_get_iter(
model, &iter, path))
return;
2050 gboolean path_currently_selected, gpointer data)
2056 if(path_currently_selected)
return TRUE;
2059 if(gtk_tree_selection_count_selected_rows(selection) == 0)
return TRUE;
2069 const int *indices = gtk_tree_path_get_indices(path);
2070 const int depth = gtk_tree_path_get_depth(path);
2072 GList *
items = gtk_tree_selection_get_selected_rows(selection, NULL);
2073 GList *doomed = NULL;
2074 for(
const GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
2076 GtkTreePath *item = (GtkTreePath *)items_iter->data;
2077 const int dd = gtk_tree_path_get_depth(item);
2078 const int *ii = gtk_tree_path_get_indices(item);
2079 const gboolean peer = (dd == depth) && (dd == 1 || ii[dd - 2] == indices[dd - 2]);
2080 if(!peer) doomed = g_list_prepend(doomed, item);
2083 for(
const GList *doomed_iter = doomed; doomed_iter; doomed_iter = g_list_next(doomed_iter))
2084 gtk_tree_selection_unselect_path(selection, (GtkTreePath *)doomed_iter->data);
2087 g_list_free(doomed);
2088 g_list_free_full(
items, (GDestroyNotify)gtk_tree_path_free);
2097 return (grid == 0) ? _(
"Permanently delete this shape. It is detached from every mask "
2098 "and removed from the list of available shapes.")
2099 : _(
"Detach this shape from the mask. The shape is kept and stays "
2100 "available for reuse.");
2112 return g_strdup_printf(_(
"Manage which modules use this %s. A mask is created for the "
2113 "ticked ones that have none, and shared between them."),
2114 row_info.
is_group ? _(
"group") : _(
"shape"));
2126 return g_strdup(_(
"Select a mask in the module groups list to attach this shape to it."));
2129 return g_strdup_printf(_(
"Attach this to the mask '%s'."), grp->
name);
2136 return g_strdup_printf(_(
"This is already part of the mask '%s'."), grp->
name);
2139 return g_strdup_printf(_(
"This group cannot be added to the mask '%s': it already contains it."),
2143 return g_strdup_printf(_(
"The mask '%s' already uses every shape of this group."), grp->
name);
2153 const gint
x,
const gint y, GtkTooltip *
tooltip)
2155 gint bx = 0, by = 0;
2156 gtk_tree_view_convert_widget_to_bin_window_coords(tree_view,
x, y, &bx, &by);
2158 GtkTreePath *path = NULL;
2159 GtkTreeViewColumn *column = NULL;
2160 if(!gtk_tree_view_get_path_at_pos(tree_view, bx, by, &path, &column, NULL, NULL))
return FALSE;
2162 const gboolean on_action = (column == list->
action_col);
2166 GtkTreeModel *
model = gtk_tree_view_get_model(tree_view);
2168 const gboolean got = (on_action || on_add || on_assign) && gtk_tree_model_get_iter(
model, &iter, path);
2169 gtk_tree_path_free(path);
2170 if(!got)
return FALSE;
2182 gtk_tooltip_set_text(
tooltip, text);
2189 GtkTooltip *
tooltip, gpointer data)
2192 GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
2193 GtkTreeModel *
model = gtk_tree_view_get_model(tree_view);
2194 GtkTreePath *path = NULL;
2196 gboolean show =
FALSE;
2203 if(!gtk_tree_view_get_tooltip_context(tree_view, &
x, &y, keyboard_tip, &
model, &path, &iter))
return FALSE;
2208 gtk_tooltip_set_markup(
tooltip, tmp);
2209 gtk_tree_view_set_tooltip_row(tree_view,
tooltip, path);
2212 gtk_tree_path_free(path);
2221 const size_t text_length,
int *nb)
2225 for(
const GList *points = grp->
points; points; points = g_list_next(points))
2231 if(
point->formid == formid)
2234 if(*nb > 1) g_strlcat(text,
"\n", text_length);
2235 g_strlcat(text, grp->
name, text_length);
2244static void _is_form_used(
const int formid,
char *text,
const size_t text_length,
int *nb)
2246 for(
const GList *forms =
dt_dev_get_global()->forms; forms; forms = g_list_next(forms))
2283 GList *owners = NULL;
2284 for(
const GList *iops =
dt_dev_get_global()->iop; iops; iops = g_list_next(iops))
2288 owners = g_list_prepend(owners, iop);
2291 return g_list_reverse(owners);
2301 g_list_free(owners);
2310 GdkPixbuf *icop = NULL;
2329 char used_by[1000] =
"";
2342 guint holder_index = 0;
2345 &holder_index, holder_name,
sizeof(holder_name)) ==
DT_MASKS_OK
2346 && (holder_id !=
row->grp_id || (
int)holder_index !=
row->index))
2348 note = g_strdup_printf(_(
"Already in '%s'"), holder_name);
2351 gtk_tree_store_append(treestore, child, toplevel);
2380 if(self.
flat)
return;
2385 for(
const GList *forms = self.
form->
points; forms; forms = g_list_next(forms))
2393 .opacity = grpt->
opacity, .index = index,
2404 gboolean found =
FALSE;
2410 found = (fid == formid)
2412 || (
IS_NULL_PTR(module) || (mod && (!g_strcmp0(module->
op, mod->
op)))));
2413 if(found)
return found;
2415 GtkTreeIter parent = *iter;
2416 if(gtk_tree_model_iter_children(
model, &child, &parent))
2425 }
while(gtk_tree_model_iter_next(
model, iter));
2433 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
2435 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
2437 GList *
items = gtk_tree_selection_get_selected_rows(selection, &
model);
2439 for(GList *items_iter =
items; items_iter; items_iter = g_list_next(items_iter))
2441 GtkTreePath *item = (GtkTreePath *)items_iter->data;
2443 if(gtk_tree_model_get_iter(
model, &iter, item))
2449 res = g_list_prepend(
res, GINT_TO_POINTER(fid));
2450 res = g_list_prepend(
res, GINT_TO_POINTER(gid));
2451 res = g_list_prepend(
res, (
void *)(mod));
2455 g_list_foreach(
items, (GFunc)gtk_tree_path_free, NULL);
2464 const gboolean exclusive)
2466 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
2467 GtkTreePath *path = gtk_tree_model_get_path(
model, iter);
2469 if(exclusive) gtk_tree_selection_unselect_all(selection);
2470 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(list->
treeview), path);
2471 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(list->
treeview), path, NULL,
TRUE, 0.5, 0.5);
2472 gtk_tree_selection_select_iter(selection, iter);
2474 gtk_tree_path_free(path);
2484 g_list_free(owners);
2499 const gboolean flat)
2509 const _tree_row_t row = { .
form = form, .opacity = 1.0f, .root_id = root_id, .flat = flat };
2518 gboolean any =
FALSE;
2535 for(
const GList *iops = g_list_last(dev->
iop); iops; iops = g_list_previous(iops))
2552 for(
const GList *forms =
dt_dev_get_global()->forms; forms; forms = g_list_next(forms))
2571 gboolean is_separator =
FALSE;
2573 return is_separator;
2580 return gtk_tree_store_new(
TREE_COUNT, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN,
2581 GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
2582 G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
2583 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
2601 GtkTreeIter separator;
2604 gtk_tree_store_append(treestore, &separator, NULL);
2610 if(had_groups && !had_shapes) gtk_tree_store_remove(treestore, &separator);
2619 const GList *ids = selectids;
2623 ids = g_list_next(ids);
2625 ids = g_list_next(ids);
2626 const int fid = GPOINTER_TO_INT(ids->data);
2627 ids = g_list_next(ids);
2634 if(!gtk_tree_model_get_iter_first(
model, &iter))
return;
2648 if(group_id <= 0)
return FALSE;
2653 if(!gtk_tree_model_get_iter_first(
model, &iter))
return FALSE;
2685 if(!
IS_NULL_PTR(content)) gtk_widget_set_sensitive(content, active);
2696 gtk_tree_view_set_model(GTK_TREE_VIEW(list->
treeview), GTK_TREE_MODEL(empty));
2697 g_object_unref(empty);
2720 GtkTreeModel *
model = GTK_TREE_MODEL(treestore);
2721 gtk_tree_view_set_model(GTK_TREE_VIEW(list->
treeview),
model);
2726 g_list_free(selectids);
2734 g_object_unref(treestore);
2755 float opacity = 1.0f;
2760 for(
const GList *pts = grp->
points; pts; pts = g_list_next(pts))
2793 float opacity = 1.0f;
2798 for(
const GList *pts = grp->
points; pts; pts = g_list_next(pts))
2827 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
2828 if(!GTK_IS_TREE_MODEL(
model))
continue;
2836 GList **rl = (GList **)data;
2837 const int refid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(
model),
"formid"));
2838 const int refgid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(
model),
"groupid"));
2844 if(grid == refgid &&
id == refid)
2846 GtkTreeRowReference *rowref = gtk_tree_row_reference_new(
model, path);
2847 *rl = g_list_append(*rl, rowref);
2856 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
2857 if(!GTK_IS_TREE_MODEL(
model))
return;
2859 g_object_set_data(G_OBJECT(
model),
"formid", GUINT_TO_POINTER(formid));
2860 g_object_set_data(G_OBJECT(
model),
"groupid", GUINT_TO_POINTER(parentid));
2863 for(
const GList *rlt = rl; rlt; rlt = g_list_next(rlt))
2865 GtkTreeRowReference *rowref = (GtkTreeRowReference *)rlt->data;
2866 GtkTreePath *path = gtk_tree_row_reference_get_path(rowref);
2867 gtk_tree_row_reference_free(rowref);
2871 if(gtk_tree_model_get_iter(
model, &iter, path))
2873 gtk_tree_store_remove(GTK_TREE_STORE(
model), &iter);
2875 gtk_tree_path_free(path);
2893 const int selectid,
int throw_event,
const int level)
2895 gboolean found =
FALSE;
2899 GtkTreeIter
i = *iter;
2908 || (
IS_NULL_PTR(module) || (mod && (!g_strcmp0(module->
op, mod->
op))))))
2910 gtk_tree_selection_select_iter(selection, &
i);
2917 GtkTreeIter parent =
i;
2918 if(gtk_tree_model_iter_children(
model, &child, &parent))
2920 }
while(!found && gtk_tree_model_iter_next(
model, &
i) ==
TRUE);
2928 const int throw_event)
2933 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
2935 gtk_tree_selection_unselect_all(selection);
2941 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
2942 if(!GTK_IS_TREE_MODEL(
model))
2956 gboolean found =
FALSE;
2957 if(gtk_tree_model_get_iter_first(
model, &iter))
2962 GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
2965 GtkTreePath *path = (GtkTreePath *)rows->data;
2966 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(list->
treeview), path);
2967 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(list->
treeview), path, NULL,
TRUE, 0.5, 0.5);
2969 g_list_free_full(rows, (GDestroyNotify)gtk_tree_path_free);
2990 gboolean found =
FALSE;
2993 if(gtk_tree_model_iter_children(
model, &iter, parent_iter))
2997 int current_formid = -1;
3000 if(current_formid == formid)
3006 }
while(gtk_tree_model_iter_next(
model, &iter));
3014 gboolean found =
FALSE;
3019 int current_parentid = -1;
3022 if(current_parentid == parentid)
3031 }
while(gtk_tree_model_iter_next(
model, iter));
3042 const int formid,
const int parentid,
3045 gboolean found =
FALSE;
3051 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->
treeview));
3052 if(!GTK_IS_TREE_MODEL(
model))
continue;
3055 if(!gtk_tree_model_get_iter_first(
model, &iter))
continue;
3148#define DT_MASKS_PANEL_CONF_WIDTH "plugins/darkroom/masks/windowwidth"
3149#define DT_MASKS_PANEL_CONF_X "plugins/darkroom/masks/window_x"
3150#define DT_MASKS_PANEL_CONF_Y "plugins/darkroom/masks/window_y"
3156#ifdef GDK_WINDOWING_WAYLAND
3157 return !GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(
window));
3167 if(!GTK_IS_WINDOW(
d->popup_window) || !gtk_widget_get_visible(
d->popup_window))
return;
3171 gtk_window_get_size(GTK_WINDOW(
d->popup_window), &
width, &
height);
3178 gtk_window_get_position(GTK_WINDOW(
d->popup_window), &
x, &y);
3188 if(!GTK_IS_WINDOW(
d->popup_window))
return;
3192 gtk_window_get_size(GTK_WINDOW(
d->popup_window), &
width, &
height);
3197 if(stored_width > 0)
3199 width = stored_width;
3200 gtk_window_resize(GTK_WINDOW(
d->popup_window),
width,
MAX(
height, 1));
3214 GdkDisplay *display = gtk_widget_get_display(
d->popup_window);
3217 GdkMonitor *monitor = gdk_display_get_monitor_at_point(display,
x +
width / 2, y +
height / 2);
3218 if(
IS_NULL_PTR(monitor)) monitor = gdk_display_get_primary_monitor(display);
3219 if(
IS_NULL_PTR(monitor) && gdk_display_get_n_monitors(display) > 0)
3220 monitor = gdk_display_get_monitor(display, 0);
3224 GdkRectangle workarea = { 0 };
3225 gdk_monitor_get_workarea(monitor, &workarea);
3226 clamped_x = CLAMP(
x, workarea.x, workarea.x +
MAX(0, workarea.width -
width));
3227 clamped_y = CLAMP(y, workarea.y, workarea.y +
MAX(0, workarea.height -
height));
3231 gtk_window_move(GTK_WINDOW(
d->popup_window), clamped_x, clamped_y);
3268 const gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
3269 if(active == gtk_widget_get_visible(
d->popup_window))
return;
3280 gtk_widget_show_all(
d->popup_window);
3285 gtk_widget_hide(
d->popup_window);
3293 GdkEvent *event
__attribute__((unused)), gpointer user_data)
3296 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->popup_button),
FALSE);
3310 return !
IS_NULL_PTR(
d->popup_window) && gtk_widget_get_visible(
d->popup_window);
3316 if(!
d || !
d->popup_button)
return FALSE;
3330 self->
data = (
void *)
d;
3342 d->popup_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3343 gtk_window_set_title(GTK_WINDOW(
d->popup_window), _(
"Shape Manager"));
3344 gtk_window_set_type_hint(GTK_WINDOW(
d->popup_window), GDK_WINDOW_TYPE_HINT_UTILITY);
3348 gtk_window_set_modal(GTK_WINDOW(
d->popup_window),
FALSE);
3349 gtk_window_set_focus_on_map(GTK_WINDOW(
d->popup_window),
FALSE);
3350 gtk_window_set_accept_focus(GTK_WINDOW(
d->popup_window),
FALSE);
3351 gtk_window_set_transient_for(GTK_WINDOW(
d->popup_window), GTK_WINDOW(
dt_gui_main_window()));
3357 gtk_window_set_position(GTK_WINDOW(
d->popup_window), GTK_WIN_POS_CENTER_ON_PARENT);
3365#ifdef GDK_WINDOWING_QUARTZ
3377 gtk_container_set_border_width(GTK_CONTAINER(shape_manager_container),
DT_GUI_BOX_SPACING);
3378 gtk_container_add(GTK_CONTAINER(
d->popup_window), shape_manager_container);
3387 gtk_widget_set_tooltip_text(
d->popup_button, _(
"Open shape manager..."));
3400 .owner_module = NULL,
3401 .creation_module = NULL,
3404 .action_section = NULL,
3416 gtk_box_pack_start(GTK_BOX(hbox), shape_buttons_box,
FALSE,
FALSE, 0);
3419 gtk_box_pack_start(GTK_BOX(shape_manager_container), hbox,
FALSE,
FALSE, 0);
3427 if(!gtk_style_context_lookup_color(gtk_widget_get_style_context(shape_manager_container),
3428 "disabled_fg_color", &used_color))
3429 used_color = (GdkRGBA){ 0.62, 0.62, 0.62, 1.0 };
3436 if(!gtk_style_context_lookup_color(gtk_widget_get_style_context(shape_manager_container),
3437 "fg_color", &fg_color))
3438 fg_color = (GdkRGBA){ 1.0, 1.0, 1.0, 1.0 };
3447 GtkWidget *lists_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3450 gtk_widget_set_name(lists_paned,
"shape-manager-lists");
3456 const char *height_key;
3459 N_(
"Every shape and group drawn on this image, including the masks "
3460 "modules already use -- pick any of them up to reuse."),
3461 "plugins/darkroom/masks/windowheight" },
3463 N_(
"The masks modules actually render, and the shapes each one is made of."),
3464 "plugins/darkroom/masks/moduleslistheight" },
3473 list->
treeview = gtk_tree_view_new();
3475 GtkTreeViewColumn *col = gtk_tree_view_column_new();
3476 gtk_tree_view_append_column(GTK_TREE_VIEW(list->
treeview), col);
3478 GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
3479 gtk_tree_view_column_pack_start(col, renderer,
FALSE);
3480 gtk_tree_view_column_set_attributes(col, renderer,
"pixbuf",
TREE_IC_OP, NULL);
3483 renderer = gtk_cell_renderer_pixbuf_new();
3484 gtk_tree_view_column_pack_start(col, renderer,
FALSE);
3485 gtk_tree_view_column_set_attributes(col, renderer,
"pixbuf",
TREE_IC_INVERSE, NULL);
3496 renderer = gtk_cell_renderer_text_new();
3497 gtk_tree_view_column_pack_start(col, renderer,
TRUE);
3498 gtk_tree_view_column_add_attribute(col, renderer,
"text",
TREE_TEXT);
3503 gtk_tree_view_column_add_attribute(col, renderer,
"strikethrough",
TREE_STRIKE);
3515 renderer = gtk_cell_renderer_pixbuf_new();
3519 g_object_set(renderer,
"icon-name",
"mail-attachment-symbolic",
"stock-size", GTK_ICON_SIZE_MENU, NULL);
3521 g_object_set(renderer,
"pixbuf",
d->ic_used, NULL);
3522 gtk_tree_view_column_pack_end(col, renderer,
FALSE);
3529 renderer = gtk_cell_renderer_text_new();
3530 g_object_set(renderer,
"style", PANGO_STYLE_ITALIC,
"xalign", 1.0f, NULL);
3531 gtk_cell_renderer_set_sensitive(renderer,
FALSE);
3532 gtk_tree_view_column_pack_end(col, renderer,
FALSE);
3533 gtk_tree_view_column_add_attribute(col, renderer,
"text",
TREE_NOTE);
3541 gtk_tree_view_column_set_expand(col,
TRUE);
3547 list->
add_col = gtk_tree_view_column_new();
3548 gtk_tree_view_column_set_sizing(list->
add_col, GTK_TREE_VIEW_COLUMN_FIXED);
3551 renderer = gtk_cell_renderer_pixbuf_new();
3556 g_object_set(renderer,
"icon-name",
"list-add-symbolic",
"stock-size", GTK_ICON_SIZE_MENU, NULL);
3557 gtk_cell_renderer_set_sensitive(renderer,
FALSE);
3558 gtk_tree_view_column_pack_start(list->
add_col, renderer,
FALSE);
3561 gtk_tree_view_append_column(GTK_TREE_VIEW(list->
treeview), list->
add_col);
3565 list->
assign_col = gtk_tree_view_column_new();
3566 gtk_tree_view_column_set_sizing(list->
assign_col, GTK_TREE_VIEW_COLUMN_FIXED);
3569 renderer = gtk_cell_renderer_pixbuf_new();
3571 g_object_set(renderer,
"icon-name",
"view-list-symbolic",
"stock-size", GTK_ICON_SIZE_MENU, NULL);
3573 g_object_set(renderer,
"pixbuf",
d->ic_assign, NULL);
3580 list->
action_col = gtk_tree_view_column_new();
3581 gtk_tree_view_column_set_sizing(list->
action_col, GTK_TREE_VIEW_COLUMN_FIXED);
3584 renderer = gtk_cell_renderer_pixbuf_new();
3585 g_object_set(renderer,
"icon-name",
"list-remove-symbolic",
"stock-size", GTK_ICON_SIZE_MENU, NULL);
3589 renderer = gtk_cell_renderer_pixbuf_new();
3590 g_object_set(renderer,
"icon-name",
"user-trash-symbolic",
"stock-size", GTK_ICON_SIZE_MENU, NULL);
3596 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list->
treeview));
3597 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
3602 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list->
treeview),
FALSE);
3605 g_object_set(list->
treeview,
"has-tooltip",
TRUE, (gchar *)0);
3615 gtk_widget_set_name(half,
"shape-manager-list");
3617 gtk_widget_set_tooltip_text(title, _(list_defs[
i].
tooltip));
3618 gtk_box_pack_start(GTK_BOX(half), title,
FALSE,
FALSE, 0);
3632 if(GTK_IS_SCROLLED_WINDOW(
scrolled))
3635 gtk_box_pack_start(GTK_BOX(half), wrapper,
TRUE,
TRUE, 0);
3643 gtk_paned_pack1(GTK_PANED(lists_paned), half,
FALSE,
FALSE);
3645 gtk_paned_pack2(GTK_PANED(lists_paned), half,
TRUE,
FALSE);
3648 gtk_box_pack_start(GTK_BOX(shape_manager_container), lists_paned,
TRUE,
TRUE, 0);
3671 if(self && self->
data)
3680 gtk_widget_destroy(
d->popup_window);
3681 d->popup_window = NULL;
3686 if(!
IS_NULL_PTR(
d->ic_add_off)) g_object_unref(
d->ic_add_off);
3687 if(!
IS_NULL_PTR(
d->ic_assign)) g_object_unref(
d->ic_assign);
3688 if(!
IS_NULL_PTR(
d->ic_inverse)) g_object_unref(
d->ic_inverse);
3690 if(!
IS_NULL_PTR(
d->ic_intersection)) g_object_unref(
d->ic_intersection);
3691 if(!
IS_NULL_PTR(
d->ic_difference)) g_object_unref(
d->ic_difference);
3692 if(!
IS_NULL_PTR(
d->ic_exclusion)) g_object_unref(
d->ic_exclusion);
3696 d->ic_add_off = NULL;
3697 d->ic_assign = NULL;
3698 d->ic_inverse = NULL;
3700 d->ic_intersection = NULL;
3701 d->ic_difference = NULL;
3702 d->ic_exclusion = NULL;
Handle default and user-set shortcuts (accelerators)
GtkWidget * dt_gui_main_window(void)
int scrolled(struct dt_iop_module_t *self, double x, double y, int up, uint32_t state)
void gui_reset(dt_imageio_module_format_t *self)
void dt_iop_gui_blend_masks_update(dt_iop_module_t *module)
gboolean dt_iop_gui_blend_set_drawn_mask_group(dt_iop_module_t *module, const int group_id)
The blending panel's GUI state and API, cut out of develop/blend.h.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
int dt_conf_key_exists(const char *key)
Does key have a value?
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
void reset(dt_view_t *self)
struct dt_develop_t * dt_dev_get_global(void)
struct dt_view_manager_t * dt_view_manager_get_global(void)
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_dev_pixelpipe_change_zoom_main(dt_develop_t *dev)
void dt_dev_masks_selection_change(dt_develop_t *dev, struct dt_iop_module_t *module, const int selectid, const int throw_event)
void dt_dev_undo_start_record(dt_develop_t *dev)
void dt_dev_undo_end_record(dt_develop_t *dev)
gchar * dt_history_item_get_name(const struct dt_iop_module_t *module)
void dt_gui_refocus_parent(GtkWindow *parent)
GtkTreeStore * store
its model, owned by the view
GHashTable * selected
set of checked row labels, mirrored to conf on every change
static GdkPixbuf * dt_draw_get_pixbuf_from_cairo(DTGTKCairoPaintIconFunc paint, const int width, const int height)
const dt_collection_sort_t items[]
gboolean dt_iop_module_supports_drawn_mask(dt_iop_module_t *iop)
gboolean dt_iop_module_is_in_pipeline(dt_iop_module_t *iop)
GtkWidget * dt_ui_section_label_new(const gchar *str)
GtkWidget * dt_ui_label_new(const gchar *str)
GdkPixbuf * dt_gui_symbolic_icon_pixbuf(const char *icon_name, GtkIconSize size, const GdkRGBA *color, GtkStyleContext *context)
Load a symbolic icon as a pre-tinted pixbuf, at the pixel size size names.
static gboolean _modchooser_button_press(GtkWidget *dialog, const GdkEventButton *event, gpointer user_data __attribute__((unused)))
static gboolean _tree_button_tooltip(const dt_shape_manager_list_t *list, GtkTreeView *tree_view, const gint x, const gint y, GtkTooltip *tooltip)
static void _tree_row_assign_to_modules(dt_shape_manager_list_t *list, GtkTreeModel *model, GtkTreeIter *iter)
static void _tree_add_exist(GtkButton *button, dt_masks_form_t *grp)
static void _tree_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, dt_shape_manager_list_t *list)
static void _is_form_used(const int formid, char *text, const size_t text_length, int *nb)
static void _tree_start_name_editing(const dt_shape_manager_list_t *list, GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path, const gboolean cursor_at_end)
@ TREE_IC_INVERSE_VISIBLE
static void _shape_manager_broadcast(dt_lib_module_t *self, const int formid, const int parentid, const dt_masks_event_t event)
static void _tree_add_shape_menu_item(GtkWidget *menu, const dt_masks_type_t type, dt_iop_module_t *module)
static int _selected_group_in_module_list(const dt_shape_manager_t *lm)
static gboolean _tree_restrict_select(GtkTreeSelection *selection, GtkTreeModel *model __attribute__((unused)), GtkTreePath *path, gboolean path_currently_selected, gpointer data)
static void _shape_manager_selection_change(dt_lib_module_t *self, struct dt_iop_module_t *module, const int selectid, const int throw_event)
static void _menu_append_new_shape_submenu(GtkMenuShell *menu, dt_iop_module_t *module)
static void _tree_moveup(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static void _groups_naming_form(const int formid, const dt_masks_form_t *grp, char *text, const size_t text_length, int *nb)
static gchar * _tooltip_add_text(const dt_shape_manager_t *lm, GtkTreeModel *model, GtkTreeIter *iter)
static void _shape_manager_modules_moved(gpointer instance __attribute__((unused)), dt_lib_module_t *self)
static void _menu_append_separator(GtkMenuShell *menu)
static gboolean _find_iter_by_parentid_and_formid(GtkTreeModel *model, int parentid, int formid, GtkTreeIter *iter)
static int _tree_apply_click_selection(GtkWidget *treeview, GtkTreeSelection *selection, const GdkEventButton *event, GtkTreePath *mouse_path)
static void _shape_manager_popup_restore_geometry(dt_shape_manager_t *d)
Put the panel back where it was left, before it is mapped. With nothing stored – first run,...
static gboolean _row_can_be_added(const dt_shape_manager_t *lm, GtkTreeModel *model, GtkTreeIter *iter)
static void _set_iter_name(dt_shape_manager_t *lm, dt_masks_form_t *form, int state, float opacity, GtkTreeModel *model, GtkTreeIter *iter, int index)
static void _tree_row_action(dt_shape_manager_list_t *list, GtkTreeModel *model, GtkTreeIter *iter)
static gboolean _find_child_iter_by_formid(GtkTreeModel *model, GtkTreeIter *parent_iter, int formid, GtkTreeIter *child_iter)
static void _menu_append_join_group(GtkMenuShell *menu, dt_shape_manager_list_t *list)
static gboolean _remove_foreach(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
static void _modchooser_toggled(GtkCellRendererToggle *cell __attribute__((unused)), const gchar *path_string, GtkListStore *store)
static void _shape_manager_popup_button_toggled_cb(GtkWidget *button, gpointer user_data)
#define DT_MASKS_PANEL_CONF_WIDTH
static void _add_cell_data_func(GtkTreeViewColumn *col __attribute__((unused)), GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
static gboolean _group_is_module_mask(const dt_masks_form_t *form)
static void _shape_manager_relax_height_caps(const dt_shape_manager_t *d)
Forget how far the user last dragged each list, so the auto-sizing pass that follows measures true,...
static GtkWidget * _tree_context_menu(GtkTreeSelection *selection, GtkTreeModel *model, dt_shape_manager_list_t *list, dt_iop_module_t *module)
static void _shape_manager_popup_save_geometry(dt_shape_manager_t *d)
Remember where the user put the panel and how wide they made it. Called on every path that takes the ...
static void _shape_manager_update_list(dt_lib_module_t *self)
static int _tree_format_form_usage_label(char *str, const size_t str_size, const dt_masks_form_t *form, const dt_iop_module_t *module)
void gui_cleanup(dt_lib_module_t *self)
static void _tree_restore_selection(dt_shape_manager_list_t *list, GtkTreeModel *model, const GList *selectids)
static gboolean _tree_row_is_separator(GtkTreeModel *model, GtkTreeIter *iter, gpointer data __attribute__((unused)))
static void _shape_manager_list_recurs(GtkTreeStore *treestore, GtkTreeIter *toplevel, dt_shape_manager_t *lm, const _tree_row_t *row)
static gboolean _shape_manager_popup_position_is_usable(GtkWidget *window)
Is this window on a backend where absolute coordinates mean anything? Wayland gives a client neither ...
static gint _shape_manager_height_ceiling(void)
The toolbox button is the panel's only state: showing and hiding both go through its active flag,...
static int _tree_root_formid(GtkTreeModel *model, GtkTreeIter iter)
static gboolean _shape_manager_is_active(void)
const char ** views(dt_lib_module_t *self __attribute__((unused)))
static const char * _tooltip_action_text(const int grid)
static int _tree_button_pressed(GtkWidget *treeview, GdkEventButton *event, dt_shape_manager_list_t *list)
static void _add_masks_history_item(dt_shape_manager_t *lm)
static void _shape_manager_sync_add_sensitivity(const dt_shape_manager_t *lm)
static gboolean _shape_manager_refresh_row(dt_lib_module_t *self, dt_shape_manager_t *lm, const int formid, const int parentid, const dt_masks_event_t event)
static void _shape_manager_view_changed(gpointer instance __attribute__((unused)), dt_view_t *old_view __attribute__((unused)), dt_view_t *new_view __attribute__((unused)), dt_lib_module_t *self)
#define DT_MASKS_PANEL_CONF_X
static GtkTreeStore * _tree_store_build(dt_shape_manager_t *lm, const dt_shape_list_t which)
static void _tree_delete_shape(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static void _modchooser_collect(GtkListStore *store, GList **to_attach, GList **to_detach)
static void _tree_row_add_to_group(dt_shape_manager_list_t *list, GtkTreeModel *model, GtkTreeIter *iter)
static void _menu_append_existing_shapes(GtkMenuShell *menu, dt_masks_form_t *grp, const int grpid, dt_iop_module_t *module)
static void _tree_edit_group_name(dt_lib_module_t *self, dt_shape_list_t which, int formid, gboolean cursor_at_end)
static gboolean _shape_manager_add_popup_button_idle(gpointer user_data)
static gboolean _modchooser_run(const dt_masks_form_t *form, GList **to_attach, GList **to_detach)
static void _shape_manager_handler_callback(gpointer instance __attribute__((unused)), const int formid, const int parentid, const dt_masks_event_t event, dt_lib_module_t *self)
static gboolean _tree_edit_group_name_idle(gpointer user_data)
static gboolean _tree_store_add_forms(GtkTreeStore *treestore, dt_shape_manager_t *lm, const dt_shape_list_t which, const gboolean groups)
uint32_t container(dt_lib_module_t *self __attribute__((unused)))
gboolean _find_mask_iter_by_values(GtkTreeModel *model, GtkTreeIter *iter, const dt_iop_module_t *module, const int formid, const int level)
GList * _shape_manager_get_selected(dt_shape_manager_list_t *list)
static void _menu_append_operations(GtkMenuShell *menu, dt_shape_manager_list_t *list, const int nb)
static dt_iop_module_t * _module_owning_group(const dt_masks_form_t *group)
static void _tree_duplicate_shape(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static void _tree_group(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static void _tree_apply_operation(GtkWidget *menu_item, dt_shape_manager_list_t *list)
static gboolean _tree_store_append_group_row(GtkTreeStore *treestore, dt_shape_manager_t *lm, dt_masks_form_t *form, const gboolean is_module_mask, const gboolean flat)
static void _shape_manager_recreate_list(dt_lib_module_t *self)
static void _tree_add_shape(GtkWidget *menu_item, dt_iop_module_t *module)
static GtkTreeStore * _tree_store_new(void)
#define DT_MASKS_PANEL_CONF_Y
static void _shape_manager_remove_item_from(const dt_shape_manager_list_t *list, int formid, int parentid)
static void _show_masks_on_owning_module(GtkTreeModel *model, GtkTreeIter *iter)
static void _shape_manager_get_values(GtkTreeModel *model, GtkTreeIter *iter, dt_iop_module_t **module, int *groupid, int *formid)
void gui_init(dt_lib_module_t *self)
static gboolean _shape_manager_selection_change_r(GtkTreeModel *model, GtkTreeSelection *selection, GtkTreeIter *iter, struct dt_iop_module_t *module, const int selectid, int throw_event, const int level)
static void _tree_reveal_row(dt_shape_manager_list_t *list, GtkTreeModel *model, GtkTreeIter *iter, const gboolean exclusive)
static dt_masks_form_t * _module_create_own_mask(dt_develop_t *dev, dt_iop_module_t *module, int *own_id)
static void _refresh_owning_modules(const dt_masks_form_t *grp)
static void _tree_name_caret_to_end(GtkWidget *editable, gpointer user_data __attribute__((unused)))
static void _tree_name_editing_done(GtkCellEditable *editable __attribute__((unused)), dt_shape_manager_t *lm)
static void _tree_movedown(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static void _tree_cell_edited(GtkCellRendererText *cell __attribute__((unused)), const gchar *path_string, const gchar *new_text, dt_shape_manager_list_t *list)
static void _tree_delete_unused(GtkButton *button __attribute__((unused)), dt_shape_manager_list_t *list)
static gchar * _tooltip_assign_text(GtkTreeModel *model, GtkTreeIter *iter)
static gboolean _shape_manager_selection_change_in(dt_shape_manager_t *lm, const dt_shape_manager_list_t *list, struct dt_iop_module_t *module, const int selectid, const int throw_event)
static gboolean _shape_manager_popup_delete_cb(GtkWidget *window __attribute__((unused)), GdkEvent *event __attribute__((unused)), gpointer user_data)
Closing from the window manager hides the panel, same as the toolbox button, so its widgets and state...
static gboolean _modchooser_button_pressed(GtkWidget *treeview, const GdkEventButton *event, GtkListStore *store)
static gboolean _tree_select_module_group(dt_shape_manager_list_t *list, GtkTreeModel *model, const dt_masks_form_gui_t *gui)
static void _tree_add_to_group(GtkMenuItem *item, dt_shape_manager_list_t *list)
static gboolean _shape_manager_is_window_visible(dt_lib_module_t *self)
static GList * _modules_owning_group(const dt_masks_form_t *group)
static gboolean _tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data)
static void _tree_selection_change(GtkTreeSelection *selection, dt_shape_manager_list_t *list)
static void _tree_append_row(GtkTreeStore *treestore, GtkTreeIter *toplevel, dt_shape_manager_t *lm, const _tree_row_t *row, GtkTreeIter *child)
static GList * _selected_form_ids(dt_shape_manager_list_t *list)
static void _tree_name_editing_started(GtkCellRenderer *renderer __attribute__((unused)), GtkCellEditable *editable, const gchar *path __attribute__((unused)), dt_shape_manager_list_t *list)
static void _shape_manager_remove_item(dt_lib_module_t *self, int formid, int parentid)
static gboolean _form_can_join_group(dt_develop_t *dev, const int group_id, const int fid)
static void _shape_manager_update_item(dt_lib_module_t *self __attribute__((unused)), int formid, int parentid, dt_shape_manager_t *lm, GtkTreeModel *model, GtkTreeIter *iter)
static void _shape_manager_shape_button_started(GtkWidget *button __attribute__((unused)), dt_iop_module_t *module __attribute__((unused)), dt_masks_type_t type __attribute__((unused)), gpointer user_data __attribute__((unused)))
static gboolean _update_foreach(GtkTreeModel *model, GtkTreePath *path __attribute__((unused)), GtkTreeIter *iter, gpointer data)
_lib_location_type_t type
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_masks_result_t dt_masks_group_get_member(dt_develop_t *dev, const int group_id, const int formid, dt_masks_member_t *out)
Read one group member by identity.
dt_masks_result_t dt_masks_group_set_member_operation(dt_develop_t *dev, const int group_id, const int formid, const dt_masks_state_t operation, dt_masks_member_t *out)
Set a group member's combination operator, or toggle its inversion.
gboolean dt_masks_form_get_info(const dt_masks_form_t *form, dt_masks_form_info_t *out)
guint dt_masks_group_list(dt_develop_t *dev, dt_masks_form_info_t *out, const guint out_max)
Describe every group of the live list, in dev->forms order, into caller storage.
int dt_masks_group_find_holder(dt_develop_t *dev, const int formid)
Which group references formid, searching every group in dev->forms depth-first.
dt_masks_result_t dt_masks_group_first_use(dt_develop_t *dev, const int root_id, const int formid, int *holder_id, guint *index, char *holder_name, const size_t holder_name_size)
Where the mask rooted at root_id FIRST applies formid.
dt_masks_result_t dt_masks_group_set_name_from_module(dt_develop_t *dev, const int group_id, dt_iop_module_t *module)
Name a group after the module that renders it, by id.
dt_masks_result_t dt_masks_group_contains(dt_develop_t *dev, const int container_id, const int needle_id)
Whether container_id holds needle_id, at any depth (and trivially when they are the same id).
dt_masks_result_t dt_masks_group_covers_shapes(dt_develop_t *dev, const int group_id, const int target_id, gboolean *has_shapes)
Whether every shape group_id ultimately holds is also held by target_id.
int dt_masks_form_duplicate_in_group(dt_develop_t *dev, int group_id, int form_id)
Duplicate a shape (dt_masks_form_duplicate) and, if group_id names a valid group, attach the duplicat...
dt_masks_form_t * dt_masks_create_ext(dt_develop_t *dev, dt_masks_type_t type)
void dt_masks_cleanup_unused(dt_develop_t *dev)
Cleanup unused masks and refresh the current forms snapshot.
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
void dt_masks_form_move(dt_masks_form_t *grp, int formid, int up)
void dt_masks_form_delete(dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *grp, dt_masks_form_t *form)
dt_masks_form_t * dt_masks_get_from_id(dt_develop_t *dev, int id)
Ask the masks module about a shape or a group, instead of reading its structs.
void dt_masks_group_ungroup(dt_develop_t *dev, dt_masks_form_t *dest_group, dt_masks_form_t *group_form)
void dt_masks_gui_populate_interaction_sliders(GtkWidget *menu, dt_develop_t *dev, dt_masks_form_t *form, const int group_id, dt_masks_form_gui_t *gui, dt_iop_module_t *module)
Append the full set of shape-parameter sliders (size/fading/rotation or curvature/fade/rotation depen...
GtkWidget * dt_masks_shape_menu_item_new(GtkWidget *menu, const dt_masks_type_t type, GCallback activate_callback, gpointer user_data)
Append a menu entry for one shape type: its toolbar icon, then its toolbar label.
void dt_masks_change_form_gui(dt_develop_t *dev, dt_masks_form_t *new_form)
gboolean dt_masks_gui_confirm_permanent_delete(const char *form_name)
Ask the user to confirm a permanent shape deletion, gated by the "ask_before_delete_mask_shape" pref....
void dt_masks_append_form(dt_develop_t *develop, dt_masks_form_t *mask_form)
void dt_masks_shape_buttons_deactivate_all(GtkWidget *active_button)
GtkWidget * dt_masks_shape_buttons_create(const dt_masks_shape_buttons_config_t *config)
Build a synchronized toolbar for creating masks shapes.
dt_masks_form_group_t * dt_masks_group_add_form(dt_develop_t *dev, dt_masks_form_t *group_form, dt_masks_form_t *mask_form)
void dt_masks_reset_show_masks_icons(dt_develop_t *dev)
void dt_masks_set_visible_form(dt_develop_t *dev, dt_masks_form_t *form)
int dt_masks_center_view_on_form(dt_develop_t *dev, const dt_masks_form_t *mask_form)
Center the darkroom ROI on a mask form gravity center.
gboolean dt_masks_creation_mode_enter(dt_develop_t *dev, dt_iop_module_t *module, const dt_masks_type_t type)
Enter mask creation mode for a given shape type.
dt_masks_form_group_t * dt_masks_group_add_form_with_state(dt_develop_t *dev, dt_masks_form_t *group_form, dt_masks_form_t *mask_form, const int parentid, const dt_masks_state_t state, const float opacity)
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
@ DT_MASKS_SHAPE_BUTTONS_NONE
@ DT_MASKS_SHAPE_BUTTONS_ALL
void dt_masks_form_unref(dt_masks_form_t *form)
dt_masks_form_t * dt_masks_cow_touch(dt_develop_t *dev, dt_masks_form_t *form)
#define DT_MASKS_FORM_NAME_LEN
@ DT_MASKS_STATE_DIFFERENCE
@ DT_MASKS_STATE_INTERSECTION
@ DT_MASKS_STATE_EXCLUSION
#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_osx_disallow_fullscreen(GtkWidget *widget)
Asking the interface to repaint itself.
#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_MODULE_MOVED
This signal is raised when order of modules in pipeline is changed.
@ DT_SIGNAL_VIEWMANAGER_VIEW_CHANGED
This signal is raised by viewmanager when a view has changed. 1 : dt_view_t * the old view 2 : dt_vie...
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
const float uint32_t state[4]
dt_iop_module_t *int gstate
void(* list_update)(struct dt_lib_module_t *self)
void(* list_remove)(struct dt_lib_module_t *self, int formid, int parentid)
struct dt_lib_module_t *void(* list_change)(struct dt_lib_module_t *self)
struct dt_masks_form_gui_t * form_gui
void(* selection_change)(struct dt_lib_module_t *self, struct dt_iop_module_t *module, const int selectid, const int throw_event)
gboolean(* is_visible)(struct dt_lib_module_t *self)
struct dt_develop_t::@14::@22 masks
struct dt_develop_t::@14 proxy
struct dt_develop_blend_params_t * blend_params
One shape's membership of one group, BY VALUE.
GtkTreeViewColumn * add_col
GtkTreeViewColumn * action_col
GtkTreeViewColumn * assign_col
GtkTreeViewColumn * name_col
GtkCellRenderer * name_renderer
gboolean name_edit_cursor_at_end
dt_shape_manager_list_t lists[DT_SHAPE_LIST_COUNT]
gboolean name_edit_at_end
dt_shape_list_t name_edit_which
GdkPixbuf * ic_difference
GdkPixbuf * ic_intersection
struct dt_view_manager_t::@60 proxy
struct dt_view_manager_t::@60::@61 module_toolbox
Telling the user something happened.
void dt_view_manager_module_toolbox_add(dt_view_manager_t *vm, GtkWidget *tool, dt_view_type_flags_t views)
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)