static void gimp_operation_tool_sync_op (GimpOperationTool *op_tool, GimpDrawable *drawable) { GimpImageMapTool *im_tool = GIMP_IMAGE_MAP_TOOL (op_tool); GimpToolOptions *options = GIMP_TOOL_GET_OPTIONS (op_tool); GParamSpec **pspecs; guint n_pspecs; gint bounds_x; gint bounds_y; gint bounds_width; gint bounds_height; gint i; gimp_item_mask_intersect (GIMP_ITEM (drawable), &bounds_x, &bounds_y, &bounds_width, &bounds_height); pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (im_tool->config), &n_pspecs); for (i = 0; i < n_pspecs; i++) { GParamSpec *pspec = pspecs[i]; #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec, "role", "output-extent")) { if (HAS_KEY (pspec, "unit", "pixel-coordinate") && HAS_KEY (pspec, "axis", "x")) { g_object_set (im_tool->config, pspec->name, 0, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-coordinate") && HAS_KEY (pspec, "axis", "y")) { g_object_set (im_tool->config, pspec->name, 0, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-distance") && HAS_KEY (pspec, "axis", "x")) { g_object_set (im_tool->config, pspec->name, bounds_width, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-distance") && HAS_KEY (pspec, "axis", "y")) { g_object_set (im_tool->config, pspec->name, bounds_height, NULL); } } else if (HAS_KEY (pspec, "role", "color-primary")) { GimpRGB color; gimp_context_get_foreground (GIMP_CONTEXT (options), &color); g_object_set (im_tool->config, pspec->name, &color, NULL); } else if (HAS_KEY (pspec, "role", "color-secondary")) { GimpRGB color; gimp_context_get_background (GIMP_CONTEXT (options), &color); g_object_set (im_tool->config, pspec->name, &color, NULL); } } g_free (pspecs); }
static void gimp_operation_tool_color_picked (GimpImageMapTool *im_tool, gpointer identifier, gdouble x, gdouble y, const Babl *sample_format, const GimpRGB *color) { GimpOperationTool *tool = GIMP_OPERATION_TOOL (im_tool); gchar **pspecs; pspecs = g_strsplit (identifier, ":", 2); if (pspecs[1]) { GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool); GimpDrawable *drawable = GIMP_TOOL (im_tool)->drawable; GObjectClass *object_class = G_OBJECT_GET_CLASS (im_tool->config); GParamSpec *pspec_x; GParamSpec *pspec_y; gint width = 1; gint height = 1; if (drawable) { gint off_x, off_y; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); x -= off_x; y -= off_y; switch (options->region) { case GIMP_IMAGE_MAP_REGION_SELECTION: if (gimp_item_mask_intersect (GIMP_ITEM (drawable), &off_x, &off_y, &width, &height)) { x -= off_x; y -= off_y; } break; case GIMP_IMAGE_MAP_REGION_DRAWABLE: width = gimp_item_get_width (GIMP_ITEM (drawable)); height = gimp_item_get_height (GIMP_ITEM (drawable)); break; } } pspec_x = g_object_class_find_property (object_class, pspecs[0]); pspec_y = g_object_class_find_property (object_class, pspecs[1]); if (pspec_x && pspec_y && G_PARAM_SPEC_TYPE (pspec_x) == G_PARAM_SPEC_TYPE (pspec_y)) { GValue value_x = G_VALUE_INIT; GValue value_y = G_VALUE_INIT; g_value_init (&value_x, G_PARAM_SPEC_VALUE_TYPE (pspec_x)); g_value_init (&value_y, G_PARAM_SPEC_VALUE_TYPE (pspec_y)); #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec_x, "unit", "relative-coordinate") && HAS_KEY (pspec_y, "unit", "relative-coordinate")) { x /= (gdouble) width; y /= (gdouble) height; } if (G_IS_PARAM_SPEC_INT (pspec_x)) { g_value_set_int (&value_x, x); g_value_set_int (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (im_tool->config, pspecs[0], g_value_get_int (&value_x), pspecs[1], g_value_get_int (&value_y), NULL); } else if (G_IS_PARAM_SPEC_DOUBLE (pspec_x)) { g_value_set_double (&value_x, x); g_value_set_double (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (im_tool->config, pspecs[0], g_value_get_double (&value_x), pspecs[1], g_value_get_double (&value_y), NULL); } else { g_warning ("%s: unhandled param spec of type %s", G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (pspec_x)); } g_value_unset (&value_x); g_value_unset (&value_y); } } else { g_object_set (im_tool->config, pspecs[0], color, NULL); } g_strfreev (pspecs); }
GtkWidget * gimp_prop_widget_new_from_pspec (GObject *config, GParamSpec *pspec, GimpContext *context, GimpCreatePickerFunc create_picker_func, gpointer picker_creator, const gchar **label) { GtkWidget *widget = NULL; g_return_val_if_fail (G_IS_OBJECT (config), NULL); g_return_val_if_fail (pspec != NULL, NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (label != NULL, NULL); *label = NULL; if (GEGL_IS_PARAM_SPEC_SEED (pspec)) { GtkAdjustment *adj; GtkWidget *spin; GtkWidget *button; widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); spin = gimp_prop_spin_button_new (config, pspec->name, 1.0, 10.0, 0); gtk_box_pack_start (GTK_BOX (widget), spin, TRUE, TRUE, 0); gtk_widget_show (spin); button = gtk_button_new_with_label (_("New Seed")); gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0); gtk_widget_show (button); adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin)); g_signal_connect (button, "clicked", G_CALLBACK (gimp_prop_widget_new_seed_clicked), adj); *label = g_param_spec_get_nick (pspec); } else if (G_IS_PARAM_SPEC_INT (pspec) || G_IS_PARAM_SPEC_UINT (pspec) || G_IS_PARAM_SPEC_FLOAT (pspec) || G_IS_PARAM_SPEC_DOUBLE (pspec)) { gdouble lower; gdouble upper; gdouble step; gdouble page; gint digits; if (GEGL_IS_PARAM_SPEC_DOUBLE (pspec)) { GeglParamSpecDouble *gspec = GEGL_PARAM_SPEC_DOUBLE (pspec); lower = gspec->ui_minimum; upper = gspec->ui_maximum; step = gspec->ui_step_small; page = gspec->ui_step_big; digits = gspec->ui_digits; } else if (GEGL_IS_PARAM_SPEC_INT (pspec)) { GeglParamSpecInt *gspec = GEGL_PARAM_SPEC_INT (pspec); lower = gspec->ui_minimum; upper = gspec->ui_maximum; step = gspec->ui_step_small; page = gspec->ui_step_big; digits = 0; } else { gdouble value; _gimp_prop_widgets_get_numeric_values (config, pspec, &value, &lower, &upper, G_STRFUNC); if ((upper - lower <= 1.0) && (G_IS_PARAM_SPEC_FLOAT (pspec) || G_IS_PARAM_SPEC_DOUBLE (pspec))) { step = 0.01; page = 0.1; digits = 4; } else if ((upper - lower <= 10.0) && (G_IS_PARAM_SPEC_FLOAT (pspec) || G_IS_PARAM_SPEC_DOUBLE (pspec))) { step = 0.1; page = 1.0; digits = 3; } else { step = 1.0; page = 10.0; digits = (G_IS_PARAM_SPEC_FLOAT (pspec) || G_IS_PARAM_SPEC_DOUBLE (pspec)) ? 2 : 0; } } widget = gimp_prop_spin_scale_new (config, pspec->name, NULL, step, page, digits); if (HAS_KEY (pspec, "unit", "degree") && (upper - lower) == 360.0) { GtkWidget *hbox; GtkWidget *dial; gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (widget), TRUE); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); gtk_widget_show (widget); dial = gimp_prop_angle_dial_new (config, pspec->name); gtk_box_pack_start (GTK_BOX (hbox), dial, FALSE, FALSE, 0); gtk_widget_show (dial); widget = hbox; } else if (HAS_KEY (pspec, "unit", "kelvin")) { GtkWidget *hbox; GtkWidget *button; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); gtk_widget_show (widget); button = gimp_prop_kelvin_presets_new (config, pspec->name); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); widget = hbox; } } else if (G_IS_PARAM_SPEC_STRING (pspec)) { static GQuark multiline_quark = 0; if (! multiline_quark) multiline_quark = g_quark_from_static_string ("multiline"); if (GIMP_IS_PARAM_SPEC_CONFIG_PATH (pspec)) { widget = gimp_prop_file_chooser_button_new (config, pspec->name, g_param_spec_get_nick (pspec), GTK_FILE_CHOOSER_ACTION_OPEN); } else if (g_param_spec_get_qdata (pspec, multiline_quark)) { GtkTextBuffer *buffer; GtkWidget *view; buffer = gimp_prop_text_buffer_new (config, pspec->name, -1); view = gtk_text_view_new_with_buffer (buffer); g_object_unref (buffer); widget = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (widget), view); gtk_widget_show (view); } else { widget = gimp_prop_entry_new (config, pspec->name, -1); } *label = g_param_spec_get_nick (pspec); } else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) { widget = gimp_prop_check_button_new (config, pspec->name, g_param_spec_get_nick (pspec)); } else if (G_IS_PARAM_SPEC_ENUM (pspec)) { widget = gimp_prop_enum_combo_box_new (config, pspec->name, 0, 0); gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (widget), g_param_spec_get_nick (pspec)); } else if (GIMP_IS_PARAM_SPEC_RGB (pspec)) { GtkWidget *button; widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); button = gimp_prop_color_button_new (config, pspec->name, g_param_spec_get_nick (pspec), 128, 24, GIMP_COLOR_AREA_SMALL_CHECKS); gimp_color_button_set_update (GIMP_COLOR_BUTTON (button), TRUE); gimp_color_panel_set_context (GIMP_COLOR_PANEL (button), context); gtk_box_pack_start (GTK_BOX (widget), button, TRUE, TRUE, 0); gtk_widget_show (button); if (create_picker_func) { button = create_picker_func (picker_creator, pspec->name, GIMP_STOCK_COLOR_PICKER_GRAY, _("Pick color from the image")); gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0); gtk_widget_show (button); } *label = g_param_spec_get_nick (pspec); } else { g_warning ("%s: not supported: %s (%s)\n", G_STRFUNC, g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name); } return widget; }
GtkWidget * gimp_prop_gui_new (GObject *config, GType owner_type, GimpContext *context, GimpCreatePickerFunc create_picker_func, gpointer picker_creator) { GtkWidget *gui = NULL; GParamSpec **param_specs; guint n_param_specs; gint i, j; g_return_val_if_fail (G_IS_OBJECT (config), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); param_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config), &n_param_specs); for (i = 0, j = 0; i < n_param_specs; i++) { GParamSpec *pspec = param_specs[i]; /* ignore properties of parent classes of owner_type */ if (! g_type_is_a (pspec->owner_type, owner_type)) continue; if (HAS_KEY (pspec, "role", "output-extent")) continue; param_specs[j] = param_specs[i]; j++; } n_param_specs = j; if (n_param_specs > 0) { const gchar *config_type_name = G_OBJECT_TYPE_NAME (config); for (i = 0; i < G_N_ELEMENTS (gui_new_funcs); i++) { if (! gui_new_funcs[i].config_type || ! strcmp (gui_new_funcs[i].config_type, config_type_name)) { g_printerr ("GUI new func match: %s\n", gui_new_funcs[i].config_type ? gui_new_funcs[i].config_type : "generic fallback"); gui = gui_new_funcs[i].gui_new_func (config, param_specs, n_param_specs, context, create_picker_func, picker_creator); break; } } } else { gui = gtk_label_new (_("This operation has no editable properties")); gimp_label_set_attributes (GTK_LABEL (gui), PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, -1); gtk_misc_set_padding (GTK_MISC (gui), 0, 4); } g_free (param_specs); return gui; }
static void gimp_operation_tool_sync_op (GimpOperationTool *op_tool, gboolean sync_colors) { GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (op_tool); GimpToolOptions *options = GIMP_TOOL_GET_OPTIONS (op_tool); GParamSpec **pspecs; guint n_pspecs; gint off_x, off_y; GeglRectangle area; gint i; gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area); pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (filter_tool->config), &n_pspecs); for (i = 0; i < n_pspecs; i++) { GParamSpec *pspec = pspecs[i]; #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec, "role", "output-extent")) { if (HAS_KEY (pspec, "unit", "pixel-coordinate") && HAS_KEY (pspec, "axis", "x")) { g_object_set (filter_tool->config, pspec->name, 0, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-coordinate") && HAS_KEY (pspec, "axis", "y")) { g_object_set (filter_tool->config, pspec->name, 0, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-distance") && HAS_KEY (pspec, "axis", "x")) { g_object_set (filter_tool->config, pspec->name, area.width, NULL); } else if (HAS_KEY (pspec, "unit", "pixel-distance") && HAS_KEY (pspec, "axis", "y")) { g_object_set (filter_tool->config, pspec->name, area.height, NULL); } } else if (sync_colors) { if (HAS_KEY (pspec, "role", "color-primary")) { GimpRGB color; gimp_context_get_foreground (GIMP_CONTEXT (options), &color); g_object_set (filter_tool->config, pspec->name, &color, NULL); } else if (sync_colors && HAS_KEY (pspec, "role", "color-secondary")) { GimpRGB color; gimp_context_get_background (GIMP_CONTEXT (options), &color); g_object_set (filter_tool->config, pspec->name, &color, NULL); } } } g_free (pspecs); }
static void gimp_operation_tool_color_picked (GimpFilterTool *filter_tool, gpointer identifier, gdouble x, gdouble y, const Babl *sample_format, const GimpRGB *color) { gchar **pspecs = g_strsplit (identifier, ":", 2); if (pspecs[1]) { GObjectClass *object_class = G_OBJECT_GET_CLASS (filter_tool->config); GParamSpec *pspec_x; GParamSpec *pspec_y; gint off_x, off_y; GeglRectangle area; gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area); x -= off_x + area.x; y -= off_y + area.y; pspec_x = g_object_class_find_property (object_class, pspecs[0]); pspec_y = g_object_class_find_property (object_class, pspecs[1]); if (pspec_x && pspec_y && G_PARAM_SPEC_TYPE (pspec_x) == G_PARAM_SPEC_TYPE (pspec_y)) { GValue value_x = G_VALUE_INIT; GValue value_y = G_VALUE_INIT; g_value_init (&value_x, G_PARAM_SPEC_VALUE_TYPE (pspec_x)); g_value_init (&value_y, G_PARAM_SPEC_VALUE_TYPE (pspec_y)); #define HAS_KEY(p,k,v) gimp_gegl_param_spec_has_key (p, k, v) if (HAS_KEY (pspec_x, "unit", "relative-coordinate") && HAS_KEY (pspec_y, "unit", "relative-coordinate")) { x /= (gdouble) area.width; y /= (gdouble) area.height; } if (G_IS_PARAM_SPEC_INT (pspec_x)) { g_value_set_int (&value_x, x); g_value_set_int (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (filter_tool->config, pspecs[0], g_value_get_int (&value_x), pspecs[1], g_value_get_int (&value_y), NULL); } else if (G_IS_PARAM_SPEC_DOUBLE (pspec_x)) { g_value_set_double (&value_x, x); g_value_set_double (&value_y, y); g_param_value_validate (pspec_x, &value_x); g_param_value_validate (pspec_y, &value_y); g_object_set (filter_tool->config, pspecs[0], g_value_get_double (&value_x), pspecs[1], g_value_get_double (&value_y), NULL); } else { g_warning ("%s: unhandled param spec of type %s", G_STRFUNC, G_PARAM_SPEC_TYPE_NAME (pspec_x)); } g_value_unset (&value_x); g_value_unset (&value_y); } } else { g_object_set (filter_tool->config, pspecs[0], color, NULL); } g_strfreev (pspecs); }