static void gimp_gegl_config_class_init (GObjectClass *klass, const gchar *operation) { GParamSpec **pspecs; guint n_pspecs; gint i; klass->set_property = gimp_gegl_config_set_property; klass->get_property = gimp_gegl_config_get_property; pspecs = gegl_operation_list_properties (operation, &n_pspecs); for (i = 0; i < n_pspecs; i++) { GParamSpec *pspec = pspecs[i]; if ((pspec->flags & G_PARAM_READABLE) && (pspec->flags & G_PARAM_WRITABLE) && strcmp (pspec->name, "input") && strcmp (pspec->name, "output")) { GParamSpec *copy = gimp_param_spec_duplicate (pspec); if (copy) { g_object_class_install_property (klass, i + 1, copy); } } } g_free (pspecs); }
void gimp_gegl_config_proxy_sync (GimpObject *proxy, GeglNode *node) { GParamSpec **pspecs; gchar *operation; guint n_pspecs; gint i; g_return_if_fail (GIMP_IS_OBJECT (proxy)); g_return_if_fail (GEGL_IS_NODE (node)); gegl_node_get (node, "operation", &operation, NULL); g_return_if_fail (operation != NULL); pspecs = gegl_operation_list_properties (operation, &n_pspecs); g_free (operation); for (i = 0; i < n_pspecs; i++) { GParamSpec *gegl_pspec = pspecs[i]; GParamSpec *gimp_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), gegl_pspec->name); if (gimp_pspec) { GValue value = { 0, }; g_value_init (&value, gimp_pspec->value_type); g_object_get_property (G_OBJECT (proxy), gimp_pspec->name, &value); if (GEGL_IS_PARAM_SPEC_COLOR (gegl_pspec)) { GimpRGB gimp_color; GeglColor *gegl_color; gimp_value_get_rgb (&value, &gimp_color); g_value_unset (&value); gegl_color = gimp_gegl_color_new (&gimp_color); g_value_init (&value, gegl_pspec->value_type); g_value_take_object (&value, gegl_color); } gegl_node_set_property (node, gegl_pspec->name, &value); g_value_unset (&value); } } g_free (pspecs); }
void gegl_dot_util_add_node (GString *string, GeglNode *node) { g_string_append_printf (string, "op_%p [fontsize=\"10\" label=\"", node); /* We build the record from top to bottom */ g_string_append_printf (string, "{"); /* The first row is a list of output pads */ { GSList *pads = gegl_node_get_pads (node); GSList *entry = pads; gboolean got_output = FALSE; g_string_append_printf (string, "{"); while (entry) { GeglPad *pad = entry->data; if (gegl_pad_is_output (pad)) { if (got_output) { g_string_append (string, "|"); } got_output = TRUE; g_string_append_printf (string, "<%s>%s", gegl_pad_get_name (pad), gegl_pad_get_name (pad)); } entry = g_slist_next (entry); } g_string_append_printf (string, "}|"); } /* The second row is the operation name such as gegl:translate */ g_string_append_printf (string, "%s |", gegl_node_get_debug_name (node)); /* The next rows are property names and their values */ if (1) { guint n_properties; GParamSpec **properties = gegl_operation_list_properties (gegl_node_get_operation (node), &n_properties); guint i; for (i = 0; i < n_properties; i++) { const gchar *name = properties[i]->name; GValue tvalue = { 0, }; GValue svalue = { 0, }; if (properties[i]->value_type == GEGL_TYPE_BUFFER) continue; g_value_init (&svalue, G_TYPE_STRING); g_value_init (&tvalue, properties[i]->value_type); gegl_node_get_property (node, name, &tvalue); if (g_value_transform (&tvalue, &svalue)) { gchar *sval = g_value_dup_string (&svalue); if (sval && strlen (sval) > 30) { sval[28] = '.'; sval[29] = '.'; sval[30] = '\0'; } if (sval) { g_string_append_printf (string, "%s=%s | ", name, sval); g_free (sval); } g_value_unset (&svalue); } g_value_unset (&tvalue); } g_free (properties); } /* The last row is input pads */ { GSList *pads = gegl_node_get_pads (node); GSList *entry = pads; gboolean got_input = FALSE; g_string_append_printf (string, "{"); while (entry) { GeglPad *pad = entry->data; if (gegl_pad_is_input (pad)) { if (got_input) { g_string_append (string, "|"); } got_input = TRUE; g_string_append_printf (string, "<%s>%s", gegl_pad_get_name (pad), gegl_pad_get_name (pad)); } entry = g_slist_next (entry); } g_string_append_printf (string, "}"); } g_string_append_printf (string, "}\""); g_string_append_printf (string, "shape=\"record\"];\n"); }
gint layer_node_selected (gpointer host, GeglEditor* editor, gint node_id) { GeglEditorLayer* self = (GeglEditorLayer*)host; GeglNode* node = NULL; GSList* pair = self->pairs; for(;pair != NULL; pair = pair->next) { node_id_pair* data = pair->data; if(data->id == node_id) { node = data->node; break; } } g_assert(node != NULL); GeglNode** nodes; const gchar** pads; gint num = gegl_node_get_consumers(node, "output", &nodes, &pads); int i; g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num); for(i = 0; i < num; i++) { g_print("Connection: (%s to %s)\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[0]), pads[0]); } g_print("Input from: %s\n", gegl_node_get_operation(gegl_node_get_producer(node, "input", NULL))); // g_print("selected: %s\n", gegl_node_get_operation(node)); guint n_props; GParamSpec** properties = gegl_operation_list_properties(gegl_node_get_operation(node), &n_props); //TODO: only create enough columns for the properties which will actually be included (i.e. ignoring GeglBuffer props) GtkTable *prop_table = GTK_TABLE(gtk_table_new(2, n_props, FALSE)); int d; for(d = 0, i = 0; i < n_props; i++, d++) { GParamSpec* prop = properties[i]; GType type = prop->value_type; const gchar* name = prop->name; GtkWidget* name_label = gtk_label_new(name); gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0.5); GtkWidget* value_entry = gtk_entry_new(); gchar buf[256] = "*"; //can probably be smaller; In fact, can probably do this without sprintf and a buffer. TODO: look at g_string gint i_value; gdouble d_value; gchar* str_value; gboolean skip = FALSE; switch(type) { case G_TYPE_INT: gegl_node_get(node, name, &i_value, NULL); sprintf(buf, "%d", i_value); break; case G_TYPE_DOUBLE: gegl_node_get(node, name, &d_value, NULL); sprintf(buf, "%.3f", d_value); break; case G_TYPE_STRING: gegl_node_get(node, name, &str_value, NULL); sprintf(buf, "%s", str_value); break; } if(type == GEGL_TYPE_BUFFER) { skip = TRUE; d--; } else if( type == GEGL_TYPE_COLOR) { skip = TRUE; GtkWidget *color_button = gtk_button_new_with_label("Select"); select_color_info* info = malloc(sizeof(select_color_info)); info->node = node; info->property = name; info->layer = self; g_signal_connect(color_button, "clicked", (GCallback)select_color, info); gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1); gtk_table_attach(prop_table, color_button, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1); } if(!skip) { gtk_entry_set_text(GTK_ENTRY(value_entry), buf); gtk_entry_set_width_chars(GTK_ENTRY(value_entry), 2); struct text_prop_data *data = malloc(sizeof(struct text_prop_data)); //TODO store this in a list and free it when the node is deselected data->node = node; data->property = name; data->prop_type = type; data->layer = self; g_signal_connect(value_entry, "activate", G_CALLBACK(text_property_changed), data); gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1); gtk_table_attach(prop_table, value_entry, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1); } } // gegl_node_process(node); GeglGtkView *gtk_view = gegl_gtk_view_new_for_node(node); GeglRectangle rect = gegl_node_get_bounding_box(node); if(gegl_rectangle_is_infinite_plane(&rect)) { gegl_gtk_view_set_autoscale_policy(gtk_view, GEGL_GTK_VIEW_AUTOSCALE_DISABLED); gegl_gtk_view_set_scale(gtk_view, 1.0); g_print("Disable autoscale: scale=%f, x=%f, y=%f\n", gegl_gtk_view_get_scale(gtk_view), gegl_gtk_view_get_x(gtk_view), gegl_gtk_view_get_y(gtk_view)); } gtk_widget_show(GTK_WIDGET(gtk_view)); //TODO: draw checkerboard under preview to indicate transparency gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(prop_table), FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(gtk_view), TRUE, TRUE, 10); GtkWidget* label = gtk_label_new("Click the image\nto open in a\nnew window"); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); gtk_box_pack_start(GTK_BOX(self->prop_box), label, FALSE, TRUE, 10); gtk_widget_show_all(self->prop_box); }