diff --git a/ChangeLog b/ChangeLog index 1f16d451a5..49b1cd7d0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2001-11-27 Michael Natterer + + * app/core/gimpcontainer.c: GType is a pointer now, not a guint. + + * app/widgets/gimpdock.c: chain up in widget_class->style_set(). + + Gradient Editor chopping plus merging of bex' proofreading: + (fixes #62278). + + * app/core/core-types.h: moved the gradient related enums here. + + * app/core/gimpgradient.[ch]: removed the enums, added gradient + segment utility functions from the gradient_editor. + + * app/gui/gui-types.h: added the GradientEditor typedef here. + + * app/gui/Makefile.am + * app/gui/gradient-editor-commands.[ch]: new files implementing + callbacks and menu_update stuff for the new gradient_editor + item factory. + + * app/gui/gradient-editor.[ch]: removed tons of code, namespace + cleanup, stuff... + + * app/gui/menus.[ch]: added the gradient_editor menu stuff here. + Added menus_set_color() which creates & updates a color menu item + (will soon be used in other places too). Renamed menus_set_state() + to menus_set_active(). + + The editor's menu code is ugly as before, only different and evil + the same way as the rest of the menu stuff, so it's at least + consistent :) + + * app/display/gimpdisplayshell.c: changed accordingly. + + * app/gui/test-commands.c: don't include "gradient-editor.h". + 2001-11-27 Sven Neumann * configure.in @@ -64,7 +101,6 @@ * app/gui/file-save-dialog.c: More of my extensive proofing. Someone needs to check bex comments and do some hacking. - 2001-11-26 Michael Natterer * app/core/gimpimage.c: gimp_image_construct_layers/channels(): diff --git a/app/actions/gradient-editor-commands.c b/app/actions/gradient-editor-commands.c new file mode 100644 index 0000000000..9d68b093c5 --- /dev/null +++ b/app/actions/gradient-editor-commands.c @@ -0,0 +1,1479 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "gui-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpgradient.h" + +#include "widgets/gimpwidgets-utils.h" + +#include "color-notebook.h" +#include "gradient-editor.h" +#include "gradient-editor-commands.h" +#include "menus.h" + +#include "libgimp/gimpintl.h" + + +/* local function prototypes */ + +static void gradient_editor_menu_set_sensitivity (GradientEditor *editor); +static void gradient_editor_left_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data); +static void gradient_editor_right_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data); + +static GimpGradientSegment * + gradient_editor_save_selection (GradientEditor *editor); +static void gradient_editor_replace_selection (GradientEditor *editor, + GimpGradientSegment *replace_seg); + +static void gradient_editor_dialog_cancel_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_split_uniform_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_replicate_callback (GtkWidget *widget, + GradientEditor *editor); + + +/* public functionss */ + +void +gradient_editor_left_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + editor->left_saved_dirty = GIMP_DATA (gradient)->dirty; + editor->left_saved_segments = gradient_editor_save_selection (editor); + + color_notebook_new (_("Left Endpoint Color"), + &editor->control_sel_l->left_color, + gradient_editor_left_color_changed, + editor, + editor->instant_update, + TRUE); + + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_load_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradientSegment *seg; + GimpRGB color; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + i = (gint) action; + + switch (i) + { + case 0: /* Fetch from left neighbor's right endpoint */ + if (editor->control_sel_l->prev != NULL) + seg = editor->control_sel_l->prev; + else + seg = gimp_gradient_segment_get_last (editor->control_sel_l); + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &seg->right_color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 1: /* Fetch from right endpoint */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->right_color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 2: /* Fetch from FG color */ + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 3: /* Fetch from BG color */ + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + default: /* Load a color */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->saved_colors[i - 4], + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + } + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_save_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + editor->saved_colors[action] = editor->control_sel_l->left_color; +} + +void +gradient_editor_right_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + editor->right_saved_dirty = GIMP_DATA (gradient)->dirty; + editor->right_saved_segments = gradient_editor_save_selection (editor); + + color_notebook_new (_("Right Endpoint Color"), + &editor->control_sel_l->right_color, + gradient_editor_right_color_changed, + editor, + editor->instant_update, + TRUE); + + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_load_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradientSegment *seg; + GimpRGB color; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + i = (gint) action; + + switch (i) + { + case 0: /* Fetch from right neighbor's left endpoint */ + if (editor->control_sel_r->next != NULL) + seg = editor->control_sel_r->next; + else + seg = gimp_gradient_segment_get_first (editor->control_sel_r); + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + &seg->left_color, + TRUE, TRUE); + break; + + case 1: /* Fetch from left endpoint */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_l->left_color, + TRUE, TRUE); + break; + + case 2: /* Fetch from FG color */ + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &color, + TRUE, TRUE); + break; + + case 3: /* Fetch from BG color */ + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &color, + TRUE, TRUE); + break; + + default: /* Load a color */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->saved_colors[i - 4], + TRUE, TRUE); + break; + } + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_save_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + editor->saved_colors[action] = editor->control_sel_l->left_color; +} + +void +gradient_editor_blending_func_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegmentType type; + GimpGradientSegment *seg, *aseg; + + if (! GTK_CHECK_MENU_ITEM (widget)->active) + return; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + type = (GimpGradientSegmentType) action; + + seg = editor->control_sel_l; + + do + { + seg->type = type; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_coloring_type_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegmentColor color; + GimpGradientSegment *seg, *aseg; + + if (! GTK_CHECK_MENU_ITEM (widget)->active) + return; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + color = (GimpGradientSegmentColor) action; + + seg = editor->control_sel_l; + + do + { + seg->color = color; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_flip_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *oseg, *oaseg; + GimpGradientSegment *seg, *prev, *tmp; + GimpGradientSegment *lseg, *rseg; + gdouble left, right; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + left = editor->control_sel_l->left; + right = editor->control_sel_r->right; + + /* Build flipped segments */ + + prev = NULL; + oseg = editor->control_sel_r; + tmp = NULL; + + do + { + seg = gimp_gradient_segment_new (); + + if (prev == NULL) + { + seg->left = left; + tmp = seg; /* Remember first segment */ + } + else + seg->left = left + right - oseg->right; + + seg->middle = left + right - oseg->middle; + seg->right = left + right - oseg->left; + + seg->left_color = oseg->right_color; + + seg->right_color = oseg->left_color; + + switch (oseg->type) + { + case GRAD_SPHERE_INCREASING: + seg->type = GRAD_SPHERE_DECREASING; + break; + + case GRAD_SPHERE_DECREASING: + seg->type = GRAD_SPHERE_INCREASING; + break; + + default: + seg->type = oseg->type; + } + + switch (oseg->color) + { + case GRAD_HSV_CCW: + seg->color = GRAD_HSV_CW; + break; + + case GRAD_HSV_CW: + seg->color = GRAD_HSV_CCW; + break; + + default: + seg->color = oseg->color; + } + + seg->prev = prev; + seg->next = NULL; + + if (prev) + prev->next = seg; + + prev = seg; + + oaseg = oseg; + oseg = oseg->prev; /* Move backwards! */ + } + while (oaseg != editor->control_sel_l); + + seg->right = right; /* Squish accumulative error */ + + /* Free old segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + oseg = editor->control_sel_l; + + do + { + oaseg = oseg->next; + gimp_gradient_segment_free (oseg); + oseg = oaseg; + } + while (oaseg != rseg); + + /* Link in new segments */ + + if (lseg) + lseg->next = tmp; + else + gradient->segments = tmp; + + tmp->prev = lseg; + + seg->next = rseg; + + if (rseg) + rseg->prev = seg; + + /* Reset selection */ + + editor->control_sel_l = tmp; + editor->control_sel_r = seg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_replicate_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GtkWidget *dialog; + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *scale; + GtkObject *scale_data; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + /* Create dialog window */ + dialog = + gimp_dialog_new ((editor->control_sel_l == editor->control_sel_r) ? + _("Replicate segment") : + _("Replicate selection"), + "gradient_segment_replicate", + gimp_standard_help_func, + "dialogs/gradient_editor/replicate_segment.html", + GTK_WIN_POS_MOUSE, + FALSE, TRUE, FALSE, + + GTK_STOCK_CANCEL, gradient_editor_dialog_cancel_callback, + editor, NULL, NULL, TRUE, TRUE, + + _("Replicate"), gradient_editor_replicate_callback, + editor, NULL, NULL, FALSE, FALSE, + + NULL); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); + gtk_widget_show (vbox); + + /* Instructions */ + label = gtk_label_new (_("Select the number of times")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + label = gtk_label_new ((editor->control_sel_l == editor->control_sel_r) ? + _("to replicate the selected segment") : + _("to replicate the selection")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* Scale */ + editor->replicate_times = 2; + scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); + + scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 4); + gtk_widget_show (scale); + + g_signal_connect (G_OBJECT (scale_data), "value_changed", + G_CALLBACK (gimp_int_adjustment_update), + &editor->replicate_times); + + /* Show! */ + gtk_widget_show (dialog); + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_split_midpoint_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *lseg, *rseg; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + seg = editor->control_sel_l; + + do + { + gimp_gradient_segment_split_midpoint (gradient, seg, &lseg, &rseg); + seg = rseg->next; + } + while (lseg != editor->control_sel_r); + + editor->control_sel_r = rseg; + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_split_uniformly_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GtkWidget *dialog; + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *scale; + GtkObject *scale_data; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + /* Create dialog window */ + dialog = + gimp_dialog_new ((editor->control_sel_l == editor->control_sel_r) ? + _("Split Segment Uniformly") : + _("Split Segments Uniformly"), + "gradient_segment_split_uniformly", + gimp_standard_help_func, + "dialogs/gradient_editor/split_segments_uniformly.html", + GTK_WIN_POS_MOUSE, + FALSE, TRUE, FALSE, + + GTK_STOCK_CANCEL, gradient_editor_dialog_cancel_callback, + editor, NULL, NULL, FALSE, TRUE, + + _("Split"), gradient_editor_split_uniform_callback, + editor, NULL, NULL, TRUE, FALSE, + + NULL); + + /* The main vbox */ + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); + gtk_widget_show (vbox); + + /* Instructions */ + label = gtk_label_new (_("Please select the number of uniform parts")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + label = + gtk_label_new ((editor->control_sel_l == editor->control_sel_r) ? + _("in which to split the selected segment") : + _("in which to split the segments in the selection")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* Scale */ + editor->split_parts = 2; + scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); + + scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 4); + gtk_widget_show (scale); + + g_signal_connect (G_OBJECT (scale_data), "value_changed", + G_CALLBACK (gimp_int_adjustment_update), + &editor->split_parts); + + /* Show! */ + gtk_widget_show (dialog); + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_delete_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *lseg, *rseg, *seg, *aseg, *next; + gdouble join; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + /* Remember segments to the left and to the right of the selection */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + /* Cannot delete all the segments in the gradient */ + + if ((lseg == NULL) && (rseg == NULL)) + return; + + /* Calculate join point */ + + join = (editor->control_sel_l->left + + editor->control_sel_r->right) / 2.0; + + if (lseg == NULL) + join = 0.0; + else if (rseg == NULL) + join = 1.0; + + /* Move segments */ + + if (lseg != NULL) + gimp_gradient_segments_compress_range (lseg, lseg, lseg->left, join); + + if (rseg != NULL) + gimp_gradient_segments_compress_range (rseg, rseg, join, rseg->right); + + /* Link */ + + if (lseg) + lseg->next = rseg; + + if (rseg) + rseg->prev = lseg; + + /* Delete old segments */ + + seg = editor->control_sel_l; + + do + { + next = seg->next; + aseg = seg; + + gimp_gradient_segment_free (seg); + + seg = next; + } + while (aseg != editor->control_sel_r); + + /* Change selection */ + + if (rseg) + { + editor->control_sel_l = rseg; + editor->control_sel_r = rseg; + } + else + { + editor->control_sel_l = lseg; + editor->control_sel_r = lseg; + } + + if (lseg == NULL) + gradient->segments = rseg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_recenter_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + seg = editor->control_sel_l; + + do + { + seg->middle = (seg->left + seg->right) / 2.0; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_redistribute_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg; + gdouble left, right, seg_len; + gint num_segs; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + /* Count number of segments in selection */ + + num_segs = 0; + seg = editor->control_sel_l; + + do + { + num_segs++; + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + /* Calculate new segment length */ + + left = editor->control_sel_l->left; + right = editor->control_sel_r->right; + seg_len = (right - left) / num_segs; + + /* Redistribute */ + + seg = editor->control_sel_l; + + for (i = 0; i < num_segs; i++) + { + seg->left = left + i * seg_len; + seg->right = left + (i + 1) * seg_len; + seg->middle = (seg->left + seg->right) / 2.0; + + seg = seg->next; + } + + /* Fix endpoints to squish accumulative error */ + + editor->control_sel_l->left = left; + editor->control_sel_r->right = right; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_blend_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_r->right_color, + TRUE, FALSE); + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_blend_opacity_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_r->right_color, + FALSE, TRUE); + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_show_context_menu (GradientEditor *editor) +{ + GtkItemFactory *item_factory; + + gradient_editor_menu_set_sensitivity (editor); + + item_factory = menus_get_gradient_editor_factory (); + + gimp_item_factory_popup_with_data (item_factory, editor); +} + + +/* private functions */ + +static void +gradient_editor_menu_set_sensitivity (GradientEditor *editor) +{ + GimpGradientSegment *left_seg; + GimpGradientSegment *right_seg; + GimpRGB fg; + GimpRGB bg; + gboolean blending_equal = TRUE; + gboolean coloring_equal = TRUE; + gboolean selection; + gboolean delete; + + if (editor->control_sel_l->prev) + left_seg = editor->control_sel_l->prev; + else + left_seg = gimp_gradient_segment_get_last (editor->control_sel_l); + + if (editor->control_sel_r->next) + right_seg = editor->control_sel_r->next; + else + right_seg = gimp_gradient_segment_get_first (editor->control_sel_r); + + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &fg); + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &bg); + + { + GimpGradientSegmentType type; + GimpGradientSegmentColor color; + GimpGradientSegment *seg, *aseg; + + type = editor->control_sel_l->type; + color = editor->control_sel_l->color; + + seg = editor->control_sel_l; + + do + { + blending_equal = blending_equal && (seg->type == type); + coloring_equal = coloring_equal && (seg->color == color); + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + } + + selection = (editor->control_sel_l != editor->control_sel_r); + delete = (editor->control_sel_l->prev || editor->control_sel_r->next); + +#define SET_ACTIVE(menu,active) \ + menus_set_active ("/" menu, (active)) +#define SET_COLOR(menu,color,set_label) \ + menus_set_color ("/" menu, (color), (set_label)) +#define SET_LABEL(menu,label) \ + menus_set_label ("/" menu, (label)) +#define SET_SENSITIVE(menu,condition) \ + menus_set_sensitive ("/" menu, (condition) != 0) +#define SET_VISIBLE(menu,condition) \ + menus_set_visible ("/" menu, (condition) != 0) + + SET_COLOR ("Left Endpoint's Color...", + &editor->control_sel_l->left_color, FALSE); + SET_COLOR ("Load Left Color From/Left Neighbor's Right Endpoint", + &left_seg->right_color, FALSE); + SET_COLOR ("Load Left Color From/Right Endpoint", + &editor->control_sel_r->right_color, FALSE); + SET_COLOR ("Load Left Color From/FG Color", &fg, FALSE); + SET_COLOR ("Load Left Color From/BG Color", &bg, FALSE); + + SET_COLOR ("Load Left Color From/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Load Left Color From/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Load Left Color From/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Load Left Color From/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Load Left Color From/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Load Left Color From/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Load Left Color From/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Load Left Color From/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Load Left Color From/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Load Left Color From/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Save Left Color To/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Save Left Color To/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Save Left Color To/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Save Left Color To/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Save Left Color To/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Save Left Color To/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Save Left Color To/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Save Left Color To/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Save Left Color To/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Save Left Color To/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Right Endpoint's Color...", + &editor->control_sel_r->right_color, FALSE); + SET_COLOR ("Load Right Color From/Right Neighbor's Left Endpoint", + &right_seg->left_color, FALSE); + SET_COLOR ("Load Right Color From/Left Endpoint", + &editor->control_sel_l->left_color, FALSE); + SET_COLOR ("Load Right Color From/FG Color", &fg, FALSE); + SET_COLOR ("Load Right Color From/BG Color", &bg, FALSE); + + SET_COLOR ("Load Right Color From/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Load Right Color From/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Load Right Color From/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Load Right Color From/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Load Right Color From/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Load Right Color From/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Load Right Color From/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Load Right Color From/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Load Right Color From/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Load Right Color From/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Save Right Color To/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Save Right Color To/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Save Right Color To/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Save Right Color To/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Save Right Color To/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Save Right Color To/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Save Right Color To/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Save Right Color To/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Save Right Color To/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Save Right Color To/10", &editor->saved_colors[9], TRUE); + + if (! selection) + { + SET_LABEL ("flip", _("Flip Segment")); + SET_LABEL ("replicate", _("Replicate Segment")); + SET_LABEL ("blendingfunction", _("Blending Function for Segment")); + SET_LABEL ("coloringtype", _("Coloring Type for Segment")); + SET_LABEL ("splitmidpoint", _("Split Segment at Midpoint")); + SET_LABEL ("splituniformly", _("Split Segment Uniformly")); + SET_LABEL ("delete", _("Delete Segment")); + SET_LABEL ("recenter", _("Re-center Segment's Midpoint")); + SET_LABEL ("redistribute", _("Re-distribute Handles in Segment")); + } + else + { + SET_LABEL ("flip", _("Flip Selection")); + SET_LABEL ("replicate", _("Replicate Selection")); + SET_LABEL ("blendingfunction", _("Blending Function for Selection")); + SET_LABEL ("coloringtype", _("Coloring Type for Selection")); + SET_LABEL ("splitmidpoint", _("Split Segments at Midpoints")); + SET_LABEL ("splituniformly", _("Split Segments Uniformly")); + SET_LABEL ("delete", _("Delete Selection")); + SET_LABEL ("recenter", _("Re-center Midpoints in Selection")); + SET_LABEL ("redistribute", _("Re-distribute Handles in Selection")); + } + + SET_SENSITIVE ("blendingfunction/(Varies)", FALSE); + SET_SENSITIVE ("coloringtype/(Varies)", FALSE); + + if (blending_equal) + { + SET_VISIBLE ("blendingfunction/(Varies)", FALSE); + + switch (editor->control_sel_l->type) + { + case GRAD_LINEAR: + SET_ACTIVE ("blendingfunction/Linear", TRUE); + break; + case GRAD_CURVED: + SET_ACTIVE ("blendingfunction/Curved", TRUE); + break; + case GRAD_SINE: + SET_ACTIVE ("blendingfunction/Sinusodial", TRUE); + break; + case GRAD_SPHERE_INCREASING: + SET_ACTIVE ("blendingfunction/Spherical (increasing)", TRUE); + break; + case GRAD_SPHERE_DECREASING: + SET_ACTIVE ("blendingfunction/Spherical (decreasing)", TRUE); + break; + } + } + else + { + SET_VISIBLE ("blendingfunction/(Varies)", TRUE); + SET_ACTIVE ("blendingfunction/(Varies)", TRUE); + } + + if (coloring_equal) + { + SET_VISIBLE ("coloringtype/(Varies)", FALSE); + + switch (editor->control_sel_l->color) + { + case GRAD_RGB: + SET_ACTIVE ("coloringtype/RGB", TRUE); + break; + case GRAD_HSV_CCW: + SET_ACTIVE ("coloringtype/HSV (counter-clockwise hue)", TRUE); + break; + case GRAD_HSV_CW: + SET_ACTIVE ("coloringtype/HSV (clockwise hue)", TRUE); + break; + } + } + else + { + SET_VISIBLE ("coloringtype/(Varies)", TRUE); + SET_ACTIVE ("coloringtype/(Varies)", TRUE); + } + + SET_SENSITIVE ("Blend Endpoints' Colors", selection); + SET_SENSITIVE ("Blend Endpoints' Opacity", selection); + SET_SENSITIVE ("delete", delete); + +#undef SET_ACTIVE +#undef SET_COLOR +#undef SET_LABEL +#undef SET_SENSITIVE +#undef SET_VISIBLE +} + +static void +gradient_editor_left_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) data; + + gradient = gimp_context_get_gradient (editor->context); + + switch (state) + { + case COLOR_NOTEBOOK_OK: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + (GimpRGB *) color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + gimp_gradient_segments_free (editor->left_saved_segments); + gimp_data_dirty (GIMP_DATA (gradient)); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + + case COLOR_NOTEBOOK_UPDATE: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + (GimpRGB *) color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + gimp_data_dirty (GIMP_DATA (gradient)); + break; + + case COLOR_NOTEBOOK_CANCEL: + gradient_editor_replace_selection (editor, editor->left_saved_segments); + GIMP_DATA (gradient)->dirty = editor->left_saved_dirty; + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + } + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +static void +gradient_editor_right_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) data; + + gradient = gimp_context_get_gradient (editor->context); + + switch (state) + { + case COLOR_NOTEBOOK_UPDATE: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + (GimpRGB *) color, + TRUE, TRUE); + gimp_data_dirty (GIMP_DATA (gradient)); + break; + + case COLOR_NOTEBOOK_OK: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + (GimpRGB *) color, + TRUE, TRUE); + gimp_gradient_segments_free (editor->right_saved_segments); + gimp_data_dirty (GIMP_DATA (gradient)); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + + case COLOR_NOTEBOOK_CANCEL: + gradient_editor_replace_selection (editor, editor->right_saved_segments); + GIMP_DATA (gradient)->dirty = editor->right_saved_dirty; + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + } + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +static GimpGradientSegment * +gradient_editor_save_selection (GradientEditor *editor) +{ + GimpGradientSegment *seg, *prev, *tmp; + GimpGradientSegment *oseg, *oaseg; + + prev = NULL; + oseg = editor->control_sel_l; + tmp = NULL; + + do + { + seg = gimp_gradient_segment_new (); + + *seg = *oseg; /* Copy everything */ + + if (prev == NULL) + tmp = seg; /* Remember first segment */ + else + prev->next = seg; + + seg->prev = prev; + seg->next = NULL; + + prev = seg; + oaseg = oseg; + oseg = oseg->next; + } + while (oaseg != editor->control_sel_r); + + return tmp; +} + +static void +gradient_editor_replace_selection (GradientEditor *editor, + GimpGradientSegment *replace_seg) +{ + GimpGradient *gradient; + GimpGradientSegment *lseg, *rseg; + GimpGradientSegment *replace_last; + + gradient = gimp_context_get_gradient (editor->context); + + /* Remember left and right segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + replace_last = gimp_gradient_segment_get_last (replace_seg); + + /* Free old selection */ + + editor->control_sel_r->next = NULL; + + gimp_gradient_segments_free (editor->control_sel_l); + + /* Link in new segments */ + + if (lseg) + lseg->next = replace_seg; + else + gradient->segments = replace_seg; + + replace_seg->prev = lseg; + + if (rseg) + rseg->prev = replace_last; + + replace_last->next = rseg; + + editor->control_sel_l = replace_seg; + editor->control_sel_r = replace_last; + + gradient->last_visited = NULL; /* Force re-search */ +} + +static void +gradient_editor_dialog_cancel_callback (GtkWidget *widget, + GradientEditor *editor) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); +} + +static void +gradient_editor_split_uniform_callback (GtkWidget *widget, + GradientEditor *editor) +{ + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg, *lseg, *rseg, *lsel; + + gradient = gimp_context_get_gradient (editor->context); + + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); + + seg = editor->control_sel_l; + lsel = NULL; + + do + { + aseg = seg; + + gimp_gradient_segment_split_uniform (gradient, seg, + editor->split_parts, &lseg, &rseg); + + if (seg == editor->control_sel_l) + lsel = lseg; + + seg = rseg->next; + } + while (aseg != editor->control_sel_r); + + editor->control_sel_l = lsel; + editor->control_sel_r = rseg; + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +static void +gradient_editor_replicate_callback (GtkWidget *widget, + GradientEditor *editor) +{ + GimpGradient *gradient; + gdouble sel_left, sel_right, sel_len; + gdouble new_left; + gdouble factor; + GimpGradientSegment *prev, *seg, *tmp; + GimpGradientSegment *oseg, *oaseg; + GimpGradientSegment *lseg, *rseg; + gint i; + + gradient = gimp_context_get_gradient (editor->context); + + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); + + /* Remember original parameters */ + sel_left = editor->control_sel_l->left; + sel_right = editor->control_sel_r->right; + sel_len = sel_right - sel_left; + + factor = 1.0 / editor->replicate_times; + + /* Build replicated segments */ + + prev = NULL; + seg = NULL; + tmp = NULL; + + for (i = 0; i < editor->replicate_times; i++) + { + /* Build one cycle */ + + new_left = sel_left + i * factor * sel_len; + + oseg = editor->control_sel_l; + + do + { + seg = gimp_gradient_segment_new (); + + if (prev == NULL) + { + seg->left = sel_left; + tmp = seg; /* Remember first segment */ + } + else + seg->left = new_left + factor * (oseg->left - sel_left); + + seg->middle = new_left + factor * (oseg->middle - sel_left); + seg->right = new_left + factor * (oseg->right - sel_left); + + seg->left_color = oseg->right_color; + + seg->right_color = oseg->right_color; + + seg->type = oseg->type; + seg->color = oseg->color; + + seg->prev = prev; + seg->next = NULL; + + if (prev) + prev->next = seg; + + prev = seg; + + oaseg = oseg; + oseg = oseg->next; + } + while (oaseg != editor->control_sel_r); + } + + seg->right = sel_right; /* Squish accumulative error */ + + /* Free old segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + oseg = editor->control_sel_l; + + do + { + oaseg = oseg->next; + gimp_gradient_segment_free (oseg); + oseg = oaseg; + } + while (oaseg != rseg); + + /* Link in new segments */ + + if (lseg) + lseg->next = tmp; + else + gradient->segments = tmp; + + tmp->prev = lseg; + + seg->next = rseg; + + if (rseg) + rseg->prev = seg; + + /* Reset selection */ + + editor->control_sel_l = tmp; + editor->control_sel_r = seg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} diff --git a/app/actions/gradient-editor-commands.h b/app/actions/gradient-editor-commands.h new file mode 100644 index 0000000000..8bd0900e28 --- /dev/null +++ b/app/actions/gradient-editor-commands.h @@ -0,0 +1,82 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GRADIENT_EDITOR_COMMANDS_H__ +#define __GRADIENT_EDITOR_COMMANDS_H__ + + +void gradient_editor_left_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_load_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_save_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_right_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_load_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_save_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_blending_func_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_coloring_type_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_flip_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_replicate_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_split_midpoint_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_split_uniformly_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_delete_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_recenter_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_redistribute_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_blend_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_blend_opacity_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_show_context_menu (GradientEditor *editor); + + +#endif /* __GRADIENT_EDITOR_COMMANDS_H__ */ diff --git a/app/core/core-types.h b/app/core/core-types.h index 3f40e42f79..1d2e8ff988 100644 --- a/app/core/core-types.h +++ b/app/core/core-types.h @@ -176,6 +176,22 @@ typedef enum SPIRAL_ANTICLOCKWISE } GradientType; +typedef enum /*< skip >*/ +{ + GRAD_LINEAR = 0, + GRAD_CURVED, + GRAD_SINE, + GRAD_SPHERE_INCREASING, + GRAD_SPHERE_DECREASING +} GimpGradientSegmentType; + +typedef enum /*< skip >*/ +{ + GRAD_RGB = 0, /* normal RGB */ + GRAD_HSV_CCW, /* counterclockwise hue */ + GRAD_HSV_CW /* clockwise hue */ +} GimpGradientSegmentColor; + typedef enum /*< chop=_MODE >*/ { FG_BG_RGB_MODE, diff --git a/app/core/gimpcontainer.c b/app/core/gimpcontainer.c index e1ecdefe91..7cf684cf9c 100644 --- a/app/core/gimpcontainer.c +++ b/app/core/gimpcontainer.c @@ -205,22 +205,11 @@ gimp_container_class_init (GimpContainerClass *klass) klass->get_child_by_index = NULL; klass->get_child_index = NULL; - /* spit out a warning once GType becomes a gpointer */ - { - guint32 *foo = NULL; - GType *bar; - - bar = foo; - } - g_object_class_install_property (object_class, PROP_CHILDREN_TYPE, - g_param_spec_uint ("children_type", - NULL, NULL, - GIMP_TYPE_OBJECT, - G_MAXINT, - GIMP_TYPE_OBJECT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_param_spec_pointer ("children_type", + NULL, NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_POLICY, @@ -278,7 +267,7 @@ gimp_container_set_property (GObject *object, switch (property_id) { case PROP_CHILDREN_TYPE: - container->children_type = (GType) g_value_get_uint (value); + container->children_type = (GType) g_value_get_pointer (value); g_type_class_ref (container->children_type); break; case PROP_POLICY: @@ -303,7 +292,7 @@ gimp_container_get_property (GObject *object, switch (property_id) { case PROP_CHILDREN_TYPE: - g_value_set_uint (value, (guint) container->children_type); + g_value_set_pointer (value, (gpointer) container->children_type); break; case PROP_POLICY: g_value_set_enum (value, container->policy); diff --git a/app/core/gimpgradient.c b/app/core/gimpgradient.c index 07ec18d6f0..323da99e90 100644 --- a/app/core/gimpgradient.c +++ b/app/core/gimpgradient.c @@ -811,3 +811,242 @@ gimp_gradient_segment_get_last (GimpGradientSegment *seg) return seg; } + +GimpGradientSegment * +gimp_gradient_segment_get_first (GimpGradientSegment *seg) +{ + if (!seg) + return NULL; + + while (seg->prev) + seg = seg->prev; + + return seg; +} + +void +gimp_gradient_segment_split_midpoint (GimpGradient *gradient, + GimpGradientSegment *lseg, + GimpGradientSegment **newl, + GimpGradientSegment **newr) +{ + GimpRGB color; + GimpGradientSegment *newseg; + + g_return_if_fail (GIMP_IS_GRADIENT (gradient)); + g_return_if_fail (lseg != NULL); + g_return_if_fail (newl != NULL); + g_return_if_fail (newr != NULL); + + /* Get color at original segment's midpoint */ + gimp_gradient_get_color_at (gradient, lseg->middle, &color); + + /* Create a new segment and insert it in the list */ + + newseg = gimp_gradient_segment_new (); + + newseg->prev = lseg; + newseg->next = lseg->next; + + lseg->next = newseg; + + if (newseg->next) + newseg->next->prev = newseg; + + /* Set coordinates of new segment */ + + newseg->left = lseg->middle; + newseg->right = lseg->right; + newseg->middle = (newseg->left + newseg->right) / 2.0; + + /* Set coordinates of original segment */ + + lseg->right = newseg->left; + lseg->middle = (lseg->left + lseg->right) / 2.0; + + /* Set colors of both segments */ + + newseg->right_color = lseg->right_color; + + lseg->right_color.r = newseg->left_color.r = color.r; + lseg->right_color.g = newseg->left_color.g = color.g; + lseg->right_color.b = newseg->left_color.b = color.b; + lseg->right_color.a = newseg->left_color.a = color.a; + + /* Set parameters of new segment */ + + newseg->type = lseg->type; + newseg->color = lseg->color; + + /* Done */ + + *newl = lseg; + *newr = newseg; +} + +void +gimp_gradient_segment_split_uniform (GimpGradient *gradient, + GimpGradientSegment *lseg, + gint parts, + GimpGradientSegment **newl, + GimpGradientSegment **newr) +{ + GimpGradientSegment *seg, *prev, *tmp; + gdouble seg_len; + gint i; + + g_return_if_fail (GIMP_IS_GRADIENT (gradient)); + g_return_if_fail (lseg != NULL); + g_return_if_fail (newl != NULL); + g_return_if_fail (newr != NULL); + + seg_len = (lseg->right - lseg->left) / parts; /* Length of divisions */ + + seg = NULL; + prev = NULL; + tmp = NULL; + + for (i = 0; i < parts; i++) + { + seg = gimp_gradient_segment_new (); + + if (i == 0) + tmp = seg; /* Remember first segment */ + + seg->left = lseg->left + i * seg_len; + seg->right = lseg->left + (i + 1) * seg_len; + seg->middle = (seg->left + seg->right) / 2.0; + + gimp_gradient_get_color_at (gradient, seg->left, &seg->left_color); + gimp_gradient_get_color_at (gradient, seg->right, &seg->right_color); + + seg->type = lseg->type; + seg->color = lseg->color; + + seg->prev = prev; + seg->next = NULL; + + if (prev) + prev->next = seg; + + prev = seg; + } + + /* Fix edges */ + + tmp->left_color = lseg->left_color; + + seg->right_color = lseg->right_color; + + tmp->left = lseg->left; + seg->right = lseg->right; /* To squish accumulative error */ + + /* Link in list */ + + tmp->prev = lseg->prev; + seg->next = lseg->next; + + if (lseg->prev) + lseg->prev->next = tmp; + else + gradient->segments = tmp; /* We are on leftmost segment */ + + if (lseg->next) + lseg->next->prev = seg; + + gradient->last_visited = NULL; /* Force re-search */ + + /* Done */ + + *newl = tmp; + *newr = seg; + + /* Delete old segment */ + + gimp_gradient_segment_free (lseg); +} + +void +gimp_gradient_segments_compress_range (GimpGradientSegment *range_l, + GimpGradientSegment *range_r, + gdouble new_l, + gdouble new_r) +{ + gdouble orig_l, orig_r; + gdouble scale; + GimpGradientSegment *seg, *aseg; + + g_return_if_fail (range_l != NULL); + g_return_if_fail (range_r != NULL); + + orig_l = range_l->left; + orig_r = range_r->right; + + scale = (new_r - new_l) / (orig_r - orig_l); + + seg = range_l; + + do + { + seg->left = new_l + (seg->left - orig_l) * scale; + seg->middle = new_l + (seg->middle - orig_l) * scale; + seg->right = new_l + (seg->right - orig_l) * scale; + + /* Next */ + + aseg = seg; + seg = seg->next; + } + while (aseg != range_r); +} + +void +gimp_gradient_segments_blend_endpoints (GimpGradientSegment *lseg, + GimpGradientSegment *rseg, + GimpRGB *rgb1, + GimpRGB *rgb2, + gboolean blend_colors, + gboolean blend_opacity) +{ + GimpRGB d; + gdouble left, len; + GimpGradientSegment *seg; + GimpGradientSegment *aseg; + + g_return_if_fail (lseg != NULL); + g_return_if_fail (rseg != NULL); + + d.r = rgb2->r - rgb1->r; + d.g = rgb2->g - rgb1->g; + d.b = rgb2->b - rgb1->b; + d.a = rgb2->a - rgb1->a; + + left = lseg->left; + len = rseg->right - left; + + seg = lseg; + + do + { + if (blend_colors) + { + seg->left_color.r = rgb1->r + (seg->left - left) / len * d.r; + seg->left_color.g = rgb1->g + (seg->left - left) / len * d.g; + seg->left_color.b = rgb1->b + (seg->left - left) / len * d.b; + + seg->right_color.r = rgb1->r + (seg->right - left) / len * d.r; + seg->right_color.g = rgb1->g + (seg->right - left) / len * d.g; + seg->right_color.b = rgb1->b + (seg->right - left) / len * d.b; + } + + if (blend_opacity) + { + seg->left_color.a = rgb1->a + (seg->left - left) / len * d.a; + seg->right_color.a = rgb1->a + (seg->right - left) / len * d.a; + } + + aseg = seg; + seg = seg->next; + } + while (aseg != rseg); +} diff --git a/app/core/gimpgradient.h b/app/core/gimpgradient.h index 5fbdb5dd1a..a593f81215 100644 --- a/app/core/gimpgradient.h +++ b/app/core/gimpgradient.h @@ -28,23 +28,6 @@ #define GIMP_GRADIENT_DEFAULT_SAMPLE_SIZE 40 -typedef enum -{ - GRAD_LINEAR = 0, - GRAD_CURVED, - GRAD_SINE, - GRAD_SPHERE_INCREASING, - GRAD_SPHERE_DECREASING -} GimpGradientSegmentType; - -typedef enum -{ - GRAD_RGB = 0, /* normal RGB */ - GRAD_HSV_CCW, /* counterclockwise hue */ - GRAD_HSV_CW /* clockwise hue */ -} GimpGradientSegmentColor; - - typedef struct _GimpGradientSegment GimpGradientSegment; struct _GimpGradientSegment @@ -101,11 +84,32 @@ GimpGradientSegment * gimp_gradient_get_segment_at (GimpGradient *grad, /* gradient segment functions */ -GimpGradientSegment * gimp_gradient_segment_new (void); -GimpGradientSegment * gimp_gradient_segment_get_last (GimpGradientSegment *seg); +GimpGradientSegment * gimp_gradient_segment_new (void); +GimpGradientSegment * gimp_gradient_segment_get_last (GimpGradientSegment *seg); +GimpGradientSegment * gimp_gradient_segment_get_first (GimpGradientSegment *seg); void gimp_gradient_segment_free (GimpGradientSegment *seg); void gimp_gradient_segments_free (GimpGradientSegment *seg); +void gimp_gradient_segment_split_midpoint (GimpGradient *gradient, + GimpGradientSegment *lseg, + GimpGradientSegment **newl, + GimpGradientSegment **newr); +void gimp_gradient_segment_split_uniform (GimpGradient *gradient, + GimpGradientSegment *lseg, + gint parts, + GimpGradientSegment **newl, + GimpGradientSegment **newr); + +void gimp_gradient_segments_compress_range (GimpGradientSegment *range_l, + GimpGradientSegment *range_r, + gdouble new_l, + gdouble new_r); +void gimp_gradient_segments_blend_endpoints (GimpGradientSegment *lseg, + GimpGradientSegment *rseg, + GimpRGB *rgb1, + GimpRGB *rgb2, + gboolean blend_colors, + gboolean blend_opacity); #endif /* __GIMP_GRADIENT_H__ */ diff --git a/app/display/gimpdisplayshell-draw.c b/app/display/gimpdisplayshell-draw.c index 98e91a43e6..ba341e9389 100644 --- a/app/display/gimpdisplayshell-draw.c +++ b/app/display/gimpdisplayshell-draw.c @@ -953,8 +953,8 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) #define SET_SENSITIVE(menu,condition) \ menus_set_sensitive ("/" menu, (condition) != 0) -#define SET_STATE(menu,condition) \ - menus_set_state ("/" menu, (condition) != 0) +#define SET_ACTIVE(menu,condition) \ + menus_set_active ("/" menu, (condition) != 0) SET_SENSITIVE ("File/Save", gdisp && drawable); SET_SENSITIVE ("File/Save as...", gdisp && drawable); @@ -998,15 +998,15 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) SET_SENSITIVE ("View/Zoom", gdisp); if (gdisp) { - SET_STATE ("View/Toggle Selection", ! shell->select->hidden); - SET_STATE ("View/Toggle Layer Boundary", ! shell->select->layer_hidden); - SET_STATE ("View/Toggle Rulers", - GTK_WIDGET_VISIBLE (shell->origin) ? 1 : 0); - SET_STATE ("View/Toggle Guides", gdisp->draw_guides); - SET_STATE ("View/Snap to Guides", gdisp->snap_to_guides); - SET_STATE ("View/Toggle Statusbar", - GTK_WIDGET_VISIBLE (shell->statusarea) ? 1 : 0); - SET_STATE ("View/Dot for Dot", gdisp->dot_for_dot); + SET_ACTIVE ("View/Toggle Selection", ! shell->select->hidden); + SET_ACTIVE ("View/Toggle Layer Boundary", ! shell->select->layer_hidden); + SET_ACTIVE ("View/Toggle Rulers", + GTK_WIDGET_VISIBLE (shell->origin) ? 1 : 0); + SET_ACTIVE ("View/Toggle Guides", gdisp->draw_guides); + SET_ACTIVE ("View/Snap to Guides", gdisp->snap_to_guides); + SET_ACTIVE ("View/Toggle Statusbar", + GTK_WIDGET_VISIBLE (shell->statusarea) ? 1 : 0); + SET_ACTIVE ("View/Dot for Dot", gdisp->dot_for_dot); } SET_SENSITIVE ("Image", gdisp); @@ -1073,7 +1073,7 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) SET_SENSITIVE ("Script-Fu", gdisp && lp); -#undef SET_STATE +#undef SET_ACTIVE #undef SET_SENSITIVE plug_in_set_menu_sensitivity (type); diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 98e91a43e6..ba341e9389 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -953,8 +953,8 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) #define SET_SENSITIVE(menu,condition) \ menus_set_sensitive ("/" menu, (condition) != 0) -#define SET_STATE(menu,condition) \ - menus_set_state ("/" menu, (condition) != 0) +#define SET_ACTIVE(menu,condition) \ + menus_set_active ("/" menu, (condition) != 0) SET_SENSITIVE ("File/Save", gdisp && drawable); SET_SENSITIVE ("File/Save as...", gdisp && drawable); @@ -998,15 +998,15 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) SET_SENSITIVE ("View/Zoom", gdisp); if (gdisp) { - SET_STATE ("View/Toggle Selection", ! shell->select->hidden); - SET_STATE ("View/Toggle Layer Boundary", ! shell->select->layer_hidden); - SET_STATE ("View/Toggle Rulers", - GTK_WIDGET_VISIBLE (shell->origin) ? 1 : 0); - SET_STATE ("View/Toggle Guides", gdisp->draw_guides); - SET_STATE ("View/Snap to Guides", gdisp->snap_to_guides); - SET_STATE ("View/Toggle Statusbar", - GTK_WIDGET_VISIBLE (shell->statusarea) ? 1 : 0); - SET_STATE ("View/Dot for Dot", gdisp->dot_for_dot); + SET_ACTIVE ("View/Toggle Selection", ! shell->select->hidden); + SET_ACTIVE ("View/Toggle Layer Boundary", ! shell->select->layer_hidden); + SET_ACTIVE ("View/Toggle Rulers", + GTK_WIDGET_VISIBLE (shell->origin) ? 1 : 0); + SET_ACTIVE ("View/Toggle Guides", gdisp->draw_guides); + SET_ACTIVE ("View/Snap to Guides", gdisp->snap_to_guides); + SET_ACTIVE ("View/Toggle Statusbar", + GTK_WIDGET_VISIBLE (shell->statusarea) ? 1 : 0); + SET_ACTIVE ("View/Dot for Dot", gdisp->dot_for_dot); } SET_SENSITIVE ("Image", gdisp); @@ -1073,7 +1073,7 @@ gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell) SET_SENSITIVE ("Script-Fu", gdisp && lp); -#undef SET_STATE +#undef SET_ACTIVE #undef SET_SENSITIVE plug_in_set_menu_sensitivity (type); diff --git a/app/gui/Makefile.am b/app/gui/Makefile.am index 347a9458d6..b8cbf0167d 100644 --- a/app/gui/Makefile.am +++ b/app/gui/Makefile.am @@ -54,6 +54,8 @@ libappgui_a_SOURCES = @STRIP_BEGIN@ \ file-save-dialog.h \ gradient-editor.c \ gradient-editor.h \ + gradient-editor-commands.c \ + gradient-editor-commands.h \ gradient-select.h \ gradient-select.c \ gradients-commands.c \ diff --git a/app/gui/gradient-editor-commands.c b/app/gui/gradient-editor-commands.c new file mode 100644 index 0000000000..9d68b093c5 --- /dev/null +++ b/app/gui/gradient-editor-commands.c @@ -0,0 +1,1479 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "gui-types.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpgradient.h" + +#include "widgets/gimpwidgets-utils.h" + +#include "color-notebook.h" +#include "gradient-editor.h" +#include "gradient-editor-commands.h" +#include "menus.h" + +#include "libgimp/gimpintl.h" + + +/* local function prototypes */ + +static void gradient_editor_menu_set_sensitivity (GradientEditor *editor); +static void gradient_editor_left_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data); +static void gradient_editor_right_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data); + +static GimpGradientSegment * + gradient_editor_save_selection (GradientEditor *editor); +static void gradient_editor_replace_selection (GradientEditor *editor, + GimpGradientSegment *replace_seg); + +static void gradient_editor_dialog_cancel_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_split_uniform_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_replicate_callback (GtkWidget *widget, + GradientEditor *editor); + + +/* public functionss */ + +void +gradient_editor_left_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + editor->left_saved_dirty = GIMP_DATA (gradient)->dirty; + editor->left_saved_segments = gradient_editor_save_selection (editor); + + color_notebook_new (_("Left Endpoint Color"), + &editor->control_sel_l->left_color, + gradient_editor_left_color_changed, + editor, + editor->instant_update, + TRUE); + + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_load_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradientSegment *seg; + GimpRGB color; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + i = (gint) action; + + switch (i) + { + case 0: /* Fetch from left neighbor's right endpoint */ + if (editor->control_sel_l->prev != NULL) + seg = editor->control_sel_l->prev; + else + seg = gimp_gradient_segment_get_last (editor->control_sel_l); + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &seg->right_color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 1: /* Fetch from right endpoint */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->right_color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 2: /* Fetch from FG color */ + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + case 3: /* Fetch from BG color */ + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + + default: /* Load a color */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->saved_colors[i - 4], + &editor->control_sel_r->right_color, + TRUE, TRUE); + break; + } + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_save_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + editor->saved_colors[action] = editor->control_sel_l->left_color; +} + +void +gradient_editor_right_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + editor->right_saved_dirty = GIMP_DATA (gradient)->dirty; + editor->right_saved_segments = gradient_editor_save_selection (editor); + + color_notebook_new (_("Right Endpoint Color"), + &editor->control_sel_l->right_color, + gradient_editor_right_color_changed, + editor, + editor->instant_update, + TRUE); + + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_load_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradientSegment *seg; + GimpRGB color; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + i = (gint) action; + + switch (i) + { + case 0: /* Fetch from right neighbor's left endpoint */ + if (editor->control_sel_r->next != NULL) + seg = editor->control_sel_r->next; + else + seg = gimp_gradient_segment_get_first (editor->control_sel_r); + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + &seg->left_color, + TRUE, TRUE); + break; + + case 1: /* Fetch from left endpoint */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_l->left_color, + TRUE, TRUE); + break; + + case 2: /* Fetch from FG color */ + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &color, + TRUE, TRUE); + break; + + case 3: /* Fetch from BG color */ + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &color); + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &color, + TRUE, TRUE); + break; + + default: /* Load a color */ + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->saved_colors[i - 4], + TRUE, TRUE); + break; + } + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_save_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + editor->saved_colors[action] = editor->control_sel_l->left_color; +} + +void +gradient_editor_blending_func_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegmentType type; + GimpGradientSegment *seg, *aseg; + + if (! GTK_CHECK_MENU_ITEM (widget)->active) + return; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + type = (GimpGradientSegmentType) action; + + seg = editor->control_sel_l; + + do + { + seg->type = type; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_coloring_type_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegmentColor color; + GimpGradientSegment *seg, *aseg; + + if (! GTK_CHECK_MENU_ITEM (widget)->active) + return; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + color = (GimpGradientSegmentColor) action; + + seg = editor->control_sel_l; + + do + { + seg->color = color; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_flip_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *oseg, *oaseg; + GimpGradientSegment *seg, *prev, *tmp; + GimpGradientSegment *lseg, *rseg; + gdouble left, right; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + left = editor->control_sel_l->left; + right = editor->control_sel_r->right; + + /* Build flipped segments */ + + prev = NULL; + oseg = editor->control_sel_r; + tmp = NULL; + + do + { + seg = gimp_gradient_segment_new (); + + if (prev == NULL) + { + seg->left = left; + tmp = seg; /* Remember first segment */ + } + else + seg->left = left + right - oseg->right; + + seg->middle = left + right - oseg->middle; + seg->right = left + right - oseg->left; + + seg->left_color = oseg->right_color; + + seg->right_color = oseg->left_color; + + switch (oseg->type) + { + case GRAD_SPHERE_INCREASING: + seg->type = GRAD_SPHERE_DECREASING; + break; + + case GRAD_SPHERE_DECREASING: + seg->type = GRAD_SPHERE_INCREASING; + break; + + default: + seg->type = oseg->type; + } + + switch (oseg->color) + { + case GRAD_HSV_CCW: + seg->color = GRAD_HSV_CW; + break; + + case GRAD_HSV_CW: + seg->color = GRAD_HSV_CCW; + break; + + default: + seg->color = oseg->color; + } + + seg->prev = prev; + seg->next = NULL; + + if (prev) + prev->next = seg; + + prev = seg; + + oaseg = oseg; + oseg = oseg->prev; /* Move backwards! */ + } + while (oaseg != editor->control_sel_l); + + seg->right = right; /* Squish accumulative error */ + + /* Free old segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + oseg = editor->control_sel_l; + + do + { + oaseg = oseg->next; + gimp_gradient_segment_free (oseg); + oseg = oaseg; + } + while (oaseg != rseg); + + /* Link in new segments */ + + if (lseg) + lseg->next = tmp; + else + gradient->segments = tmp; + + tmp->prev = lseg; + + seg->next = rseg; + + if (rseg) + rseg->prev = seg; + + /* Reset selection */ + + editor->control_sel_l = tmp; + editor->control_sel_r = seg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_replicate_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GtkWidget *dialog; + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *scale; + GtkObject *scale_data; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + /* Create dialog window */ + dialog = + gimp_dialog_new ((editor->control_sel_l == editor->control_sel_r) ? + _("Replicate segment") : + _("Replicate selection"), + "gradient_segment_replicate", + gimp_standard_help_func, + "dialogs/gradient_editor/replicate_segment.html", + GTK_WIN_POS_MOUSE, + FALSE, TRUE, FALSE, + + GTK_STOCK_CANCEL, gradient_editor_dialog_cancel_callback, + editor, NULL, NULL, TRUE, TRUE, + + _("Replicate"), gradient_editor_replicate_callback, + editor, NULL, NULL, FALSE, FALSE, + + NULL); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); + gtk_widget_show (vbox); + + /* Instructions */ + label = gtk_label_new (_("Select the number of times")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + label = gtk_label_new ((editor->control_sel_l == editor->control_sel_r) ? + _("to replicate the selected segment") : + _("to replicate the selection")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* Scale */ + editor->replicate_times = 2; + scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); + + scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 4); + gtk_widget_show (scale); + + g_signal_connect (G_OBJECT (scale_data), "value_changed", + G_CALLBACK (gimp_int_adjustment_update), + &editor->replicate_times); + + /* Show! */ + gtk_widget_show (dialog); + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_split_midpoint_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *lseg, *rseg; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + seg = editor->control_sel_l; + + do + { + gimp_gradient_segment_split_midpoint (gradient, seg, &lseg, &rseg); + seg = rseg->next; + } + while (lseg != editor->control_sel_r); + + editor->control_sel_r = rseg; + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_split_uniformly_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GtkWidget *dialog; + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *scale; + GtkObject *scale_data; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + /* Create dialog window */ + dialog = + gimp_dialog_new ((editor->control_sel_l == editor->control_sel_r) ? + _("Split Segment Uniformly") : + _("Split Segments Uniformly"), + "gradient_segment_split_uniformly", + gimp_standard_help_func, + "dialogs/gradient_editor/split_segments_uniformly.html", + GTK_WIN_POS_MOUSE, + FALSE, TRUE, FALSE, + + GTK_STOCK_CANCEL, gradient_editor_dialog_cancel_callback, + editor, NULL, NULL, FALSE, TRUE, + + _("Split"), gradient_editor_split_uniform_callback, + editor, NULL, NULL, TRUE, FALSE, + + NULL); + + /* The main vbox */ + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); + gtk_widget_show (vbox); + + /* Instructions */ + label = gtk_label_new (_("Please select the number of uniform parts")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + label = + gtk_label_new ((editor->control_sel_l == editor->control_sel_r) ? + _("in which to split the selected segment") : + _("in which to split the segments in the selection")); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + /* Scale */ + editor->split_parts = 2; + scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); + + scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 4); + gtk_widget_show (scale); + + g_signal_connect (G_OBJECT (scale_data), "value_changed", + G_CALLBACK (gimp_int_adjustment_update), + &editor->split_parts); + + /* Show! */ + gtk_widget_show (dialog); + gtk_widget_set_sensitive (editor->shell, FALSE); +} + +void +gradient_editor_delete_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *lseg, *rseg, *seg, *aseg, *next; + gdouble join; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + /* Remember segments to the left and to the right of the selection */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + /* Cannot delete all the segments in the gradient */ + + if ((lseg == NULL) && (rseg == NULL)) + return; + + /* Calculate join point */ + + join = (editor->control_sel_l->left + + editor->control_sel_r->right) / 2.0; + + if (lseg == NULL) + join = 0.0; + else if (rseg == NULL) + join = 1.0; + + /* Move segments */ + + if (lseg != NULL) + gimp_gradient_segments_compress_range (lseg, lseg, lseg->left, join); + + if (rseg != NULL) + gimp_gradient_segments_compress_range (rseg, rseg, join, rseg->right); + + /* Link */ + + if (lseg) + lseg->next = rseg; + + if (rseg) + rseg->prev = lseg; + + /* Delete old segments */ + + seg = editor->control_sel_l; + + do + { + next = seg->next; + aseg = seg; + + gimp_gradient_segment_free (seg); + + seg = next; + } + while (aseg != editor->control_sel_r); + + /* Change selection */ + + if (rseg) + { + editor->control_sel_l = rseg; + editor->control_sel_r = rseg; + } + else + { + editor->control_sel_l = lseg; + editor->control_sel_r = lseg; + } + + if (lseg == NULL) + gradient->segments = rseg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_recenter_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + seg = editor->control_sel_l; + + do + { + seg->middle = (seg->left + seg->right) / 2.0; + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_redistribute_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg; + gdouble left, right, seg_len; + gint num_segs; + gint i; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gradient = gimp_context_get_gradient (editor->context); + + /* Count number of segments in selection */ + + num_segs = 0; + seg = editor->control_sel_l; + + do + { + num_segs++; + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + + /* Calculate new segment length */ + + left = editor->control_sel_l->left; + right = editor->control_sel_r->right; + seg_len = (right - left) / num_segs; + + /* Redistribute */ + + seg = editor->control_sel_l; + + for (i = 0; i < num_segs; i++) + { + seg->left = left + i * seg_len; + seg->right = left + (i + 1) * seg_len; + seg->middle = (seg->left + seg->right) / 2.0; + + seg = seg->next; + } + + /* Fix endpoints to squish accumulative error */ + + editor->control_sel_l->left = left; + editor->control_sel_r->right = right; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +void +gradient_editor_blend_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_r->right_color, + TRUE, FALSE); + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_blend_opacity_cmd_callback (GtkWidget *widget, + gpointer data, + guint action) +{ + GradientEditor *editor; + + editor = (GradientEditor *) gimp_widget_get_callback_context (widget); + + if (! editor) + return; + + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_l->left_color, + &editor->control_sel_r->right_color, + FALSE, TRUE); + + gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (editor->context))); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +void +gradient_editor_show_context_menu (GradientEditor *editor) +{ + GtkItemFactory *item_factory; + + gradient_editor_menu_set_sensitivity (editor); + + item_factory = menus_get_gradient_editor_factory (); + + gimp_item_factory_popup_with_data (item_factory, editor); +} + + +/* private functions */ + +static void +gradient_editor_menu_set_sensitivity (GradientEditor *editor) +{ + GimpGradientSegment *left_seg; + GimpGradientSegment *right_seg; + GimpRGB fg; + GimpRGB bg; + gboolean blending_equal = TRUE; + gboolean coloring_equal = TRUE; + gboolean selection; + gboolean delete; + + if (editor->control_sel_l->prev) + left_seg = editor->control_sel_l->prev; + else + left_seg = gimp_gradient_segment_get_last (editor->control_sel_l); + + if (editor->control_sel_r->next) + right_seg = editor->control_sel_r->next; + else + right_seg = gimp_gradient_segment_get_first (editor->control_sel_r); + + gimp_context_get_foreground (gimp_get_user_context (editor->context->gimp), + &fg); + gimp_context_get_background (gimp_get_user_context (editor->context->gimp), + &bg); + + { + GimpGradientSegmentType type; + GimpGradientSegmentColor color; + GimpGradientSegment *seg, *aseg; + + type = editor->control_sel_l->type; + color = editor->control_sel_l->color; + + seg = editor->control_sel_l; + + do + { + blending_equal = blending_equal && (seg->type == type); + coloring_equal = coloring_equal && (seg->color == color); + + aseg = seg; + seg = seg->next; + } + while (aseg != editor->control_sel_r); + } + + selection = (editor->control_sel_l != editor->control_sel_r); + delete = (editor->control_sel_l->prev || editor->control_sel_r->next); + +#define SET_ACTIVE(menu,active) \ + menus_set_active ("/" menu, (active)) +#define SET_COLOR(menu,color,set_label) \ + menus_set_color ("/" menu, (color), (set_label)) +#define SET_LABEL(menu,label) \ + menus_set_label ("/" menu, (label)) +#define SET_SENSITIVE(menu,condition) \ + menus_set_sensitive ("/" menu, (condition) != 0) +#define SET_VISIBLE(menu,condition) \ + menus_set_visible ("/" menu, (condition) != 0) + + SET_COLOR ("Left Endpoint's Color...", + &editor->control_sel_l->left_color, FALSE); + SET_COLOR ("Load Left Color From/Left Neighbor's Right Endpoint", + &left_seg->right_color, FALSE); + SET_COLOR ("Load Left Color From/Right Endpoint", + &editor->control_sel_r->right_color, FALSE); + SET_COLOR ("Load Left Color From/FG Color", &fg, FALSE); + SET_COLOR ("Load Left Color From/BG Color", &bg, FALSE); + + SET_COLOR ("Load Left Color From/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Load Left Color From/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Load Left Color From/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Load Left Color From/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Load Left Color From/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Load Left Color From/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Load Left Color From/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Load Left Color From/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Load Left Color From/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Load Left Color From/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Save Left Color To/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Save Left Color To/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Save Left Color To/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Save Left Color To/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Save Left Color To/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Save Left Color To/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Save Left Color To/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Save Left Color To/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Save Left Color To/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Save Left Color To/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Right Endpoint's Color...", + &editor->control_sel_r->right_color, FALSE); + SET_COLOR ("Load Right Color From/Right Neighbor's Left Endpoint", + &right_seg->left_color, FALSE); + SET_COLOR ("Load Right Color From/Left Endpoint", + &editor->control_sel_l->left_color, FALSE); + SET_COLOR ("Load Right Color From/FG Color", &fg, FALSE); + SET_COLOR ("Load Right Color From/BG Color", &bg, FALSE); + + SET_COLOR ("Load Right Color From/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Load Right Color From/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Load Right Color From/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Load Right Color From/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Load Right Color From/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Load Right Color From/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Load Right Color From/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Load Right Color From/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Load Right Color From/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Load Right Color From/10", &editor->saved_colors[9], TRUE); + + SET_COLOR ("Save Right Color To/01", &editor->saved_colors[0], TRUE); + SET_COLOR ("Save Right Color To/02", &editor->saved_colors[1], TRUE); + SET_COLOR ("Save Right Color To/03", &editor->saved_colors[2], TRUE); + SET_COLOR ("Save Right Color To/04", &editor->saved_colors[3], TRUE); + SET_COLOR ("Save Right Color To/05", &editor->saved_colors[4], TRUE); + SET_COLOR ("Save Right Color To/06", &editor->saved_colors[5], TRUE); + SET_COLOR ("Save Right Color To/07", &editor->saved_colors[6], TRUE); + SET_COLOR ("Save Right Color To/08", &editor->saved_colors[7], TRUE); + SET_COLOR ("Save Right Color To/09", &editor->saved_colors[8], TRUE); + SET_COLOR ("Save Right Color To/10", &editor->saved_colors[9], TRUE); + + if (! selection) + { + SET_LABEL ("flip", _("Flip Segment")); + SET_LABEL ("replicate", _("Replicate Segment")); + SET_LABEL ("blendingfunction", _("Blending Function for Segment")); + SET_LABEL ("coloringtype", _("Coloring Type for Segment")); + SET_LABEL ("splitmidpoint", _("Split Segment at Midpoint")); + SET_LABEL ("splituniformly", _("Split Segment Uniformly")); + SET_LABEL ("delete", _("Delete Segment")); + SET_LABEL ("recenter", _("Re-center Segment's Midpoint")); + SET_LABEL ("redistribute", _("Re-distribute Handles in Segment")); + } + else + { + SET_LABEL ("flip", _("Flip Selection")); + SET_LABEL ("replicate", _("Replicate Selection")); + SET_LABEL ("blendingfunction", _("Blending Function for Selection")); + SET_LABEL ("coloringtype", _("Coloring Type for Selection")); + SET_LABEL ("splitmidpoint", _("Split Segments at Midpoints")); + SET_LABEL ("splituniformly", _("Split Segments Uniformly")); + SET_LABEL ("delete", _("Delete Selection")); + SET_LABEL ("recenter", _("Re-center Midpoints in Selection")); + SET_LABEL ("redistribute", _("Re-distribute Handles in Selection")); + } + + SET_SENSITIVE ("blendingfunction/(Varies)", FALSE); + SET_SENSITIVE ("coloringtype/(Varies)", FALSE); + + if (blending_equal) + { + SET_VISIBLE ("blendingfunction/(Varies)", FALSE); + + switch (editor->control_sel_l->type) + { + case GRAD_LINEAR: + SET_ACTIVE ("blendingfunction/Linear", TRUE); + break; + case GRAD_CURVED: + SET_ACTIVE ("blendingfunction/Curved", TRUE); + break; + case GRAD_SINE: + SET_ACTIVE ("blendingfunction/Sinusodial", TRUE); + break; + case GRAD_SPHERE_INCREASING: + SET_ACTIVE ("blendingfunction/Spherical (increasing)", TRUE); + break; + case GRAD_SPHERE_DECREASING: + SET_ACTIVE ("blendingfunction/Spherical (decreasing)", TRUE); + break; + } + } + else + { + SET_VISIBLE ("blendingfunction/(Varies)", TRUE); + SET_ACTIVE ("blendingfunction/(Varies)", TRUE); + } + + if (coloring_equal) + { + SET_VISIBLE ("coloringtype/(Varies)", FALSE); + + switch (editor->control_sel_l->color) + { + case GRAD_RGB: + SET_ACTIVE ("coloringtype/RGB", TRUE); + break; + case GRAD_HSV_CCW: + SET_ACTIVE ("coloringtype/HSV (counter-clockwise hue)", TRUE); + break; + case GRAD_HSV_CW: + SET_ACTIVE ("coloringtype/HSV (clockwise hue)", TRUE); + break; + } + } + else + { + SET_VISIBLE ("coloringtype/(Varies)", TRUE); + SET_ACTIVE ("coloringtype/(Varies)", TRUE); + } + + SET_SENSITIVE ("Blend Endpoints' Colors", selection); + SET_SENSITIVE ("Blend Endpoints' Opacity", selection); + SET_SENSITIVE ("delete", delete); + +#undef SET_ACTIVE +#undef SET_COLOR +#undef SET_LABEL +#undef SET_SENSITIVE +#undef SET_VISIBLE +} + +static void +gradient_editor_left_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) data; + + gradient = gimp_context_get_gradient (editor->context); + + switch (state) + { + case COLOR_NOTEBOOK_OK: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + (GimpRGB *) color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + gimp_gradient_segments_free (editor->left_saved_segments); + gimp_data_dirty (GIMP_DATA (gradient)); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + + case COLOR_NOTEBOOK_UPDATE: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + (GimpRGB *) color, + &editor->control_sel_r->right_color, + TRUE, TRUE); + gimp_data_dirty (GIMP_DATA (gradient)); + break; + + case COLOR_NOTEBOOK_CANCEL: + gradient_editor_replace_selection (editor, editor->left_saved_segments); + GIMP_DATA (gradient)->dirty = editor->left_saved_dirty; + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + } + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +static void +gradient_editor_right_color_changed (ColorNotebook *cnb, + const GimpRGB *color, + ColorNotebookState state, + gpointer data) +{ + GradientEditor *editor; + GimpGradient *gradient; + + editor = (GradientEditor *) data; + + gradient = gimp_context_get_gradient (editor->context); + + switch (state) + { + case COLOR_NOTEBOOK_UPDATE: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + (GimpRGB *) color, + TRUE, TRUE); + gimp_data_dirty (GIMP_DATA (gradient)); + break; + + case COLOR_NOTEBOOK_OK: + gimp_gradient_segments_blend_endpoints (editor->control_sel_l, + editor->control_sel_r, + &editor->control_sel_r->left_color, + (GimpRGB *) color, + TRUE, TRUE); + gimp_gradient_segments_free (editor->right_saved_segments); + gimp_data_dirty (GIMP_DATA (gradient)); + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + + case COLOR_NOTEBOOK_CANCEL: + gradient_editor_replace_selection (editor, editor->right_saved_segments); + GIMP_DATA (gradient)->dirty = editor->right_saved_dirty; + color_notebook_free (cnb); + gtk_widget_set_sensitive (editor->shell, TRUE); + break; + } + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); +} + +static GimpGradientSegment * +gradient_editor_save_selection (GradientEditor *editor) +{ + GimpGradientSegment *seg, *prev, *tmp; + GimpGradientSegment *oseg, *oaseg; + + prev = NULL; + oseg = editor->control_sel_l; + tmp = NULL; + + do + { + seg = gimp_gradient_segment_new (); + + *seg = *oseg; /* Copy everything */ + + if (prev == NULL) + tmp = seg; /* Remember first segment */ + else + prev->next = seg; + + seg->prev = prev; + seg->next = NULL; + + prev = seg; + oaseg = oseg; + oseg = oseg->next; + } + while (oaseg != editor->control_sel_r); + + return tmp; +} + +static void +gradient_editor_replace_selection (GradientEditor *editor, + GimpGradientSegment *replace_seg) +{ + GimpGradient *gradient; + GimpGradientSegment *lseg, *rseg; + GimpGradientSegment *replace_last; + + gradient = gimp_context_get_gradient (editor->context); + + /* Remember left and right segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + replace_last = gimp_gradient_segment_get_last (replace_seg); + + /* Free old selection */ + + editor->control_sel_r->next = NULL; + + gimp_gradient_segments_free (editor->control_sel_l); + + /* Link in new segments */ + + if (lseg) + lseg->next = replace_seg; + else + gradient->segments = replace_seg; + + replace_seg->prev = lseg; + + if (rseg) + rseg->prev = replace_last; + + replace_last->next = rseg; + + editor->control_sel_l = replace_seg; + editor->control_sel_r = replace_last; + + gradient->last_visited = NULL; /* Force re-search */ +} + +static void +gradient_editor_dialog_cancel_callback (GtkWidget *widget, + GradientEditor *editor) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); +} + +static void +gradient_editor_split_uniform_callback (GtkWidget *widget, + GradientEditor *editor) +{ + GimpGradient *gradient; + GimpGradientSegment *seg, *aseg, *lseg, *rseg, *lsel; + + gradient = gimp_context_get_gradient (editor->context); + + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); + + seg = editor->control_sel_l; + lsel = NULL; + + do + { + aseg = seg; + + gimp_gradient_segment_split_uniform (gradient, seg, + editor->split_parts, &lseg, &rseg); + + if (seg == editor->control_sel_l) + lsel = lseg; + + seg = rseg->next; + } + while (aseg != editor->control_sel_r); + + editor->control_sel_l = lsel; + editor->control_sel_r = rseg; + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} + +static void +gradient_editor_replicate_callback (GtkWidget *widget, + GradientEditor *editor) +{ + GimpGradient *gradient; + gdouble sel_left, sel_right, sel_len; + gdouble new_left; + gdouble factor; + GimpGradientSegment *prev, *seg, *tmp; + GimpGradientSegment *oseg, *oaseg; + GimpGradientSegment *lseg, *rseg; + gint i; + + gradient = gimp_context_get_gradient (editor->context); + + gtk_widget_destroy (gtk_widget_get_toplevel (widget)); + gtk_widget_set_sensitive (editor->shell, TRUE); + + /* Remember original parameters */ + sel_left = editor->control_sel_l->left; + sel_right = editor->control_sel_r->right; + sel_len = sel_right - sel_left; + + factor = 1.0 / editor->replicate_times; + + /* Build replicated segments */ + + prev = NULL; + seg = NULL; + tmp = NULL; + + for (i = 0; i < editor->replicate_times; i++) + { + /* Build one cycle */ + + new_left = sel_left + i * factor * sel_len; + + oseg = editor->control_sel_l; + + do + { + seg = gimp_gradient_segment_new (); + + if (prev == NULL) + { + seg->left = sel_left; + tmp = seg; /* Remember first segment */ + } + else + seg->left = new_left + factor * (oseg->left - sel_left); + + seg->middle = new_left + factor * (oseg->middle - sel_left); + seg->right = new_left + factor * (oseg->right - sel_left); + + seg->left_color = oseg->right_color; + + seg->right_color = oseg->right_color; + + seg->type = oseg->type; + seg->color = oseg->color; + + seg->prev = prev; + seg->next = NULL; + + if (prev) + prev->next = seg; + + prev = seg; + + oaseg = oseg; + oseg = oseg->next; + } + while (oaseg != editor->control_sel_r); + } + + seg->right = sel_right; /* Squish accumulative error */ + + /* Free old segments */ + + lseg = editor->control_sel_l->prev; + rseg = editor->control_sel_r->next; + + oseg = editor->control_sel_l; + + do + { + oaseg = oseg->next; + gimp_gradient_segment_free (oseg); + oseg = oaseg; + } + while (oaseg != rseg); + + /* Link in new segments */ + + if (lseg) + lseg->next = tmp; + else + gradient->segments = tmp; + + tmp->prev = lseg; + + seg->next = rseg; + + if (rseg) + rseg->prev = seg; + + /* Reset selection */ + + editor->control_sel_l = tmp; + editor->control_sel_r = seg; + + /* Done */ + + gimp_data_dirty (GIMP_DATA (gradient)); + + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); +} diff --git a/app/gui/gradient-editor-commands.h b/app/gui/gradient-editor-commands.h new file mode 100644 index 0000000000..8bd0900e28 --- /dev/null +++ b/app/gui/gradient-editor-commands.h @@ -0,0 +1,82 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GRADIENT_EDITOR_COMMANDS_H__ +#define __GRADIENT_EDITOR_COMMANDS_H__ + + +void gradient_editor_left_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_load_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_save_left_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_right_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_load_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_save_right_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_blending_func_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_coloring_type_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_flip_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_replicate_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_split_midpoint_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_split_uniformly_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_delete_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_recenter_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_redistribute_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_blend_color_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); +void gradient_editor_blend_opacity_cmd_callback (GtkWidget *widget, + gpointer data, + guint action); + +void gradient_editor_show_context_menu (GradientEditor *editor); + + +#endif /* __GRADIENT_EDITOR_COMMANDS_H__ */ diff --git a/app/gui/gradient-editor.c b/app/gui/gradient-editor.c index 79d022178b..ceca3d9882 100644 --- a/app/gui/gradient-editor.c +++ b/app/gui/gradient-editor.c @@ -72,10 +72,9 @@ #include "widgets/gimpdnd.h" -#include "color-notebook.h" #include "gradient-editor.h" +#include "gradient-editor-commands.h" -#include "errors.h" #include "gimprc.h" #include "libgimp/gimpintl.h" @@ -90,11 +89,6 @@ #define GRAD_PREVIEW_HEIGHT 64 #define GRAD_CONTROL_HEIGHT 10 -#define GRAD_COLOR_BOX_WIDTH 24 -#define GRAD_COLOR_BOX_HEIGHT 16 - -#define GRAD_NUM_COLORS 10 - #define GRAD_MOVE_TIME 150 /* ms between mouse click and detection of movement in gradient control */ @@ -114,179 +108,52 @@ GDK_BUTTON1_MOTION_MASK) -enum -{ - GRAD_UPDATE_GRADIENT = 1 << 0, - GRAD_UPDATE_PREVIEW = 1 << 1, - GRAD_UPDATE_CONTROL = 1 << 2, - GRAD_RESET_CONTROL = 1 << 3 -}; +/* local function prototypes */ -/* Gradient editor type */ +static void gradient_editor_gradient_changed (GimpContext *context, + GimpGradient *gradient, + GradientEditor *editor); +static void gradient_editor_close_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_name_activate (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_name_focus_out (GtkWidget *widget, + GdkEvent *event, + GradientEditor *editor); +static void gradient_editor_drop_gradient (GtkWidget *widget, + GimpViewable *viewable, + gpointer data); +static void gradient_editor_scrollbar_update (GtkAdjustment *adjustment, + GradientEditor *editor); +static void gradient_editor_zoom_all_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_zoom_out_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_zoom_in_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_instant_update_update (GtkWidget *widget, + GradientEditor *editor); -typedef enum -{ - GRAD_DRAG_NONE = 0, - GRAD_DRAG_LEFT, - GRAD_DRAG_MIDDLE, - GRAD_DRAG_ALL -} control_drag_mode_t; +static void gradient_editor_set_hint (GradientEditor *editor, + const gchar *str); -struct _GradientEditor -{ - GtkWidget *shell; - - GtkWidget *name; - - GtkWidget *hint_label; - GtkWidget *scrollbar; - GtkWidget *preview; - GtkWidget *control; - - GimpContext *context; - - /* Zoom and scrollbar */ - guint zoom_factor; - GtkObject *scroll_data; - - /* Instant update */ - gboolean instant_update; - - /* Gradient preview */ - guchar *preview_rows[2]; /* For caching redraw info */ - gint preview_last_x; - gboolean preview_button_down; - - /* Gradient control */ - GdkPixmap *control_pixmap; - GimpGradientSegment *control_drag_segment; /* Segment which is being dragged */ - GimpGradientSegment *control_sel_l; /* Left segment of selection */ - GimpGradientSegment *control_sel_r; /* Right segment of selection */ - control_drag_mode_t control_drag_mode; /* What is being dragged? */ - guint32 control_click_time; /* Time when mouse was pressed */ - gboolean control_compress; /* Compressing/expanding handles */ - gint control_last_x; /* Last mouse position when dragging */ - gdouble control_last_gx; /* Last position (wrt gradient) when dragging */ - gdouble control_orig_pos; /* Original click position when dragging */ - - GtkWidget *control_main_popup; /* Popup menu */ - GtkWidget *control_blending_label; /* Blending function label */ - GtkWidget *control_coloring_label; /* Coloring type label */ - GtkWidget *control_split_m_label; /* Split at midpoint label */ - GtkWidget *control_split_u_label; /* Split uniformly label */ - GtkWidget *control_delete_menu_item; /* Delete menu item */ - GtkWidget *control_delete_label; /* Delete label */ - GtkWidget *control_recenter_label; /* Re-center label */ - GtkWidget *control_redistribute_label; /* Re-distribute label */ - GtkWidget *control_flip_label; /* Flip label */ - GtkWidget *control_replicate_label; /* Replicate label */ - GtkWidget *control_blend_colors_menu_item; /* Blend colors menu item */ - GtkWidget *control_blend_opacity_menu_item; /* Blend opacity menu item */ - GtkWidget *control_left_load_popup; /* Left endpoint load menu */ - GtkWidget *control_left_save_popup; /* Left endpoint save menu */ - GtkWidget *control_right_load_popup; /* Right endpoint load menu */ - GtkWidget *control_right_save_popup; /* Right endpoint save menu */ - GtkWidget *control_blending_popup; /* Blending function menu */ - GtkWidget *control_coloring_popup; /* Coloring type menu */ - GtkWidget *control_sel_ops_popup; /* Selection ops menu */ - - GtkAccelGroup *accel_group; - - /* Blending and coloring menus */ - GtkWidget *control_blending_items[5 + 1]; /* Add 1 for the "Varies" item */ - GtkWidget *control_coloring_items[3 + 1]; - - /* Split uniformly dialog */ - gint split_parts; - - /* Replicate dialog */ - gint replicate_times; - - /* Saved colors */ - GimpRGB saved_colors[GRAD_NUM_COLORS]; - - GtkWidget *left_load_color_boxes[GRAD_NUM_COLORS + 3]; - GtkWidget *left_load_labels[GRAD_NUM_COLORS + 3]; - - GtkWidget *left_save_color_boxes[GRAD_NUM_COLORS]; - GtkWidget *left_save_labels[GRAD_NUM_COLORS]; - - GtkWidget *right_load_color_boxes[GRAD_NUM_COLORS + 3]; - GtkWidget *right_load_labels[GRAD_NUM_COLORS + 3]; - - GtkWidget *right_save_color_boxes[GRAD_NUM_COLORS]; - GtkWidget *right_save_labels[GRAD_NUM_COLORS]; - - /* Color dialogs */ - GtkWidget *left_color_preview; - GimpGradientSegment *left_saved_segments; - gboolean left_saved_dirty; - - GtkWidget *right_color_preview; - GimpGradientSegment *right_saved_segments; - gboolean right_saved_dirty; -}; - - -/***** Local functions *****/ - -static void gradient_editor_name_activate (GtkWidget *widget, - GradientEditor *gradient_editor); -static void gradient_editor_name_focus_out (GtkWidget *widget, - GdkEvent *event, - GradientEditor *gradient_editor); -static void gradient_editor_drop_gradient (GtkWidget *widget, - GimpViewable *viewable, - gpointer data); -static void gradient_editor_gradient_changed (GimpContext *context, - GimpGradient *gradient, - GradientEditor *gradient_editor); - -/* Gradient editor functions */ - -static void ed_update_editor (GradientEditor *gradient_editor, - gint flags); - -static void ed_set_hint (GradientEditor *gradient_editor, - gchar *str); - -static void ed_initialize_saved_colors (GradientEditor *gradient_editor); - -/* Main dialog button callbacks & functions */ - -static void ed_close_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Zoom, scrollbar & instant update callbacks */ - -static void ed_scrollbar_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor); -static void ed_zoom_all_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_zoom_out_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_zoom_in_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_instant_update_update (GtkWidget *widget, - GradientEditor *gradient_editor); - /* Gradient preview functions */ static gint preview_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor); -static void preview_set_hint (GradientEditor *gradient_editor, + GradientEditor *editor); +static void preview_set_hint (GradientEditor *editor, gint x); -static void preview_set_foreground (GradientEditor *gradient_editor, +static void preview_set_foreground (GradientEditor *editor, gint x); -static void preview_set_background (GradientEditor *gradient_editor, +static void preview_set_background (GradientEditor *editor, gint x); -static void preview_update (GradientEditor *gradient_editor, +static void preview_update (GradientEditor *editor, gboolean recalculate); -static void preview_fill_image (GradientEditor *gradient_editor, +static void preview_fill_image (GradientEditor *editor, gint width, gint height, gdouble left, @@ -296,27 +163,27 @@ static void preview_fill_image (GradientEditor *gradient_edi static gint control_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor); -static void control_do_hint (GradientEditor *gradient_editor, + GradientEditor *editor); +static void control_do_hint (GradientEditor *editor, gint x, gint y); -static void control_button_press (GradientEditor *gradient_editor, +static void control_button_press (GradientEditor *editor, gint x, gint y, guint button, guint state); -static gboolean control_point_in_handle (GradientEditor *gradient_editor, +static gboolean control_point_in_handle (GradientEditor *editor, GimpGradient *gradient, gint x, gint y, GimpGradientSegment *seg, - control_drag_mode_t handle); -static void control_select_single_segment (GradientEditor *gradient_editor, + GradientEditorDragMode handle); +static void control_select_single_segment (GradientEditor *editor, GimpGradientSegment *seg); -static void control_extend_selection (GradientEditor *gradient_editor, +static void control_extend_selection (GradientEditor *editor, GimpGradientSegment *seg, gdouble pos); -static void control_motion (GradientEditor *gradient_editor, +static void control_motion (GradientEditor *editor, GimpGradient *gradient, gint x); @@ -329,28 +196,28 @@ static void control_compress_range (GimpGradientSegment *range_l, gdouble new_l, gdouble new_r); -static double control_move (GradientEditor *gradient_editor, +static double control_move (GradientEditor *editor, GimpGradientSegment *range_l, GimpGradientSegment *range_r, gdouble delta); /* Control update/redraw functions */ -static void control_update (GradientEditor *gradient_editor, +static void control_update (GradientEditor *editor, GimpGradient *gradient, gboolean recalculate); -static void control_draw (GradientEditor *gradient_editor, +static void control_draw (GradientEditor *editor, GimpGradient *gradient, GdkPixmap *pixmap, gint width, gint height, gdouble left, gdouble right); -static void control_draw_normal_handle (GradientEditor *gradient_editor, +static void control_draw_normal_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height); -static void control_draw_middle_handle (GradientEditor *gradient_editor, +static void control_draw_middle_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height); @@ -360,162 +227,25 @@ static void control_draw_handle (GdkPixmap *pixmap, gint xpos, gint height); -static gint control_calc_p_pos (GradientEditor *gradient_editor, +static gint control_calc_p_pos (GradientEditor *editor, gdouble pos); -static gdouble control_calc_g_pos (GradientEditor *gradient_editor, +static gdouble control_calc_g_pos (GradientEditor *editor, gint pos); -/* Control popup functions */ - -static void cpopup_create_main_menu (GradientEditor *gradient_editor); -static void cpopup_do_popup (GradientEditor *gradient_editor); -static GtkWidget * cpopup_create_color_item (GtkWidget **color_box, - GtkWidget **label); -static GtkWidget * cpopup_create_menu_item_with_label (gchar *str, - GtkWidget **label); - -static void cpopup_adjust_menus (GradientEditor *gradient_editor); -static void cpopup_adjust_blending_menu (GradientEditor *gradient_editor); -static void cpopup_adjust_coloring_menu (GradientEditor *gradient_editor); -static void cpopup_check_selection_params (GradientEditor *gradient_editor, - gint *equal_blending, - gint *equal_coloring); - -static void cpopup_render_color_box (GtkPreview *preview, - GimpRGB *color); - -static GtkWidget * cpopup_create_load_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - gchar *label1, - gchar *label2, - GtkSignalFunc callback, - gchar accel_key_0, - guint8 accel_mods_0, - gchar accel_key_1, - guint8 accel_mods_1, - gchar accel_key_2, - guint8 accel_mods_2); -static GtkWidget * cpopup_create_save_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - GtkSignalFunc callback); - -static void cpopup_update_saved_color (GradientEditor *gradient_editor, - gint n, - GimpRGB *color); - -static void cpopup_load_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_save_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_load_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_save_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static GimpGradientSegment * cpopup_save_selection(GradientEditor *gradient_editor); -static void cpopup_replace_selection (GradientEditor *gradient_editor, - GimpGradientSegment *replace_seg); - -/* ----- */ - -static void cpopup_set_left_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_set_right_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_left_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data); -static void cpopup_right_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data); - -/* ----- */ - -static GtkWidget * cpopup_create_blending_menu (GradientEditor *gradient_editor); -static void cpopup_blending_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static GtkWidget * cpopup_create_coloring_menu (GradientEditor *gradient_editor); -static void cpopup_coloring_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* ----- */ - -static void cpopup_split_midpoint_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_midpoint (GimpGradient *gradient, - GimpGradientSegment *lseg, - GimpGradientSegment **newl, - GimpGradientSegment **newr); - -static void cpopup_split_uniform_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_split_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform (GimpGradient *gradient, - GimpGradientSegment *lseg, - gint parts, - GimpGradientSegment **newl, - GimpGradientSegment **newr); - -static void cpopup_delete_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_recenter_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_redistribute_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Control popup -> Selection operations functions */ - -static GtkWidget * cpopup_create_sel_ops_menu (GradientEditor *gradient_editor); - -static void cpopup_flip_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_replicate_scale_update (GtkAdjustment *widget, - GradientEditor *gradient_editor); -static void cpopup_do_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_replicate_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_blend_colors (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_blend_opacity (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Blend function */ - -static void cpopup_blend_endpoints (GradientEditor *gradient_editor, - GimpRGB *left, - GimpRGB *right, - gint blend_colors, - gint blend_opacity); - /* Segment functions */ static void seg_get_closest_handle (GimpGradient *grad, gdouble pos, GimpGradientSegment **seg, - control_drag_mode_t *handle); + GradientEditorDragMode *handle); -/***** Public gradient editor functions *****/ +/* public functions */ GradientEditor * gradient_editor_new (Gimp *gimp) { - GradientEditor *gradient_editor; + GradientEditor *editor; GtkWidget *main_vbox; GtkWidget *hbox; GtkWidget *vbox; @@ -523,33 +253,32 @@ gradient_editor_new (Gimp *gimp) GtkWidget *button; GtkWidget *image; GtkWidget *frame; - gint i; - gradient_editor = g_new (GradientEditor, 1); + editor = g_new (GradientEditor, 1); - gradient_editor->context = gimp_create_context (gimp, NULL, NULL); + editor->context = gimp_create_context (gimp, NULL, NULL); - g_signal_connect (G_OBJECT (gradient_editor->context), "gradient_changed", + g_signal_connect (G_OBJECT (editor->context), "gradient_changed", G_CALLBACK (gradient_editor_gradient_changed), - gradient_editor); + editor); /* Shell and main vbox */ - gradient_editor->shell = + editor->shell = gimp_dialog_new (_("Gradient Editor"), "gradient_editor", gimp_standard_help_func, "dialogs/gradient_editor/gradient_editor.html", GTK_WIN_POS_NONE, FALSE, TRUE, FALSE, - "_delete_event_", ed_close_callback, - gradient_editor, NULL, NULL, FALSE, TRUE, + "_delete_event_", gradient_editor_close_callback, + editor, NULL, NULL, FALSE, TRUE, NULL); main_vbox = gtk_vbox_new (FALSE, 4); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (gradient_editor->shell)->vbox), - main_vbox); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editor->shell)->vbox), + main_vbox); gtk_widget_show (main_vbox); vbox = gtk_vbox_new (FALSE, 1); @@ -557,16 +286,16 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (vbox); /* Gradient's name */ - gradient_editor->name = gtk_entry_new (); - gtk_box_pack_start (GTK_BOX (vbox), gradient_editor->name, FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->name); + editor->name = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (vbox), editor->name, FALSE, FALSE, 0); + gtk_widget_show (editor->name); - g_signal_connect (G_OBJECT (gradient_editor->name), "activate", + g_signal_connect (G_OBJECT (editor->name), "activate", G_CALLBACK (gradient_editor_name_activate), - gradient_editor); - g_signal_connect (G_OBJECT (gradient_editor->name), "focus_out_event", + editor); + g_signal_connect (G_OBJECT (editor->name), "focus_out_event", G_CALLBACK (gradient_editor_name_focus_out), - gradient_editor); + editor); /* Frame for gradient preview and gradient control */ frame = gtk_frame_new (NULL); @@ -579,120 +308,82 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (vbox2); /* Gradient preview */ - gradient_editor->preview_rows[0] = NULL; - gradient_editor->preview_rows[1] = NULL; - gradient_editor->preview_last_x = 0; - gradient_editor->preview_button_down = FALSE; + editor->preview_rows[0] = NULL; + editor->preview_rows[1] = NULL; + editor->preview_last_x = 0; + editor->preview_button_down = FALSE; - gradient_editor->preview = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_set_dither (GTK_PREVIEW (gradient_editor->preview), GDK_RGB_DITHER_MAX); - gtk_preview_size (GTK_PREVIEW (gradient_editor->preview), + editor->preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_set_dither (GTK_PREVIEW (editor->preview), GDK_RGB_DITHER_MAX); + gtk_preview_size (GTK_PREVIEW (editor->preview), GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT); /* Enable auto-resizing of the preview but ensure a minimal size */ - gtk_widget_set_usize (gradient_editor->preview, + gtk_widget_set_usize (editor->preview, GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT); - gtk_preview_set_expand (GTK_PREVIEW (gradient_editor->preview), TRUE); + gtk_preview_set_expand (GTK_PREVIEW (editor->preview), TRUE); - gtk_widget_set_events (gradient_editor->preview, GRAD_PREVIEW_EVENT_MASK); + gtk_widget_set_events (editor->preview, GRAD_PREVIEW_EVENT_MASK); - g_signal_connect (G_OBJECT (gradient_editor->preview), "event", + g_signal_connect (G_OBJECT (editor->preview), "event", G_CALLBACK (preview_events), - gradient_editor); + editor); - gimp_gtk_drag_dest_set_by_type (gradient_editor->preview, + gimp_gtk_drag_dest_set_by_type (editor->preview, GTK_DEST_DEFAULT_ALL, GIMP_TYPE_GRADIENT, GDK_ACTION_COPY); - gimp_dnd_viewable_dest_set (GTK_WIDGET (gradient_editor->preview), + gimp_dnd_viewable_dest_set (GTK_WIDGET (editor->preview), GIMP_TYPE_GRADIENT, gradient_editor_drop_gradient, - gradient_editor); + editor); - gtk_box_pack_start (GTK_BOX (vbox2), gradient_editor->preview, TRUE, TRUE, 0); - gtk_widget_show (gradient_editor->preview); + gtk_box_pack_start (GTK_BOX (vbox2), editor->preview, TRUE, TRUE, 0); + gtk_widget_show (editor->preview); /* Gradient control */ - gradient_editor->control_pixmap = NULL; - gradient_editor->control_drag_segment = NULL; - gradient_editor->control_sel_l = NULL; - gradient_editor->control_sel_r = NULL; - gradient_editor->control_drag_mode = GRAD_DRAG_NONE; - gradient_editor->control_click_time = 0; - gradient_editor->control_compress = FALSE; - gradient_editor->control_last_x = 0; - gradient_editor->control_last_gx = 0.0; - gradient_editor->control_orig_pos = 0.0; - gradient_editor->control_main_popup = NULL; - gradient_editor->control_blending_label = NULL; - gradient_editor->control_coloring_label = NULL; - gradient_editor->control_split_m_label = NULL; - gradient_editor->control_split_u_label = NULL; - gradient_editor->control_delete_menu_item = NULL; - gradient_editor->control_delete_label = NULL; - gradient_editor->control_recenter_label = NULL; - gradient_editor->control_redistribute_label = NULL; - gradient_editor->control_flip_label = NULL; - gradient_editor->control_replicate_label = NULL; - gradient_editor->control_blend_colors_menu_item = NULL; - gradient_editor->control_blend_opacity_menu_item = NULL; - gradient_editor->control_left_load_popup = NULL; - gradient_editor->control_left_save_popup = NULL; - gradient_editor->control_right_load_popup = NULL; - gradient_editor->control_right_save_popup = NULL; - gradient_editor->control_blending_popup = NULL; - gradient_editor->control_coloring_popup = NULL; - gradient_editor->control_sel_ops_popup = NULL; + editor->control_pixmap = NULL; + editor->control_drag_segment = NULL; + editor->control_sel_l = NULL; + editor->control_sel_r = NULL; + editor->control_drag_mode = GRAD_DRAG_NONE; + editor->control_click_time = 0; + editor->control_compress = FALSE; + editor->control_last_x = 0; + editor->control_last_gx = 0.0; + editor->control_orig_pos = 0.0; - gradient_editor->accel_group = NULL; - - for (i = 0; - i < (sizeof (gradient_editor->control_blending_items) / - sizeof (gradient_editor->control_blending_items[0])); - i++) - gradient_editor->control_blending_items[i] = NULL; - - for (i = 0; - i < (sizeof (gradient_editor->control_coloring_items) / - sizeof (gradient_editor->control_coloring_items[0])); - i++) - gradient_editor->control_coloring_items[i] = NULL; - - gradient_editor->control = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (gradient_editor->control), + editor->control = gtk_drawing_area_new (); + gtk_drawing_area_size (GTK_DRAWING_AREA (editor->control), GRAD_PREVIEW_WIDTH, GRAD_CONTROL_HEIGHT); - gtk_widget_set_events (gradient_editor->control, GRAD_CONTROL_EVENT_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), gradient_editor->control, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->control); + gtk_widget_set_events (editor->control, GRAD_CONTROL_EVENT_MASK); + gtk_box_pack_start (GTK_BOX (vbox2), editor->control, FALSE, FALSE, 0); + gtk_widget_show (editor->control); - g_signal_connect (G_OBJECT (gradient_editor->control), "event", + g_signal_connect (G_OBJECT (editor->control), "event", G_CALLBACK (control_events), - gradient_editor); + editor); /* Scrollbar */ - gradient_editor->zoom_factor = 1; + editor->zoom_factor = 1; - gradient_editor->scroll_data = - gtk_adjustment_new (0.0, 0.0, 1.0, - 1.0 * GRAD_SCROLLBAR_STEP_SIZE, - 1.0 * GRAD_SCROLLBAR_PAGE_SIZE, - 1.0); + editor->scroll_data = gtk_adjustment_new (0.0, 0.0, 1.0, + 1.0 * GRAD_SCROLLBAR_STEP_SIZE, + 1.0 * GRAD_SCROLLBAR_PAGE_SIZE, + 1.0); - g_signal_connect (G_OBJECT (gradient_editor->scroll_data), "value_changed", - G_CALLBACK (ed_scrollbar_update), - gradient_editor); - g_signal_connect (G_OBJECT (gradient_editor->scroll_data), "changed", - G_CALLBACK (ed_scrollbar_update), - gradient_editor); + g_signal_connect (G_OBJECT (editor->scroll_data), "value_changed", + G_CALLBACK (gradient_editor_scrollbar_update), + editor); + g_signal_connect (G_OBJECT (editor->scroll_data), "changed", + G_CALLBACK (gradient_editor_scrollbar_update), + editor); - gradient_editor->scrollbar = - gtk_hscrollbar_new (GTK_ADJUSTMENT (gradient_editor->scroll_data)); - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (editor->scroll_data)); + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_CONTINUOUS); - gtk_box_pack_start (GTK_BOX (vbox), gradient_editor->scrollbar, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->scrollbar); + gtk_box_pack_start (GTK_BOX (vbox), editor->scrollbar, FALSE, FALSE, 0); + gtk_widget_show (editor->scrollbar); /* Horizontal box for zoom controls and instant update toggle */ hbox = gtk_hbox_new (FALSE, 4); @@ -710,8 +401,8 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (image); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_out_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_out_callback), + editor); button = gtk_button_new (); GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT); @@ -723,8 +414,8 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (image); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_in_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_in_callback), + editor); /* Zoom all button */ button = gtk_button_new_with_label (_("Zoom all")); @@ -735,11 +426,11 @@ gradient_editor_new (Gimp *gimp) GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_all_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_all_callback), + editor); /* Instant update toggle */ - gradient_editor->instant_update = TRUE; + editor->instant_update = TRUE; button = gtk_check_button_new_with_label (_("Instant update")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); @@ -747,35 +438,79 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (button); g_signal_connect (G_OBJECT (button), "toggled", - G_CALLBACK (ed_instant_update_update), - gradient_editor); + G_CALLBACK (gradient_editor_instant_update_update), + editor); /* Hint bar */ - hbox = GTK_DIALOG (gradient_editor->shell)->action_area; + hbox = GTK_DIALOG (editor->shell)->action_area; gtk_container_set_border_width (GTK_CONTAINER (hbox), 4); gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE); - gradient_editor->hint_label = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (gradient_editor->hint_label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), gradient_editor->hint_label, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->hint_label); + editor->hint_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (editor->hint_label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), editor->hint_label, FALSE, FALSE, 0); + gtk_widget_show (editor->hint_label); /* Initialize other data */ - gradient_editor->left_color_preview = NULL; - gradient_editor->left_saved_segments = NULL; - gradient_editor->left_saved_dirty = FALSE; + editor->left_saved_segments = NULL; + editor->left_saved_dirty = FALSE; - gradient_editor->right_color_preview = NULL; - gradient_editor->right_saved_segments = NULL; - gradient_editor->right_saved_dirty = FALSE; + editor->right_saved_segments = NULL; + editor->right_saved_dirty = FALSE; - ed_initialize_saved_colors (gradient_editor); - cpopup_create_main_menu (gradient_editor); + editor->saved_colors[0].r = 0.0; /* Black */ + editor->saved_colors[0].g = 0.0; + editor->saved_colors[0].b = 0.0; + editor->saved_colors[0].a = 1.0; + + editor->saved_colors[1].r = 0.5; /* 50% Gray */ + editor->saved_colors[1].g = 0.5; + editor->saved_colors[1].b = 0.5; + editor->saved_colors[1].a = 1.0; + + editor->saved_colors[2].r = 1.0; /* White */ + editor->saved_colors[2].g = 1.0; + editor->saved_colors[2].b = 1.0; + editor->saved_colors[2].a = 1.0; + + editor->saved_colors[3].r = 0.0; /* Clear */ + editor->saved_colors[3].g = 0.0; + editor->saved_colors[3].b = 0.0; + editor->saved_colors[3].a = 0.0; + + editor->saved_colors[4].r = 1.0; /* Red */ + editor->saved_colors[4].g = 0.0; + editor->saved_colors[4].b = 0.0; + editor->saved_colors[4].a = 1.0; + + editor->saved_colors[5].r = 1.0; /* Yellow */ + editor->saved_colors[5].g = 1.0; + editor->saved_colors[5].b = 0.0; + editor->saved_colors[5].a = 1.0; + + editor->saved_colors[6].r = 0.0; /* Green */ + editor->saved_colors[6].g = 1.0; + editor->saved_colors[6].b = 0.0; + editor->saved_colors[6].a = 1.0; + + editor->saved_colors[7].r = 0.0; /* Cyan */ + editor->saved_colors[7].g = 1.0; + editor->saved_colors[7].b = 1.0; + editor->saved_colors[7].a = 1.0; + + editor->saved_colors[8].r = 0.0; /* Blue */ + editor->saved_colors[8].g = 0.0; + editor->saved_colors[8].b = 1.0; + editor->saved_colors[8].a = 1.0; + + editor->saved_colors[9].r = 1.0; /* Magenta */ + editor->saved_colors[9].g = 0.0; + editor->saved_colors[9].b = 1.0; + editor->saved_colors[9].a = 1.0; if (gimp_container_num_children (gimp->gradient_factory->container)) { - gimp_context_set_gradient (gradient_editor->context, + gimp_context_set_gradient (editor->context, GIMP_GRADIENT (gimp_container_get_child_by_index (gimp->gradient_factory->container, 0))); } else @@ -788,38 +523,80 @@ gradient_editor_new (Gimp *gimp) GIMP_OBJECT (gradient)); } - gtk_widget_show (gradient_editor->shell); + gtk_widget_show (editor->shell); - return gradient_editor; + return editor; } void -gradient_editor_set_gradient (GradientEditor *gradient_editor, +gradient_editor_set_gradient (GradientEditor *editor, GimpGradient *gradient) { - g_return_if_fail (gradient_editor != NULL); + g_return_if_fail (editor != NULL); g_return_if_fail (GIMP_IS_GRADIENT (gradient)); - gimp_context_set_gradient (gradient_editor->context, gradient); + gimp_context_set_gradient (editor->context, gradient); } void -gradient_editor_free (GradientEditor *gradient_editor) +gradient_editor_free (GradientEditor *editor) { - g_return_if_fail (gradient_editor != NULL); + g_return_if_fail (editor != NULL); +} + +void +gradient_editor_update (GradientEditor *editor, + GradientEditorUpdateMask flags) +{ + GimpGradient *gradient; + + gradient = gimp_context_get_gradient (editor->context); + + if (flags & GRAD_UPDATE_GRADIENT) + { + preview_update (editor, TRUE); + } + + if (flags & GRAD_UPDATE_PREVIEW) + preview_update (editor, TRUE); + + if (flags & GRAD_UPDATE_CONTROL) + control_update (editor, gradient, FALSE); + + if (flags & GRAD_RESET_CONTROL) + control_update (editor, gradient, TRUE); } /* private functions */ +static void +gradient_editor_gradient_changed (GimpContext *context, + GimpGradient *gradient, + GradientEditor *editor) +{ + gtk_entry_set_text (GTK_ENTRY (editor->name), + gimp_object_get_name (GIMP_OBJECT (gradient))); + + gradient_editor_update (editor, GRAD_UPDATE_PREVIEW | GRAD_RESET_CONTROL); +} + +static void +gradient_editor_close_callback (GtkWidget *widget, + GradientEditor *editor) +{ + if (GTK_WIDGET_VISIBLE (editor->shell)) + gtk_widget_hide (editor->shell); +} + static void gradient_editor_name_activate (GtkWidget *widget, - GradientEditor *gradient_editor) + GradientEditor *editor) { GimpGradient *gradient; const gchar *entry_text; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); @@ -829,9 +606,9 @@ gradient_editor_name_activate (GtkWidget *widget, static void gradient_editor_name_focus_out (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { - gradient_editor_name_activate (widget, gradient_editor); + gradient_editor_name_activate (widget, editor); } static void @@ -839,182 +616,50 @@ gradient_editor_drop_gradient (GtkWidget *widget, GimpViewable *viewable, gpointer data) { - GradientEditor *gradient_editor; + GradientEditor *editor; - gradient_editor = (GradientEditor *) data; + editor = (GradientEditor *) data; - gradient_editor_set_gradient (gradient_editor, - GIMP_GRADIENT (viewable)); + gradient_editor_set_gradient (editor, GIMP_GRADIENT (viewable)); } static void -gradient_editor_gradient_changed (GimpContext *context, - GimpGradient *gradient, - GradientEditor *gradient_editor) -{ - gtk_entry_set_text (GTK_ENTRY (gradient_editor->name), - gimp_object_get_name (GIMP_OBJECT (gradient))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_PREVIEW | GRAD_RESET_CONTROL); -} - -/*****/ - -static void -ed_update_editor (GradientEditor *gradient_editor, - gint flags) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (flags & GRAD_UPDATE_GRADIENT) - { - preview_update (gradient_editor, TRUE); - } - - if (flags & GRAD_UPDATE_PREVIEW) - preview_update (gradient_editor, TRUE); - - if (flags & GRAD_UPDATE_CONTROL) - control_update (gradient_editor, gradient, FALSE); - - if (flags & GRAD_RESET_CONTROL) - control_update (gradient_editor, gradient, TRUE); -} - -static void -ed_set_hint (GradientEditor *gradient_editor, - gchar *str) -{ - gtk_label_set_text (GTK_LABEL (gradient_editor->hint_label), str); -} - -static void -ed_initialize_saved_colors (GradientEditor *gradient_editor) -{ - gint i; - - for (i = 0; i < (GRAD_NUM_COLORS + 3); i++) - { - gradient_editor->left_load_color_boxes[i] = NULL; - gradient_editor->left_load_labels[i] = NULL; - - gradient_editor->right_load_color_boxes[i] = NULL; - gradient_editor->right_load_labels[i] = NULL; - } - - for (i = 0; i < GRAD_NUM_COLORS; i++) - { - gradient_editor->left_save_color_boxes[i] = NULL; - gradient_editor->left_save_labels[i] = NULL; - - gradient_editor->right_save_color_boxes[i] = NULL; - gradient_editor->right_save_labels[i] = NULL; - } - - gradient_editor->saved_colors[0].r = 0.0; /* Black */ - gradient_editor->saved_colors[0].g = 0.0; - gradient_editor->saved_colors[0].b = 0.0; - gradient_editor->saved_colors[0].a = 1.0; - - gradient_editor->saved_colors[1].r = 0.5; /* 50% Gray */ - gradient_editor->saved_colors[1].g = 0.5; - gradient_editor->saved_colors[1].b = 0.5; - gradient_editor->saved_colors[1].a = 1.0; - - gradient_editor->saved_colors[2].r = 1.0; /* White */ - gradient_editor->saved_colors[2].g = 1.0; - gradient_editor->saved_colors[2].b = 1.0; - gradient_editor->saved_colors[2].a = 1.0; - - gradient_editor->saved_colors[3].r = 0.0; /* Clear */ - gradient_editor->saved_colors[3].g = 0.0; - gradient_editor->saved_colors[3].b = 0.0; - gradient_editor->saved_colors[3].a = 0.0; - - gradient_editor->saved_colors[4].r = 1.0; /* Red */ - gradient_editor->saved_colors[4].g = 0.0; - gradient_editor->saved_colors[4].b = 0.0; - gradient_editor->saved_colors[4].a = 1.0; - - gradient_editor->saved_colors[5].r = 1.0; /* Yellow */ - gradient_editor->saved_colors[5].g = 1.0; - gradient_editor->saved_colors[5].b = 0.0; - gradient_editor->saved_colors[5].a = 1.0; - - gradient_editor->saved_colors[6].r = 0.0; /* Green */ - gradient_editor->saved_colors[6].g = 1.0; - gradient_editor->saved_colors[6].b = 0.0; - gradient_editor->saved_colors[6].a = 1.0; - - gradient_editor->saved_colors[7].r = 0.0; /* Cyan */ - gradient_editor->saved_colors[7].g = 1.0; - gradient_editor->saved_colors[7].b = 1.0; - gradient_editor->saved_colors[7].a = 1.0; - - gradient_editor->saved_colors[8].r = 0.0; /* Blue */ - gradient_editor->saved_colors[8].g = 0.0; - gradient_editor->saved_colors[8].b = 1.0; - gradient_editor->saved_colors[8].a = 1.0; - - gradient_editor->saved_colors[9].r = 1.0; /* Magenta */ - gradient_editor->saved_colors[9].g = 0.0; - gradient_editor->saved_colors[9].b = 1.0; - gradient_editor->saved_colors[9].a = 1.0; -} - - -/***** Main gradient editor dialog callbacks *****/ - -static void -ed_close_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - if (GTK_WIDGET_VISIBLE (gradient_editor->shell)) - gtk_widget_hide (gradient_editor->shell); -} - - -/***** Zoom, scrollbar & instant update callbacks *****/ - -static void -ed_scrollbar_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) +gradient_editor_scrollbar_update (GtkAdjustment *adjustment, + GradientEditor *editor) { gchar *str; str = g_strdup_printf (_("Zoom factor: %d:1 Displaying [%0.6f, %0.6f]"), - gradient_editor->zoom_factor, adjustment->value, + editor->zoom_factor, adjustment->value, adjustment->value + adjustment->page_size); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); - ed_update_editor (gradient_editor, GRAD_UPDATE_PREVIEW | GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_PREVIEW | GRAD_UPDATE_CONTROL); } static void -ed_zoom_all_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_all_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - gradient_editor->zoom_factor = 1; + editor->zoom_factor = 1; adjustment->value = 0.0; adjustment->page_size = 1.0; adjustment->step_increment = 1.0 * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = 1.0 * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_zoom_out_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_out_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; gdouble old_value; @@ -1022,17 +667,17 @@ ed_zoom_out_callback (GtkWidget *widget, gdouble old_page_size; gdouble page_size; - if (gradient_editor->zoom_factor <= 1) + if (editor->zoom_factor <= 1) return; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); old_value = adjustment->value; old_page_size = adjustment->page_size; - gradient_editor->zoom_factor--; + editor->zoom_factor--; - page_size = 1.0 / gradient_editor->zoom_factor; + page_size = 1.0 / editor->zoom_factor; value = old_value - (page_size - old_page_size) / 2.0; if (value < 0.0) @@ -1045,59 +690,67 @@ ed_zoom_out_callback (GtkWidget *widget, adjustment->step_increment = page_size * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = page_size * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_zoom_in_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_in_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; gdouble old_value; gdouble old_page_size; gdouble page_size; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); old_value = adjustment->value; old_page_size = adjustment->page_size; - gradient_editor->zoom_factor++; + editor->zoom_factor++; - page_size = 1.0 / gradient_editor->zoom_factor; + page_size = 1.0 / editor->zoom_factor; adjustment->value = old_value + (old_page_size - page_size) / 2.0; adjustment->page_size = page_size; adjustment->step_increment = page_size * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = page_size * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_instant_update_update (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_instant_update_update (GtkWidget *widget, + GradientEditor *editor) { if (GTK_TOGGLE_BUTTON (widget)->active) { - gradient_editor->instant_update = TRUE; - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->instant_update = TRUE; + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_CONTINUOUS); } else { - gradient_editor->instant_update = FALSE; - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->instant_update = FALSE; + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_DELAYED); } } +static void +gradient_editor_set_hint (GradientEditor *editor, + const gchar *str) +{ + gtk_label_set_text (GTK_LABEL (editor->hint_label), str); +} + + /***** Gradient preview functions *****/ static gint preview_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { gint x, y; GdkEventButton *bevent; @@ -1107,57 +760,57 @@ preview_events (GtkWidget *widget, switch (event->type) { case GDK_EXPOSE: - preview_update (gradient_editor, FALSE); + preview_update (editor, FALSE); return FALSE; case GDK_LEAVE_NOTIFY: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); break; case GDK_MOTION_NOTIFY: - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); mevent = (GdkEventMotion *) event; - if (x != gradient_editor->preview_last_x) + if (x != editor->preview_last_x) { - gradient_editor->preview_last_x = x; + editor->preview_last_x = x; - if (gradient_editor->preview_button_down) + if (editor->preview_button_down) { if (mevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); } else { - preview_set_hint (gradient_editor, x); + preview_set_hint (editor, x); } } break; case GDK_BUTTON_PRESS: - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); bevent = (GdkEventButton *) event; switch (bevent->button) { case 1: - gradient_editor->preview_last_x = x; - gradient_editor->preview_button_down = TRUE; + editor->preview_last_x = x; + editor->preview_button_down = TRUE; if (bevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); break; case 3: - cpopup_do_popup (gradient_editor); + gradient_editor_show_context_menu (editor); break; default: @@ -1172,13 +825,13 @@ preview_events (GtkWidget *widget, if (sevent->state & GDK_SHIFT_MASK) { if (sevent->direction == GDK_SCROLL_UP) - ed_zoom_in_callback (NULL, gradient_editor); + gradient_editor_zoom_in_callback (NULL, editor); else - ed_zoom_out_callback (NULL, gradient_editor); + gradient_editor_zoom_out_callback (NULL, editor); } else { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value + ((sevent->direction == GDK_SCROLL_UP) ? -adj->page_increment / 2 : @@ -1192,18 +845,18 @@ preview_events (GtkWidget *widget, break; case GDK_BUTTON_RELEASE: - if (gradient_editor->preview_button_down) + if (editor->preview_button_down) { - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); bevent = (GdkEventButton *) event; - gradient_editor->preview_last_x = x; - gradient_editor->preview_button_down = FALSE; + editor->preview_last_x = x; + editor->preview_button_down = FALSE; if (bevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); break; } @@ -1217,7 +870,7 @@ preview_events (GtkWidget *widget, } static void -preview_set_hint (GradientEditor *gradient_editor, +preview_set_hint (GradientEditor *editor, gint x) { gdouble xpos; @@ -1225,11 +878,10 @@ preview_set_hint (GradientEditor *gradient_editor, GimpHSV hsv; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); - gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), - xpos, &rgb); + gimp_gradient_get_color_at (gimp_context_get_gradient (editor->context), + xpos, &rgb); gimp_rgb_to_hsv (&rgb, &hsv); @@ -1246,24 +898,25 @@ preview_set_hint (GradientEditor *gradient_editor, hsv.v, rgb.a); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } static void -preview_set_foreground (GradientEditor *gradient_editor, +preview_set_foreground (GradientEditor *editor, gint x) { GimpRGB color; gdouble xpos; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); - gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), - xpos, &color); + xpos = control_calc_g_pos (editor, x); - gimp_context_set_foreground (gimp_get_user_context (gradient_editor->context->gimp), &color); + gimp_gradient_get_color_at (gimp_context_get_gradient (editor->context), + xpos, &color); + + gimp_context_set_foreground (gimp_get_user_context (editor->context->gimp), + &color); str = g_strdup_printf (_("Foreground color set to RGB (%d, %d, %d) <-> " "(%0.3f, %0.3f, %0.3f)"), @@ -1272,24 +925,25 @@ preview_set_foreground (GradientEditor *gradient_editor, (gint) (color.b * 255.0), color.r, color.g, color.b); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } static void -preview_set_background (GradientEditor *gradient_editor, +preview_set_background (GradientEditor *editor, gint x) { GimpRGB color; gdouble xpos; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), + (gimp_context_get_gradient (editor->context), xpos, &color); - gimp_context_set_background (gimp_get_user_context (gradient_editor->context->gimp), &color); + gimp_context_set_background (gimp_get_user_context (editor->context->gimp), + &color); str = g_strdup_printf (_("Background color to RGB (%d, %d, %d) <-> " "(%0.3f, %0.3f, %0.3f)"), @@ -1298,14 +952,14 @@ preview_set_background (GradientEditor *gradient_editor, (gint) (color.b * 255.0), color.r, color.g, color.b); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } /*****/ static void -preview_update (GradientEditor *gradient_editor, +preview_update (GradientEditor *editor, gboolean recalculate) { glong rowsiz; @@ -1316,30 +970,30 @@ preview_update (GradientEditor *gradient_editor, static guint16 last_width = 0; static guint16 last_height = 0; - if (! GTK_WIDGET_DRAWABLE (gradient_editor->preview)) + if (! GTK_WIDGET_DRAWABLE (editor->preview)) return; /* See whether we have to re-create the preview widget * (note that the preview automatically follows the size of it's container) */ - width = gradient_editor->preview->allocation.width; - height = gradient_editor->preview->allocation.height; + width = editor->preview->allocation.width; + height = editor->preview->allocation.height; - if (! gradient_editor->preview_rows[0] || - ! gradient_editor->preview_rows[1] || + if (! editor->preview_rows[0] || + ! editor->preview_rows[1] || (width != last_width) || (height != last_height)) { - if (gradient_editor->preview_rows[0]) - g_free (gradient_editor->preview_rows[0]); + if (editor->preview_rows[0]) + g_free (editor->preview_rows[0]); - if (gradient_editor->preview_rows[1]) - g_free (gradient_editor->preview_rows[1]); + if (editor->preview_rows[1]) + g_free (editor->preview_rows[1]); rowsiz = width * 3 * sizeof (guchar); - gradient_editor->preview_rows[0] = g_malloc (rowsiz); - gradient_editor->preview_rows[1] = g_malloc (rowsiz); + editor->preview_rows[0] = g_malloc (rowsiz); + editor->preview_rows[1] = g_malloc (rowsiz); recalculate = TRUE; /* Force recalculation */ } @@ -1350,19 +1004,19 @@ preview_update (GradientEditor *gradient_editor, /* Have to redraw? */ if (recalculate) { - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - preview_fill_image (gradient_editor, + preview_fill_image (editor, width, height, adjustment->value, adjustment->value + adjustment->page_size); - gtk_widget_draw (gradient_editor->preview, NULL); + gtk_widget_draw (editor->preview, NULL); } } static void -preview_fill_image (GradientEditor *gradient_editor, +preview_fill_image (GradientEditor *editor, gint width, gint height, gdouble left, @@ -1375,12 +1029,12 @@ preview_fill_image (GradientEditor *gradient_editor, GimpRGB color; gdouble c0, c1; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); dx = (right - left) / (width - 1); cur_x = left; - p0 = gradient_editor->preview_rows[0]; - p1 = gradient_editor->preview_rows[1]; + p0 = editor->preview_rows[0]; + p1 = editor->preview_rows[1]; /* Create lines to fill the image */ for (x = 0; x < width; x++) @@ -1413,11 +1067,11 @@ preview_fill_image (GradientEditor *gradient_editor, for (y = 0; y < height; y++) { if ((y / GIMP_CHECK_SIZE) & 1) - gtk_preview_draw_row (GTK_PREVIEW (gradient_editor->preview), - gradient_editor->preview_rows[1], 0, y, width); + gtk_preview_draw_row (GTK_PREVIEW (editor->preview), + editor->preview_rows[1], 0, y, width); else - gtk_preview_draw_row (GTK_PREVIEW (gradient_editor->preview), - gradient_editor->preview_rows[0], 0, y, width); + gtk_preview_draw_row (GTK_PREVIEW (editor->preview), + editor->preview_rows[0], 0, y, width); } } @@ -1434,7 +1088,7 @@ preview_fill_image (GradientEditor *gradient_editor, static gint control_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { GimpGradient *gradient; GdkEventButton *bevent; @@ -1442,97 +1096,97 @@ control_events (GtkWidget *widget, gint x, y; guint32 time; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); switch (event->type) { case GDK_EXPOSE: - control_update (gradient_editor, gradient, FALSE); + control_update (editor, gradient, FALSE); break; case GDK_LEAVE_NOTIFY: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); break; case GDK_BUTTON_PRESS: - if (gradient_editor->control_drag_mode == GRAD_DRAG_NONE) + if (editor->control_drag_mode == GRAD_DRAG_NONE) { - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); bevent = (GdkEventButton *) event; - gradient_editor->control_last_x = x; - gradient_editor->control_click_time = bevent->time; + editor->control_last_x = x; + editor->control_click_time = bevent->time; - control_button_press (gradient_editor, + control_button_press (editor, x, y, bevent->button, bevent->state); - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) gtk_grab_add (widget); } break; case GDK_BUTTON_RELEASE: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) { gtk_grab_remove (widget); - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); time = ((GdkEventButton *) event)->time; - if ((time - gradient_editor->control_click_time) >= GRAD_MOVE_TIME) + if ((time - editor->control_click_time) >= GRAD_MOVE_TIME) { - if (! gradient_editor->instant_update) + if (! editor->instant_update) gimp_data_dirty (GIMP_DATA (gradient)); - ed_update_editor (gradient_editor, - GRAD_UPDATE_GRADIENT); /* Possible move */ + /* Possible move */ + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); } - else if ((gradient_editor->control_drag_mode == GRAD_DRAG_MIDDLE) || - (gradient_editor->control_drag_mode == GRAD_DRAG_ALL)) + else if ((editor->control_drag_mode == GRAD_DRAG_MIDDLE) || + (editor->control_drag_mode == GRAD_DRAG_ALL)) { - seg = gradient_editor->control_drag_segment; + seg = editor->control_drag_segment; - if ((gradient_editor->control_drag_mode == GRAD_DRAG_ALL) && - gradient_editor->control_compress) - control_extend_selection (gradient_editor, seg, - control_calc_g_pos (gradient_editor, + if ((editor->control_drag_mode == GRAD_DRAG_ALL) && + editor->control_compress) + control_extend_selection (editor, seg, + control_calc_g_pos (editor, x)); else - control_select_single_segment (gradient_editor, seg); + control_select_single_segment (editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } - gradient_editor->control_drag_mode = GRAD_DRAG_NONE; - gradient_editor->control_compress = FALSE; + editor->control_drag_mode = GRAD_DRAG_NONE; + editor->control_compress = FALSE; - control_do_hint (gradient_editor, x, y); + control_do_hint (editor, x, y); } break; case GDK_MOTION_NOTIFY: - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); - if (x != gradient_editor->control_last_x) + if (x != editor->control_last_x) { - gradient_editor->control_last_x = x; + editor->control_last_x = x; - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) { time = ((GdkEventButton *) event)->time; - if ((time - gradient_editor->control_click_time) >= GRAD_MOVE_TIME) - control_motion (gradient_editor, gradient, x); + if ((time - editor->control_click_time) >= GRAD_MOVE_TIME) + control_motion (editor, gradient, x); } else { - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); - control_do_hint (gradient_editor, x, y); + control_do_hint (editor, x, y); } } break; @@ -1545,26 +1199,26 @@ control_events (GtkWidget *widget, } static void -control_do_hint (GradientEditor *gradient_editor, +control_do_hint (GradientEditor *editor, gint x, gint y) { - GimpGradient *gradient; - GimpGradientSegment *seg; - control_drag_mode_t handle; - gboolean in_handle; - double pos; + GimpGradient *gradient; + GimpGradientSegment *seg; + GradientEditorDragMode handle; + gboolean in_handle; + double pos; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); if ((pos < 0.0) || (pos > 1.0)) return; seg_get_closest_handle (gradient, pos, &seg, &handle); - in_handle = control_point_in_handle (gradient_editor, gradient, + in_handle = control_point_in_handle (editor, gradient, x, y, seg, handle); if (in_handle) @@ -1575,53 +1229,61 @@ control_do_hint (GradientEditor *gradient_editor, if (seg != NULL) { if (seg->prev != NULL) - ed_set_hint (gradient_editor, - _("Drag: move Shift+drag: move & compress")); + gradient_editor_set_hint (editor, + _("Drag: move " + "+Drag: move & compress")); else - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection")); } else { - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection")); } break; case GRAD_DRAG_MIDDLE: - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection " - "Drag: move")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection " + "Drag: move")); break; default: - g_warning ("in_handle is true yet we got handle type %d", - (int) handle); + g_warning ("%s: in_handle is true, but received handle type %d.", + G_STRLOC, in_handle); break; } } else - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection " - "Drag: move Shift+drag: move & compress")); + { + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection " + "Drag: move " + "+Drag: move & compress")); + } } static void -control_button_press (GradientEditor *gradient_editor, +control_button_press (GradientEditor *editor, gint x, gint y, guint button, guint state) { - GimpGradient *gradient; - GimpGradientSegment *seg; - control_drag_mode_t handle; - double xpos; - gboolean in_handle; + GimpGradient *gradient; + GimpGradientSegment *seg; + GradientEditorDragMode handle; + double xpos; + gboolean in_handle; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); switch (button) { @@ -1629,13 +1291,13 @@ control_button_press (GradientEditor *gradient_editor, break; case 3: - cpopup_do_popup (gradient_editor); + gradient_editor_show_context_menu (editor); return; /* wheelmouse support */ case 4: { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value - adj->page_increment / 2; new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size); @@ -1645,7 +1307,7 @@ control_button_press (GradientEditor *gradient_editor, case 5: { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value + adj->page_increment / 2; new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size); @@ -1659,11 +1321,11 @@ control_button_press (GradientEditor *gradient_editor, /* Find the closest handle */ - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); seg_get_closest_handle (gradient, xpos, &seg, &handle); - in_handle = control_point_in_handle (gradient_editor, gradient, + in_handle = control_point_in_handle (editor, gradient, x, y, seg, handle); /* Now see what we have */ @@ -1680,25 +1342,25 @@ control_button_press (GradientEditor *gradient_editor, { if (seg->prev != NULL) { - gradient_editor->control_drag_mode = GRAD_DRAG_LEFT; - gradient_editor->control_drag_segment = seg; - gradient_editor->control_compress = TRUE; + editor->control_drag_mode = GRAD_DRAG_LEFT; + editor->control_drag_segment = seg; + editor->control_compress = TRUE; } else { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } } else if (seg->prev != NULL) { - gradient_editor->control_drag_mode = GRAD_DRAG_LEFT; - gradient_editor->control_drag_segment = seg; + editor->control_drag_mode = GRAD_DRAG_LEFT; + editor->control_drag_segment = seg; } else { - control_select_single_segment (gradient_editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_select_single_segment (editor, seg); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } return; @@ -1710,13 +1372,13 @@ control_button_press (GradientEditor *gradient_editor, if (state & GDK_SHIFT_MASK) { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } else { - control_select_single_segment (gradient_editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_select_single_segment (editor, seg); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } return; @@ -1727,20 +1389,20 @@ control_button_press (GradientEditor *gradient_editor, case GRAD_DRAG_MIDDLE: if (state & GDK_SHIFT_MASK) { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } else { - gradient_editor->control_drag_mode = GRAD_DRAG_MIDDLE; - gradient_editor->control_drag_segment = seg; + editor->control_drag_mode = GRAD_DRAG_MIDDLE; + editor->control_drag_segment = seg; } return; default: - g_warning ("in_handle is true yet we got handle type %d", - (int) handle); + g_warning ("%s: in_handle is true, but received handle type %d.", + G_STRLOC, in_handle); return; } } @@ -1748,25 +1410,25 @@ control_button_press (GradientEditor *gradient_editor, { seg = gimp_gradient_get_segment_at (gradient, xpos); - gradient_editor->control_drag_mode = GRAD_DRAG_ALL; - gradient_editor->control_drag_segment = seg; - gradient_editor->control_last_gx = xpos; - gradient_editor->control_orig_pos = xpos; + editor->control_drag_mode = GRAD_DRAG_ALL; + editor->control_drag_segment = seg; + editor->control_last_gx = xpos; + editor->control_orig_pos = xpos; if (state & GDK_SHIFT_MASK) - gradient_editor->control_compress = TRUE; + editor->control_compress = TRUE; return; } } static gboolean -control_point_in_handle (GradientEditor *gradient_editor, - GimpGradient *gradient, - gint x, - gint y, - GimpGradientSegment *seg, - control_drag_mode_t handle) +control_point_in_handle (GradientEditor *editor, + GimpGradient *gradient, + gint x, + gint y, + GimpGradientSegment *seg, + GradientEditorDragMode handle) { gint handle_pos; @@ -1775,23 +1437,23 @@ control_point_in_handle (GradientEditor *gradient_editor, case GRAD_DRAG_LEFT: if (seg) { - handle_pos = control_calc_p_pos (gradient_editor, seg->left); + handle_pos = control_calc_p_pos (editor, seg->left); } else { seg = gimp_gradient_segment_get_last (gradient->segments); - handle_pos = control_calc_p_pos (gradient_editor, seg->right); + handle_pos = control_calc_p_pos (editor, seg->right); } break; case GRAD_DRAG_MIDDLE: - handle_pos = control_calc_p_pos (gradient_editor, seg->middle); + handle_pos = control_calc_p_pos (editor, seg->middle); break; default: - g_warning ("can not handle drag mode %d", (gint) handle); + g_warning ("%s: Cannot handle drag mode %d.", G_STRLOC, handle); return FALSE; } @@ -1806,29 +1468,29 @@ control_point_in_handle (GradientEditor *gradient_editor, /*****/ static void -control_select_single_segment (GradientEditor *gradient_editor, +control_select_single_segment (GradientEditor *editor, GimpGradientSegment *seg) { - gradient_editor->control_sel_l = seg; - gradient_editor->control_sel_r = seg; + editor->control_sel_l = seg; + editor->control_sel_r = seg; } static void -control_extend_selection (GradientEditor *gradient_editor, +control_extend_selection (GradientEditor *editor, GimpGradientSegment *seg, gdouble pos) { - if (fabs (pos - gradient_editor->control_sel_l->left) < - fabs (pos - gradient_editor->control_sel_r->right)) - gradient_editor->control_sel_l = seg; + if (fabs (pos - editor->control_sel_l->left) < + fabs (pos - editor->control_sel_r->right)) + editor->control_sel_l = seg; else - gradient_editor->control_sel_r = seg; + editor->control_sel_r = seg; } /*****/ static void -control_motion (GradientEditor *gradient_editor, +control_motion (GradientEditor *editor, GimpGradient *gradient, gint x) { @@ -1837,76 +1499,75 @@ control_motion (GradientEditor *gradient_editor, gdouble delta; gchar *str = NULL; - seg = gradient_editor->control_drag_segment; + seg = editor->control_drag_segment; - switch (gradient_editor->control_drag_mode) + switch (editor->control_drag_mode) { case GRAD_DRAG_LEFT: - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); - if (! gradient_editor->control_compress) + if (! editor->control_compress) seg->prev->right = seg->left = CLAMP (pos, seg->prev->middle + EPSILON, seg->middle - EPSILON); else - control_compress_left (gradient_editor->control_sel_l, - gradient_editor->control_sel_r, + control_compress_left (editor->control_sel_l, + editor->control_sel_r, seg, pos); str = g_strdup_printf (_("Handle position: %0.6f"), seg->left); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); break; case GRAD_DRAG_MIDDLE: - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); seg->middle = CLAMP (pos, seg->left + EPSILON, seg->right - EPSILON); str = g_strdup_printf (_("Handle position: %0.6f"), seg->middle); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); break; case GRAD_DRAG_ALL: - pos = control_calc_g_pos (gradient_editor, x); - delta = pos - gradient_editor->control_last_gx; + pos = control_calc_g_pos (editor, x); + delta = pos - editor->control_last_gx; - if ((seg->left >= gradient_editor->control_sel_l->left) && - (seg->right <= gradient_editor->control_sel_r->right)) - delta = control_move (gradient_editor, - gradient_editor->control_sel_l, - gradient_editor->control_sel_r, delta); + if ((seg->left >= editor->control_sel_l->left) && + (seg->right <= editor->control_sel_r->right)) + delta = control_move (editor, + editor->control_sel_l, + editor->control_sel_r, delta); else - delta = control_move (gradient_editor, seg, seg, delta); + delta = control_move (editor, seg, seg, delta); - gradient_editor->control_last_gx += delta; + editor->control_last_gx += delta; str = g_strdup_printf (_("Distance: %0.6f"), - gradient_editor->control_last_gx - - gradient_editor->control_orig_pos); - ed_set_hint (gradient_editor, str); + editor->control_last_gx - + editor->control_orig_pos); + gradient_editor_set_hint (editor, str); break; default: - gimp_fatal_error ("Attempt to move bogus handle %d", - (gint) gradient_editor->control_drag_mode); + g_warning ("%s: Attempting to move bogus handle %d.", + G_STRLOC, editor->control_drag_mode); break; } if (str) g_free (str); - if (gradient_editor->instant_update) + if (editor->instant_update) { gimp_data_dirty (GIMP_DATA (gradient)); - ed_update_editor (gradient_editor, - GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); } else { - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } } @@ -2028,10 +1689,10 @@ control_compress_range (GimpGradientSegment *range_l, /*****/ static gdouble -control_move (GradientEditor *gradient_editor, +control_move (GradientEditor *editor, GimpGradientSegment *range_l, GimpGradientSegment *range_r, - gdouble delta) + gdouble delta) { gdouble lbound, rbound; gint is_first, is_last; @@ -2044,7 +1705,7 @@ control_move (GradientEditor *gradient_editor, /* Calculate drag bounds */ - if (! gradient_editor->control_compress) + if (! editor->control_compress) { if (!is_first) lbound = range_l->prev->middle + EPSILON; @@ -2119,7 +1780,7 @@ control_move (GradientEditor *gradient_editor, if (!is_first) { - if (! gradient_editor->control_compress) + if (! editor->control_compress) range_l->prev->right = range_l->left; else control_compress_range (range_l->prev, range_l->prev, @@ -2128,7 +1789,7 @@ control_move (GradientEditor *gradient_editor, if (!is_last) { - if (! gradient_editor->control_compress) + if (! editor->control_compress) range_r->next->left = range_r->right; else control_compress_range (range_r->next, range_r->next, @@ -2141,7 +1802,7 @@ control_move (GradientEditor *gradient_editor, /*****/ static void -control_update (GradientEditor *gradient_editor, +control_update (GradientEditor *editor, GimpGradient *gradient, gboolean recalculate) { @@ -2149,27 +1810,27 @@ control_update (GradientEditor *gradient_editor, gint cwidth, cheight; gint pwidth, pheight; - if (! GTK_WIDGET_DRAWABLE (gradient_editor->control)) + if (! GTK_WIDGET_DRAWABLE (editor->control)) return; /* See whether we have to re-create the control pixmap * depending on the preview's width */ - cwidth = gradient_editor->preview->allocation.width; + cwidth = editor->preview->allocation.width; cheight = GRAD_CONTROL_HEIGHT; - if (gradient_editor->control_pixmap) - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + if (editor->control_pixmap) + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); - if (! gradient_editor->control_pixmap || + if (! editor->control_pixmap || (cwidth != pwidth) || (cheight != pheight)) { - if (gradient_editor->control_pixmap) - gdk_drawable_unref (gradient_editor->control_pixmap); + if (editor->control_pixmap) + gdk_drawable_unref (editor->control_pixmap); - gradient_editor->control_pixmap = - gdk_pixmap_new (gradient_editor->control->window, cwidth, cheight, -1); + editor->control_pixmap = + gdk_pixmap_new (editor->control->window, cwidth, cheight, -1); recalculate = TRUE; } @@ -2180,27 +1841,27 @@ control_update (GradientEditor *gradient_editor, /* Have to reset the selection? */ if (recalculate) - control_select_single_segment (gradient_editor, gradient->segments); + control_select_single_segment (editor, gradient->segments); /* Redraw pixmap */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - control_draw (gradient_editor, + control_draw (editor, gradient, - gradient_editor->control_pixmap, + editor->control_pixmap, cwidth, cheight, adjustment->value, adjustment->value + adjustment->page_size); - gdk_draw_drawable (gradient_editor->control->window, - gradient_editor->control->style->black_gc, - gradient_editor->control_pixmap, + gdk_draw_drawable (editor->control->window, + editor->control->style->black_gc, + editor->control_pixmap, 0, 0, 0, 0, cwidth, cheight); } static void -control_draw (GradientEditor *gradient_editor, +control_draw (GradientEditor *editor, GimpGradient *gradient, GdkPixmap *pixmap, gint width, @@ -2208,25 +1869,25 @@ control_draw (GradientEditor *gradient_editor, gdouble left, gdouble right) { - gint sel_l, sel_r; - gdouble g_pos; - GimpGradientSegment *seg; - control_drag_mode_t handle; + gint sel_l, sel_r; + gdouble g_pos; + GimpGradientSegment *seg; + GradientEditorDragMode handle; /* Clear the pixmap */ - gdk_draw_rectangle (pixmap, gradient_editor->control->style->bg_gc[GTK_STATE_NORMAL], + gdk_draw_rectangle (pixmap, editor->control->style->bg_gc[GTK_STATE_NORMAL], TRUE, 0, 0, width, height); /* Draw selection */ - sel_l = control_calc_p_pos (gradient_editor, - gradient_editor->control_sel_l->left); - sel_r = control_calc_p_pos (gradient_editor, - gradient_editor->control_sel_r->right); + sel_l = control_calc_p_pos (editor, + editor->control_sel_l->left); + sel_r = control_calc_p_pos (editor, + editor->control_sel_r->right); gdk_draw_rectangle (pixmap, - gradient_editor->control->style->dark_gc[GTK_STATE_NORMAL], + editor->control->style->dark_gc[GTK_STATE_NORMAL], TRUE, sel_l, 0, sel_r - sel_l + 1, height); /* Draw handles */ @@ -2235,13 +1896,13 @@ control_draw (GradientEditor *gradient_editor, while (seg) { - control_draw_normal_handle (gradient_editor, pixmap, seg->left, height); - control_draw_middle_handle (gradient_editor, pixmap, seg->middle, height); + control_draw_normal_handle (editor, pixmap, seg->left, height); + control_draw_middle_handle (editor, pixmap, seg->middle, height); /* Draw right handle only if this is the last segment */ if (seg->next == NULL) - control_draw_normal_handle (gradient_editor, pixmap, seg->right, height); + control_draw_normal_handle (editor, pixmap, seg->right, height); /* Next! */ @@ -2250,7 +1911,7 @@ control_draw (GradientEditor *gradient_editor, /* Draw the handle which is closest to the mouse position */ - g_pos = control_calc_g_pos (gradient_editor, gradient_editor->control_last_x); + g_pos = control_calc_g_pos (editor, editor->control_last_x); seg_get_closest_handle (gradient, CLAMP (g_pos, 0.0, 1.0), &seg, &handle); @@ -2259,21 +1920,21 @@ control_draw (GradientEditor *gradient_editor, case GRAD_DRAG_LEFT: if (seg) { - control_draw_normal_handle (gradient_editor, pixmap, + control_draw_normal_handle (editor, pixmap, seg->left, height); } else { seg = gimp_gradient_segment_get_last (gradient->segments); - control_draw_normal_handle (gradient_editor, pixmap, + control_draw_normal_handle (editor, pixmap, seg->right, height); } break; case GRAD_DRAG_MIDDLE: - control_draw_middle_handle (gradient_editor, pixmap, seg->middle, height); + control_draw_middle_handle (editor, pixmap, seg->middle, height); break; default: @@ -2282,27 +1943,27 @@ control_draw (GradientEditor *gradient_editor, } static void -control_draw_normal_handle (GradientEditor *gradient_editor, +control_draw_normal_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height) { control_draw_handle (pixmap, - gradient_editor->control->style->black_gc, - gradient_editor->control->style->black_gc, - control_calc_p_pos (gradient_editor, pos), height); + editor->control->style->black_gc, + editor->control->style->black_gc, + control_calc_p_pos (editor, pos), height); } static void -control_draw_middle_handle (GradientEditor *gradient_editor, +control_draw_middle_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height) { control_draw_handle (pixmap, - gradient_editor->control->style->black_gc, - gradient_editor->control->style->bg_gc[GTK_STATE_PRELIGHT], - control_calc_p_pos (gradient_editor, pos), height); + editor->control->style->black_gc, + editor->control->style->bg_gc[GTK_STATE_PRELIGHT], + control_calc_p_pos (editor, pos), height); } static void @@ -2330,7 +1991,7 @@ control_draw_handle (GdkPixmap *pixmap, /*****/ static gint -control_calc_p_pos (GradientEditor *gradient_editor, +control_calc_p_pos (GradientEditor *editor, gdouble pos) { gint pwidth, pheight; @@ -2342,14 +2003,14 @@ control_calc_p_pos (GradientEditor *gradient_editor, * and the gradient control's handles. */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); return RINT ((pwidth - 1) * (pos - adjustment->value) / adjustment->page_size); } static gdouble -control_calc_g_pos (GradientEditor *gradient_editor, +control_calc_g_pos (GradientEditor *editor, gint pos) { gint pwidth, pheight; @@ -2357,2209 +2018,19 @@ control_calc_g_pos (GradientEditor *gradient_editor, /* Calculate the gradient position that corresponds to widget's coordinates */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); return adjustment->page_size * pos / (pwidth - 1) + adjustment->value; } -/***** Control popup functions *****/ - -static void -cpopup_create_main_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkWidget *label; - GtkAccelGroup *accel_group; - - menu = gtk_menu_new (); - accel_group = gtk_accel_group_new (); - - gradient_editor->accel_group = accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - gtk_window_add_accel_group (GTK_WINDOW (gradient_editor->shell), accel_group); - - /* Left endpoint */ - menuitem = cpopup_create_color_item (&gradient_editor->left_color_preview, - &label); - gtk_label_set_text (GTK_LABEL (label), _("Left endpoint's color")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_set_left_color_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'L', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Load from")); - gradient_editor->control_left_load_popup = - cpopup_create_load_menu (gradient_editor, - gradient_editor->left_load_color_boxes, - gradient_editor->left_load_labels, - _("Left neighbor's right endpoint"), - _("Right endpoint"), - G_CALLBACK (cpopup_load_left_callback), - 'L', GDK_CONTROL_MASK, - 'L', GDK_MOD1_MASK, - 'F', GDK_CONTROL_MASK); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), - gradient_editor->control_left_load_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Save to")); - gradient_editor->control_left_save_popup = - cpopup_create_save_menu (gradient_editor, - gradient_editor->left_save_color_boxes, - gradient_editor->left_save_labels, - G_CALLBACK (cpopup_save_left_callback)); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_left_save_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Right endpoint */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = cpopup_create_color_item (&gradient_editor->right_color_preview, - &label); - gtk_label_set_text (GTK_LABEL (label), _("Right endpoint's color")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_set_right_color_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'R', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Load from")); - gradient_editor->control_right_load_popup = - cpopup_create_load_menu (gradient_editor, - gradient_editor->right_load_color_boxes, - gradient_editor->right_load_labels, - _("Right neighbor's left endpoint"), - _("Left endpoint"), - G_CALLBACK (cpopup_load_right_callback), - 'R', GDK_CONTROL_MASK, - 'R', GDK_MOD1_MASK, - 'F', GDK_MOD1_MASK); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_right_load_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Save to")); - gradient_editor->control_right_save_popup = - cpopup_create_save_menu (gradient_editor, - gradient_editor->right_save_color_boxes, - gradient_editor->right_save_labels, - G_CALLBACK (cpopup_save_right_callback)); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_right_save_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Blending function */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_blending_label); - gradient_editor->control_blending_popup = - cpopup_create_blending_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_blending_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Coloring type */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_coloring_label); - gradient_editor->control_coloring_popup = - cpopup_create_coloring_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_coloring_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Operations */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Split at midpoint */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_split_m_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_split_midpoint_callback), - gradient_editor); - gtk_widget_add_accelerator(menuitem, "activate", - accel_group, - 'S', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Split uniformly */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_split_u_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_split_uniform_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'U', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Delete */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_delete_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_delete_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_delete_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'D', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Recenter */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_recenter_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_recenter_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'C', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Redistribute */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_redistribute_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_redistribute_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'C', GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Selection ops */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Selection operations")); - gradient_editor->control_sel_ops_popup = - cpopup_create_sel_ops_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), - gradient_editor->control_sel_ops_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Done */ - gradient_editor->control_main_popup = menu; -} - -static void -cpopup_do_popup (GradientEditor *gradient_editor) -{ - cpopup_adjust_menus (gradient_editor); - - gtk_menu_popup (GTK_MENU (gradient_editor->control_main_popup), - NULL, NULL, NULL, NULL, 3, 0); -} - -/***** Create a single menu item *****/ - -static GtkWidget * -cpopup_create_color_item (GtkWidget **color_box, - GtkWidget **label) -{ - GtkWidget *menuitem; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *wcolor_box; - GtkWidget *wlabel; - - menuitem = gtk_menu_item_new(); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (menuitem), hbox); - gtk_widget_show (hbox); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - wcolor_box = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX); - gtk_preview_size (GTK_PREVIEW (wcolor_box), - GRAD_COLOR_BOX_WIDTH, GRAD_COLOR_BOX_HEIGHT); - gtk_box_pack_start (GTK_BOX (vbox), wcolor_box, FALSE, FALSE, 2); - gtk_widget_show (wcolor_box); - - if (color_box) - *color_box = wcolor_box; - - wlabel = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (wlabel), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), wlabel, FALSE, FALSE, 4); - gtk_widget_show (wlabel); - - if (label) - *label = wlabel; - - return menuitem; -} - -static GtkWidget * -cpopup_create_menu_item_with_label (gchar *str, - GtkWidget **label) -{ - GtkWidget *menuitem; - GtkWidget *accel_label; - - menuitem = gtk_menu_item_new (); - - accel_label = gtk_accel_label_new (str); - gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5); - gtk_container_add (GTK_CONTAINER (menuitem), accel_label); - gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), - GTK_WIDGET (menuitem)); - gtk_widget_show (accel_label); - - if (label) - *label = accel_label; - - return menuitem; -} - -/***** Update all menus *****/ - -static void -cpopup_adjust_menus (GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg; - gint i; - GimpRGB fg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Render main menu color boxes */ - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_color_preview), - &gradient_editor->control_sel_l->left_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_color_preview), - &gradient_editor->control_sel_r->right_color); - - /* Render load color from endpoint color boxes */ - - if (gradient_editor->control_sel_l->prev != NULL) - seg = gradient_editor->control_sel_l->prev; - else - seg = gimp_gradient_segment_get_last (gradient_editor->control_sel_l); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[0]), - &seg->right_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[1]), - &gradient_editor->control_sel_r->right_color); - - if (gradient_editor->control_sel_r->next != NULL) - seg = gradient_editor->control_sel_r->next; - else - seg = gradient->segments; - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[0]), - &seg->left_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[1]), - &gradient_editor->control_sel_l->left_color); - - /* Render Foreground color boxes */ - - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[2]), - &fg); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[2]), - &fg); - - /* Render saved color boxes */ - - for (i = 0; i < GRAD_NUM_COLORS; i++) - cpopup_update_saved_color (gradient_editor, - i, &gradient_editor->saved_colors[i]); - - /* Adjust labels */ - - if (gradient_editor->control_sel_l == gradient_editor->control_sel_r) - { - gtk_label_set_text (GTK_LABEL (gradient_editor->control_blending_label), - _("Blending function for segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_coloring_label), - _("Coloring type for segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_m_label), - _("Split segment at midpoint")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_u_label), - _("Split segment uniformly")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_delete_label), - _("Delete segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_recenter_label), - _("Re-center segment's midpoint")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_redistribute_label), - _("Re-distribute handles in segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_flip_label), - _("Flip segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_replicate_label), - _("Replicate segment")); - } - else - { - gtk_label_set_text (GTK_LABEL (gradient_editor->control_blending_label), - _("Blending function for selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_coloring_label), - _("Coloring type for selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_m_label), - _("Split segments at midpoints")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_u_label), - _("Split segments uniformly")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_delete_label), - _("Delete selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_recenter_label), - _("Re-center midpoints in selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_redistribute_label), - _("Re-distribute handles in selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_flip_label), - _("Flip selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_replicate_label), - _("Replicate selection")); - } - - /* Adjust blending and coloring menus */ - cpopup_adjust_blending_menu (gradient_editor); - cpopup_adjust_coloring_menu (gradient_editor); - - /* Can invoke delete? */ - if ((gradient_editor->control_sel_l->prev == NULL) && - (gradient_editor->control_sel_r->next == NULL)) - gtk_widget_set_sensitive (gradient_editor->control_delete_menu_item, FALSE); - else - gtk_widget_set_sensitive (gradient_editor->control_delete_menu_item, TRUE); - - /* Can invoke blend colors / opacity? */ - if (gradient_editor->control_sel_l == gradient_editor->control_sel_r) - { - gtk_widget_set_sensitive (gradient_editor->control_blend_colors_menu_item, - FALSE); - gtk_widget_set_sensitive (gradient_editor->control_blend_opacity_menu_item, - FALSE); - } - else - { - gtk_widget_set_sensitive (gradient_editor->control_blend_colors_menu_item, - TRUE); - gtk_widget_set_sensitive (gradient_editor->control_blend_opacity_menu_item, - TRUE); - } -} - -static void -cpopup_adjust_blending_menu (GradientEditor *gradient_editor) -{ - gint equal; - glong i, num_items; - gint type; - - cpopup_check_selection_params (gradient_editor, &equal, NULL); - - /* Block activate signals */ - num_items = (sizeof (gradient_editor->control_blending_items) / - sizeof (gradient_editor->control_blending_items[0])); - - type = (int) gradient_editor->control_sel_l->type; - - for (i = 0; i < num_items; i++) - gtk_signal_handler_block_by_data - (GTK_OBJECT (gradient_editor->control_blending_items[i]), - gradient_editor); - - /* Set state */ - if (equal) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_blending_items[type]), TRUE); - gtk_widget_hide (gradient_editor->control_blending_items[num_items - 1]); - } - else - { - gtk_widget_show (gradient_editor->control_blending_items[num_items - 1]); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_blending_items[num_items - 1]), TRUE); - } - - /* Unblock signals */ - for (i = 0; i < num_items; i++) - gtk_signal_handler_unblock_by_data (GTK_OBJECT (gradient_editor->control_blending_items[i]), - gradient_editor); -} - -static void -cpopup_adjust_coloring_menu (GradientEditor *gradient_editor) -{ - gint equal; - glong i, num_items; - gint coloring; - - cpopup_check_selection_params (gradient_editor, NULL, &equal); - - /* Block activate signals */ - num_items = (sizeof (gradient_editor->control_coloring_items) / - sizeof (gradient_editor->control_coloring_items[0])); - - coloring = (int) gradient_editor->control_sel_l->color; - - for (i = 0; i < num_items; i++) - gtk_signal_handler_block_by_data (GTK_OBJECT (gradient_editor->control_coloring_items[i]), - gradient_editor); - - /* Set state */ - if (equal) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_coloring_items[coloring]), TRUE); - gtk_widget_hide (gradient_editor->control_coloring_items[num_items - 1]); - } - else - { - gtk_widget_show (gradient_editor->control_coloring_items[num_items - 1]); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_coloring_items[num_items - 1]), TRUE); - } - - /* Unblock signals */ - for (i = 0; i < num_items; i++) - gtk_signal_handler_unblock_by_data (GTK_OBJECT (gradient_editor->control_coloring_items[i]), - gradient_editor); -} - -static void -cpopup_check_selection_params (GradientEditor *gradient_editor, - gint *equal_blending, - gint *equal_coloring) -{ - GimpGradientSegmentType type; - GimpGradientSegmentColor color; - gint etype, ecolor; - GimpGradientSegment *seg, *aseg; - - type = gradient_editor->control_sel_l->type; - color = gradient_editor->control_sel_l->color; - - etype = 1; - ecolor = 1; - - seg = gradient_editor->control_sel_l; - - do - { - etype = etype && (seg->type == type); - ecolor = ecolor && (seg->color == color); - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - if (equal_blending) - *equal_blending = etype; - - if (equal_coloring) - *equal_coloring = ecolor; -} - -/*****/ - -static void -cpopup_render_color_box (GtkPreview *preview, - GimpRGB *color) -{ - guchar rows[3][GRAD_COLOR_BOX_WIDTH * 3]; - gint x, y; - gint r0, g0, b0; - gint r1, g1, b1; - guchar *p0, *p1, *p2; - - /* Fill rows */ - - r0 = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.0; - r1 = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - g0 = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.0; - g1 = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - b0 = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.0; - b1 = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - p0 = rows[0]; - p1 = rows[1]; - p2 = rows[2]; - - for (x = 0; x < GRAD_COLOR_BOX_WIDTH; x++) - { - if ((x == 0) || (x == (GRAD_COLOR_BOX_WIDTH - 1))) - { - *p0++ = 0; - *p0++ = 0; - *p0++ = 0; - - *p1++ = 0; - *p1++ = 0; - *p1++ = 0; - } - else - if ((x / GIMP_CHECK_SIZE) & 1) - { - *p0++ = r1; - *p0++ = g1; - *p0++ = b1; - - *p1++ = r0; - *p1++ = g0; - *p1++ = b0; - } - else - { - *p0++ = r0; - *p0++ = g0; - *p0++ = b0; - - *p1++ = r1; - *p1++ = g1; - *p1++ = b1; - } - - *p2++ = 0; - *p2++ = 0; - *p2++ = 0; - } - - /* Fill preview */ - - gtk_preview_draw_row (preview, rows[2], 0, 0, GRAD_COLOR_BOX_WIDTH); - - for (y = 1; y < (GRAD_COLOR_BOX_HEIGHT - 1); y++) - if ((y / GIMP_CHECK_SIZE) & 1) - gtk_preview_draw_row (preview, rows[1], 0, y, GRAD_COLOR_BOX_WIDTH); - else - gtk_preview_draw_row (preview, rows[0], 0, y, GRAD_COLOR_BOX_WIDTH); - - gtk_preview_draw_row (preview, rows[2], 0, y, GRAD_COLOR_BOX_WIDTH); -} - -/***** Creale load & save menus *****/ - -static GtkWidget * -cpopup_create_load_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - gchar *label1, - gchar *label2, - GCallback callback, - gchar accel_key_0, guint8 accel_mods_0, - gchar accel_key_1, guint8 accel_mods_1, - gchar accel_key_2, guint8 accel_mods_2) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkAccelGroup *accel_group; - gint i; - - menu = gtk_menu_new (); - accel_group = gradient_editor->accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - - /* Create items */ - for (i = 0; i < (GRAD_NUM_COLORS + 3); i++) - { - if (i == 3) - { - /* Insert separator between "to fetch" and "saved" colors */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - } - - menuitem = cpopup_create_color_item (&color_boxes[i], &labels[i]); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_object_set_data (G_OBJECT (menuitem), "user_data", - GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - callback, - gradient_editor); - - switch (i) - { - case 0: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_0, accel_mods_0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - case 1: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_1, accel_mods_1, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - case 2: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_2, accel_mods_2, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - default: - break; - } - } - - /* Set labels */ - gtk_label_set_text (GTK_LABEL (labels[0]), label1); - gtk_label_set_text (GTK_LABEL (labels[1]), label2); - gtk_label_set_text (GTK_LABEL (labels[2]), _("FG color")); - - return menu; -} - -static GtkWidget * -cpopup_create_save_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - GCallback callback) -{ - GtkWidget *menu; - GtkWidget *menuitem; - gint i; - - menu = gtk_menu_new (); - - for (i = 0; i < GRAD_NUM_COLORS; i++) - { - menuitem = cpopup_create_color_item (&color_boxes[i], &labels[i]); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - callback, - gradient_editor); - } - - return menu; -} - -static void -cpopup_update_saved_color (GradientEditor *gradient_editor, - gint n, - GimpRGB *color) -{ - gchar *str; - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[n + 3]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_save_color_boxes[n]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[n + 3]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_save_color_boxes[n]), - color); - - str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), - color->r, - color->g, - color->b, - color->a); - - gtk_label_set_text (GTK_LABEL (gradient_editor->left_load_labels[n + 3]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->left_save_labels[n]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->right_load_labels[n + 3]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->right_save_labels[n]), str); - - g_free (str); - - gradient_editor->saved_colors[n] = *color; -} - -/*****/ - -static void -cpopup_load_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradientSegment *seg; - GimpRGB fg; - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - switch (i) - { - case 0: /* Fetch from left neighbor's right endpoint */ - if (gradient_editor->control_sel_l->prev != NULL) - seg = gradient_editor->control_sel_l->prev; - else - seg = gimp_gradient_segment_get_last (gradient_editor->control_sel_l); - - cpopup_blend_endpoints (gradient_editor, - &seg->right_color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - case 1: /* Fetch from right endpoint */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->right_color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - case 2: /* Fetch from FG color */ - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - cpopup_blend_endpoints (gradient_editor, - &fg, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - default: /* Load a color */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->saved_colors[i - 3], - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - } - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_save_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient_editor->saved_colors[i] = gradient_editor->control_sel_l->left_color; -} - -static void -cpopup_load_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg; - GimpRGB fg; - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (i) - { - case 0: /* Fetch from right neighbor's left endpoint */ - if (gradient_editor->control_sel_r->next != NULL) - seg = gradient_editor->control_sel_r->next; - else - seg = gradient->segments; - - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - &seg->left_color, - TRUE, TRUE); - break; - - case 1: /* Fetch from left endpoint */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_l->left_color, - TRUE, TRUE); - break; - - case 2: /* Fetch from FG color */ - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &fg, - TRUE, TRUE); - break; - - default: /* Load a color */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->saved_colors[i - 3], - TRUE, TRUE); - break; - } - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_save_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient_editor->saved_colors[i] = gradient_editor->control_sel_r->right_color; -} - -/*****/ - -static GimpGradientSegment * -cpopup_save_selection (GradientEditor *gradient_editor) -{ - GimpGradientSegment *seg, *prev, *tmp; - GimpGradientSegment *oseg, *oaseg; - - prev = NULL; - oseg = gradient_editor->control_sel_l; - tmp = NULL; - - do - { - seg = gimp_gradient_segment_new (); - - *seg = *oseg; /* Copy everything */ - - if (prev == NULL) - tmp = seg; /* Remember first segment */ - else - prev->next = seg; - - seg->prev = prev; - seg->next = NULL; - - prev = seg; - oaseg = oseg; - oseg = oseg->next; - } - while (oaseg != gradient_editor->control_sel_r); - - return tmp; -} - -static void -cpopup_replace_selection (GradientEditor *gradient_editor, - GimpGradientSegment *replace_seg) -{ - GimpGradient *gradient; - GimpGradientSegment *lseg, *rseg; - GimpGradientSegment *replace_last; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Remember left and right segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - replace_last = gimp_gradient_segment_get_last (replace_seg); - - /* Free old selection */ - - gradient_editor->control_sel_r->next = NULL; - - gimp_gradient_segments_free (gradient_editor->control_sel_l); - - /* Link in new segments */ - - if (lseg) - lseg->next = replace_seg; - else - gradient->segments = replace_seg; - - replace_seg->prev = lseg; - - if (rseg) - rseg->prev = replace_last; - - replace_last->next = rseg; - - gradient_editor->control_sel_l = replace_seg; - gradient_editor->control_sel_r = replace_last; - - gradient->last_visited = NULL; /* Force re-search */ -} - -/***** Color dialogs for left and right endpoint *****/ - -static void -cpopup_set_left_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gradient_editor->left_saved_dirty = GIMP_DATA (gradient)->dirty; - gradient_editor->left_saved_segments = cpopup_save_selection (gradient_editor); - - color_notebook_new (_("Left Endpoint Color"), - &gradient_editor->control_sel_l->left_color, - (ColorNotebookCallback) cpopup_left_color_changed, - gradient_editor, - gradient_editor->instant_update, - TRUE); - - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_set_right_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gradient_editor->right_saved_dirty = GIMP_DATA (gradient)->dirty; - gradient_editor->right_saved_segments = cpopup_save_selection (gradient_editor); - - color_notebook_new (_("Right Endpoint Color"), - &gradient_editor->control_sel_l->right_color, - (ColorNotebookCallback) cpopup_right_color_changed, - gradient_editor, - gradient_editor->instant_update, - TRUE); - - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_left_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data) -{ - GradientEditor *gradient_editor; - GimpGradient *gradient; - - gradient_editor = (GradientEditor *) data; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (state) - { - case COLOR_NOTEBOOK_OK: - cpopup_blend_endpoints (gradient_editor, - (GimpRGB *) color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - gimp_gradient_segments_free (gradient_editor->left_saved_segments); - gimp_data_dirty (GIMP_DATA (gradient)); - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - - case COLOR_NOTEBOOK_UPDATE: - cpopup_blend_endpoints (gradient_editor, - (GimpRGB *) color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - gimp_data_dirty (GIMP_DATA (gradient)); - break; - - case COLOR_NOTEBOOK_CANCEL: - cpopup_replace_selection (gradient_editor, - gradient_editor->left_saved_segments); - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); - GIMP_DATA (gradient)->dirty = gradient_editor->left_saved_dirty; - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - } - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_right_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data) -{ - GradientEditor *gradient_editor; - GimpGradient *gradient; - - gradient_editor = (GradientEditor *) data; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (state) - { - case COLOR_NOTEBOOK_UPDATE: - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - (GimpRGB *) color, - TRUE, TRUE); - gimp_data_dirty (GIMP_DATA (gradient)); - break; - - case COLOR_NOTEBOOK_OK: - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - (GimpRGB *) color, - TRUE, TRUE); - gimp_gradient_segments_free (gradient_editor->right_saved_segments); - gimp_data_dirty (GIMP_DATA (gradient)); - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - - case COLOR_NOTEBOOK_CANCEL: - cpopup_replace_selection (gradient_editor, - gradient_editor->right_saved_segments); - GIMP_DATA (gradient)->dirty = gradient_editor->right_saved_dirty; - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - } - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Blending menu *****/ - -static GtkWidget * -cpopup_create_blending_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GSList *group; - gint i; - - static const gchar *blending_types[] = - { - N_("Linear"), - N_("Curved"), - N_("Sinusoidal"), - N_("Spherical (increasing)"), - N_("Spherical (decreasing)") - }; - - menu = gtk_menu_new (); - group = NULL; - - for (i = 0; i < G_N_ELEMENTS (gradient_editor->control_blending_items); i++) - { - if (i == (G_N_ELEMENTS (gradient_editor->control_blending_items) - 1)) - { - menuitem = gtk_radio_menu_item_new_with_label (group, _("(Varies)")); - } - else - { - menuitem = - gtk_radio_menu_item_new_with_label (group, - gettext (blending_types[i])); - } - - group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - gradient_editor->control_blending_items[i] = menuitem; - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blending_callback), - gradient_editor); - } - - /* "Varies" is always disabled */ - gtk_widget_set_sensitive (gradient_editor->control_blending_items[G_N_ELEMENTS (gradient_editor->control_blending_items) - 1], FALSE); - - return menu; -} - -static void -cpopup_blending_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegmentType type; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (!GTK_CHECK_MENU_ITEM (widget)->active) - return; /* Do nothing if the menu item is being deactivated */ - - type = (GimpGradientSegmentType) - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - seg = gradient_editor->control_sel_l; - - do - { - seg->type = type; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Coloring menu *****/ - -static GtkWidget * -cpopup_create_coloring_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GSList *group; - gint i; - - static const gchar *coloring_types[] = - { - N_("Plain RGB"), - N_("HSV (counter-clockwise hue)"), - N_("HSV (clockwise hue)") - }; - - menu = gtk_menu_new (); - group = NULL; - - for (i = 0; i < G_N_ELEMENTS (gradient_editor->control_coloring_items); i++) - { - if (i == (G_N_ELEMENTS (gradient_editor->control_coloring_items) - 1)) - { - menuitem = gtk_radio_menu_item_new_with_label(group, _("(Varies)")); - } - else - { - menuitem = - gtk_radio_menu_item_new_with_label (group, - gettext (coloring_types[i])); - } - - group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - gradient_editor->control_coloring_items[i] = menuitem; - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_coloring_callback), - gradient_editor); - } - - /* "Varies" is always disabled */ - gtk_widget_set_sensitive (gradient_editor->control_coloring_items[G_N_ELEMENTS (gradient_editor->control_coloring_items) - 1], FALSE); - - return menu; -} - -static void -cpopup_coloring_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegmentColor color; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (! GTK_CHECK_MENU_ITEM (widget)->active) - return; /* Do nothing if the menu item is being deactivated */ - - color = (GimpGradientSegmentColor) - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - seg = gradient_editor->control_sel_l; - - do - { - seg->color = color; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/*****/ - -static void -cpopup_split_midpoint_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *lseg, *rseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - seg = gradient_editor->control_sel_l; - - do - { - cpopup_split_midpoint (gradient, seg, &lseg, &rseg); - seg = rseg->next; - } - while (lseg != gradient_editor->control_sel_r); - - gradient_editor->control_sel_r = rseg; - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_split_midpoint (GimpGradient *gradient, - GimpGradientSegment *lseg, - GimpGradientSegment **newl, - GimpGradientSegment **newr) -{ - GimpRGB color; - GimpGradientSegment *newseg; - - /* Get color at original segment's midpoint */ - gimp_gradient_get_color_at (gradient, lseg->middle, &color); - - /* Create a new segment and insert it in the list */ - - newseg = gimp_gradient_segment_new (); - - newseg->prev = lseg; - newseg->next = lseg->next; - - lseg->next = newseg; - - if (newseg->next) - newseg->next->prev = newseg; - - /* Set coordinates of new segment */ - - newseg->left = lseg->middle; - newseg->right = lseg->right; - newseg->middle = (newseg->left + newseg->right) / 2.0; - - /* Set coordinates of original segment */ - - lseg->right = newseg->left; - lseg->middle = (lseg->left + lseg->right) / 2.0; - - /* Set colors of both segments */ - - newseg->right_color = lseg->right_color; - - lseg->right_color.r = newseg->left_color.r = color.r; - lseg->right_color.g = newseg->left_color.g = color.g; - lseg->right_color.b = newseg->left_color.b = color.b; - lseg->right_color.a = newseg->left_color.a = color.a; - - /* Set parameters of new segment */ - - newseg->type = lseg->type; - newseg->color = lseg->color; - - /* Done */ - - *newl = lseg; - *newr = newseg; -} - -/*****/ - -static void -cpopup_split_uniform_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GtkWidget *dialog; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *scale; - GtkObject *scale_data; - - /* Create dialog window */ - dialog = - gimp_dialog_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("Split segment uniformly") : - _("Split segments uniformly"), - "gradient_segment_split_uniformly", - gimp_standard_help_func, - "dialogs/gradient_editor/split_segments_uniformly.html", - GTK_WIN_POS_MOUSE, - FALSE, TRUE, FALSE, - - GTK_STOCK_CANCEL, cpopup_split_uniform_cancel_callback, - gradient_editor, NULL, NULL, FALSE, TRUE, - - _("Split"), cpopup_split_uniform_split_callback, - gradient_editor, NULL, NULL, TRUE, FALSE, - - NULL); - - /* The main vbox */ - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); - gtk_widget_show (vbox); - - /* Instructions */ - label = gtk_label_new (_("Please select the number of uniform parts")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - label = - gtk_label_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("in which you want to split the selected segment") : - _("in which you want to split the segments in the selection")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* Scale */ - gradient_editor->split_parts = 2; - scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); - - scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 4); - gtk_widget_show (scale); - - g_signal_connect (G_OBJECT (scale_data), "value_changed", - G_CALLBACK (cpopup_split_uniform_scale_update), - gradient_editor); - - /* Show! */ - gtk_widget_show (dialog); - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_split_uniform_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) -{ - gradient_editor->split_parts = ROUND (adjustment->value + 0.5); -} - -static void -cpopup_split_uniform_split_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg, *lseg, *rseg, *lsel; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - - seg = gradient_editor->control_sel_l; - lsel = NULL; - - do - { - aseg = seg; - - cpopup_split_uniform (gradient, seg, - gradient_editor->split_parts, &lseg, &rseg); - - if (seg == gradient_editor->control_sel_l) - lsel = lseg; - - seg = rseg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gradient_editor->control_sel_l = lsel; - gradient_editor->control_sel_r = rseg; - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_split_uniform_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); -} - -static void -cpopup_split_uniform (GimpGradient *gradient, - GimpGradientSegment *lseg, - gint parts, - GimpGradientSegment **newl, - GimpGradientSegment **newr) -{ - GimpGradientSegment *seg, *prev, *tmp; - gdouble seg_len; - gint i; - - seg_len = (lseg->right - lseg->left) / parts; /* Length of divisions */ - - seg = NULL; - prev = NULL; - tmp = NULL; - - for (i = 0; i < parts; i++) - { - seg = gimp_gradient_segment_new (); - - if (i == 0) - tmp = seg; /* Remember first segment */ - - seg->left = lseg->left + i * seg_len; - seg->right = lseg->left + (i + 1) * seg_len; - seg->middle = (seg->left + seg->right) / 2.0; - - gimp_gradient_get_color_at (gradient, seg->left, &seg->left_color); - gimp_gradient_get_color_at (gradient, seg->right, &seg->right_color); - - seg->type = lseg->type; - seg->color = lseg->color; - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - } - - /* Fix edges */ - - tmp->left_color = lseg->left_color; - - seg->right_color = lseg->right_color; - - tmp->left = lseg->left; - seg->right = lseg->right; /* To squish accumulative error */ - - /* Link in list */ - - tmp->prev = lseg->prev; - seg->next = lseg->next; - - if (lseg->prev) - lseg->prev->next = tmp; - else - gradient->segments = tmp; /* We are on leftmost segment */ - - if (lseg->next) - lseg->next->prev = seg; - - gradient->last_visited = NULL; /* Force re-search */ - - /* Done */ - - *newl = tmp; - *newr = seg; - - /* Delete old segment */ - - gimp_gradient_segment_free (lseg); -} - -/*****/ - -static void -cpopup_delete_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *lseg, *rseg, *seg, *aseg, *next; - double join; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Remember segments to the left and to the right of the selection */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - /* Cannot delete all the segments in the gradient */ - - if ((lseg == NULL) && (rseg == NULL)) - return; - - /* Calculate join point */ - - join = (gradient_editor->control_sel_l->left + - gradient_editor->control_sel_r->right) / 2.0; - - if (lseg == NULL) - join = 0.0; - else if (rseg == NULL) - join = 1.0; - - /* Move segments */ - - if (lseg != NULL) - control_compress_range (lseg, lseg, lseg->left, join); - - if (rseg != NULL) - control_compress_range (rseg, rseg, join, rseg->right); - - /* Link */ - - if (lseg) - lseg->next = rseg; - - if (rseg) - rseg->prev = lseg; - - /* Delete old segments */ - - seg = gradient_editor->control_sel_l; - - do - { - next = seg->next; - aseg = seg; - - gimp_gradient_segment_free (seg); - - seg = next; - } - while (aseg != gradient_editor->control_sel_r); - - /* Change selection */ - - if (rseg) - { - gradient_editor->control_sel_l = rseg; - gradient_editor->control_sel_r = rseg; - } - else - { - gradient_editor->control_sel_l = lseg; - gradient_editor->control_sel_r = lseg; - } - - if (lseg == NULL) - gradient->segments = rseg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_recenter_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - seg = gradient_editor->control_sel_l; - - do - { - seg->middle = (seg->left + seg->right) / 2.0; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_redistribute_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg; - gdouble left, right, seg_len; - gint num_segs; - gint i; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Count number of segments in selection */ - - num_segs = 0; - seg = gradient_editor->control_sel_l; - - do - { - num_segs++; - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - /* Calculate new segment length */ - - left = gradient_editor->control_sel_l->left; - right = gradient_editor->control_sel_r->right; - seg_len = (right - left) / num_segs; - - /* Redistribute */ - - seg = gradient_editor->control_sel_l; - - for (i = 0; i < num_segs; i++) - { - seg->left = left + i * seg_len; - seg->right = left + (i + 1) * seg_len; - seg->middle = (seg->left + seg->right) / 2.0; - - seg = seg->next; - } - - /* Fix endpoints to squish accumulative error */ - - gradient_editor->control_sel_l->left = left; - gradient_editor->control_sel_r->right = right; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - - -/***** Control popup -> selection options functions *****/ - -static GtkWidget * -cpopup_create_sel_ops_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkAccelGroup *accel_group; - - menu = gtk_menu_new (); - accel_group = gradient_editor->accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - - /* Flip */ - menuitem = - cpopup_create_menu_item_with_label ("", &gradient_editor->control_flip_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_flip_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'F', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Replicate */ - menuitem = - cpopup_create_menu_item_with_label ("", &gradient_editor->control_replicate_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_replicate_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'M', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Blend colors / opacity */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Blend endpoints' colors")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_blend_colors_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blend_colors), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'B', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Blend endpoints' opacity")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_blend_opacity_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blend_opacity), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'B', GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - return menu; -} - -static void -cpopup_flip_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *oseg, *oaseg; - GimpGradientSegment *seg, *prev, *tmp; - GimpGradientSegment *lseg, *rseg; - gdouble left, right; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - left = gradient_editor->control_sel_l->left; - right = gradient_editor->control_sel_r->right; - - /* Build flipped segments */ - - prev = NULL; - oseg = gradient_editor->control_sel_r; - tmp = NULL; - - do - { - seg = gimp_gradient_segment_new (); - - if (prev == NULL) - { - seg->left = left; - tmp = seg; /* Remember first segment */ - } - else - seg->left = left + right - oseg->right; - - seg->middle = left + right - oseg->middle; - seg->right = left + right - oseg->left; - - seg->left_color = oseg->right_color; - - seg->right_color = oseg->left_color; - - switch (oseg->type) - { - case GRAD_SPHERE_INCREASING: - seg->type = GRAD_SPHERE_DECREASING; - break; - - case GRAD_SPHERE_DECREASING: - seg->type = GRAD_SPHERE_INCREASING; - break; - - default: - seg->type = oseg->type; - } - - switch (oseg->color) - { - case GRAD_HSV_CCW: - seg->color = GRAD_HSV_CW; - break; - - case GRAD_HSV_CW: - seg->color = GRAD_HSV_CCW; - break; - - default: - seg->color = oseg->color; - } - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - - oaseg = oseg; - oseg = oseg->prev; /* Move backwards! */ - } - while (oaseg != gradient_editor->control_sel_l); - - seg->right = right; /* Squish accumulative error */ - - /* Free old segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - oseg = gradient_editor->control_sel_l; - - do - { - oaseg = oseg->next; - gimp_gradient_segment_free (oseg); - oseg = oaseg; - } - while (oaseg != rseg); - - /* Link in new segments */ - - if (lseg) - lseg->next = tmp; - else - gradient->segments = tmp; - - tmp->prev = lseg; - - seg->next = rseg; - - if (rseg) - rseg->prev = seg; - - /* Reset selection */ - - gradient_editor->control_sel_l = tmp; - gradient_editor->control_sel_r = seg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GtkWidget *dialog; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *scale; - GtkObject *scale_data; - - /* Create dialog window */ - dialog = - gimp_dialog_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("Replicate segment") : - _("Replicate selection"), - "gradient_segment_replicate", - gimp_standard_help_func, - "dialogs/gradient_editor/replicate_segment.html", - GTK_WIN_POS_MOUSE, - FALSE, TRUE, FALSE, - - _("Replicate"), cpopup_do_replicate_callback, - gradient_editor, NULL, NULL, FALSE, FALSE, - GTK_STOCK_CANCEL, cpopup_replicate_cancel_callback, - gradient_editor, NULL, NULL, TRUE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); - gtk_widget_show (vbox); - - /* Instructions */ - label = gtk_label_new (_("Please select the number of times")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - label = gtk_label_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("you want to replicate the selected segment") : - _("you want to replicate the selection")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* Scale */ - gradient_editor->replicate_times = 2; - scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); - - scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 4); - gtk_widget_show (scale); - - g_signal_connect (G_OBJECT (scale_data), "value_changed", - G_CALLBACK (cpopup_replicate_scale_update), - gradient_editor); - - /* Show! */ - gtk_widget_show (dialog); - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_replicate_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) -{ - gradient_editor->replicate_times = (int) (adjustment->value + 0.5); -} - -static void -cpopup_do_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - gdouble sel_left, sel_right, sel_len; - gdouble new_left; - gdouble factor; - GimpGradientSegment *prev, *seg, *tmp; - GimpGradientSegment *oseg, *oaseg; - GimpGradientSegment *lseg, *rseg; - gint i; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - - /* Remember original parameters */ - sel_left = gradient_editor->control_sel_l->left; - sel_right = gradient_editor->control_sel_r->right; - sel_len = sel_right - sel_left; - - factor = 1.0 / gradient_editor->replicate_times; - - /* Build replicated segments */ - - prev = NULL; - seg = NULL; - tmp = NULL; - - for (i = 0; i < gradient_editor->replicate_times; i++) - { - /* Build one cycle */ - - new_left = sel_left + i * factor * sel_len; - - oseg = gradient_editor->control_sel_l; - - do - { - seg = gimp_gradient_segment_new (); - - if (prev == NULL) - { - seg->left = sel_left; - tmp = seg; /* Remember first segment */ - } - else - seg->left = new_left + factor * (oseg->left - sel_left); - - seg->middle = new_left + factor * (oseg->middle - sel_left); - seg->right = new_left + factor * (oseg->right - sel_left); - - seg->left_color = oseg->right_color; - - seg->right_color = oseg->right_color; - - seg->type = oseg->type; - seg->color = oseg->color; - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - - oaseg = oseg; - oseg = oseg->next; - } - while (oaseg != gradient_editor->control_sel_r); - } - - seg->right = sel_right; /* Squish accumulative error */ - - /* Free old segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - oseg = gradient_editor->control_sel_l; - - do - { - oaseg = oseg->next; - gimp_gradient_segment_free (oseg); - oseg = oaseg; - } - while (oaseg != rseg); - - /* Link in new segments */ - - if (lseg) - lseg->next = tmp; - else - gradient->segments = tmp; - - tmp->prev = lseg; - - seg->next = rseg; - - if (rseg) - rseg->prev = seg; - - /* Reset selection */ - - gradient_editor->control_sel_l = tmp; - gradient_editor->control_sel_r = seg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_replicate_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); -} - -static void -cpopup_blend_colors (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_r->right_color, - TRUE, FALSE); - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_blend_opacity (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_r->right_color, - FALSE, TRUE); - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Main blend function *****/ - -static void -cpopup_blend_endpoints (GradientEditor *gradient_editor, - GimpRGB *rgb1, - GimpRGB *rgb2, - gboolean blend_colors, - gboolean blend_opacity) -{ - GimpRGB d; - gdouble left, len; - GimpGradientSegment *seg; - GimpGradientSegment *aseg; - - d.r = rgb2->r - rgb1->r; - d.g = rgb2->g - rgb1->g; - d.b = rgb2->b - rgb1->b; - d.a = rgb2->a - rgb1->a; - - left = gradient_editor->control_sel_l->left; - len = gradient_editor->control_sel_r->right - left; - - seg = gradient_editor->control_sel_l; - - do - { - if (blend_colors) - { - seg->left_color.r = rgb1->r + (seg->left - left) / len * d.r; - seg->left_color.g = rgb1->g + (seg->left - left) / len * d.g; - seg->left_color.b = rgb1->b + (seg->left - left) / len * d.b; - - seg->right_color.r = rgb1->r + (seg->right - left) / len * d.r; - seg->right_color.g = rgb1->g + (seg->right - left) / len * d.g; - seg->right_color.b = rgb1->b + (seg->right - left) / len * d.b; - } - - if (blend_opacity) - { - seg->left_color.a = rgb1->a + (seg->left - left) / len * d.a; - seg->right_color.a = rgb1->a + (seg->right - left) / len * d.a; - } - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); -} - /***** Segment functions *****/ static void -seg_get_closest_handle (GimpGradient *grad, - gdouble pos, - GimpGradientSegment **seg, - control_drag_mode_t *handle) +seg_get_closest_handle (GimpGradient *grad, + gdouble pos, + GimpGradientSegment **seg, + GradientEditorDragMode *handle) { gdouble l_delta, m_delta, r_delta; diff --git a/app/gui/gradient-editor.h b/app/gui/gradient-editor.h index bf4bf14918..abfb2aea90 100644 --- a/app/gui/gradient-editor.h +++ b/app/gui/gradient-editor.h @@ -23,14 +23,89 @@ #define __GRADIENT_EDITOR_H__ -typedef struct _GradientEditor GradientEditor; +#define GRAD_NUM_COLORS 10 -GradientEditor * gradient_editor_new (Gimp *gimp); +typedef enum +{ + GRAD_DRAG_NONE = 0, + GRAD_DRAG_LEFT, + GRAD_DRAG_MIDDLE, + GRAD_DRAG_ALL +} GradientEditorDragMode; -void gradient_editor_set_gradient (GradientEditor *gradient_editor, - GimpGradient *gradient); -void gradient_editor_free (GradientEditor *gradient_editor); +typedef enum +{ + GRAD_UPDATE_GRADIENT = 1 << 0, + GRAD_UPDATE_PREVIEW = 1 << 1, + GRAD_UPDATE_CONTROL = 1 << 2, + GRAD_RESET_CONTROL = 1 << 3 +} GradientEditorUpdateMask; + + +struct _GradientEditor +{ + GtkWidget *shell; + + GtkWidget *name; + + GtkWidget *hint_label; + GtkWidget *scrollbar; + GtkWidget *preview; + GtkWidget *control; + + GimpContext *context; + + /* Zoom and scrollbar */ + guint zoom_factor; + GtkObject *scroll_data; + + /* Instant update */ + gboolean instant_update; + + /* Gradient preview */ + guchar *preview_rows[2]; /* For caching redraw info */ + gint preview_last_x; + gboolean preview_button_down; + + /* Gradient control */ + GdkPixmap *control_pixmap; + GimpGradientSegment *control_drag_segment; /* Segment which is being dragged */ + GimpGradientSegment *control_sel_l; /* Left segment of selection */ + GimpGradientSegment *control_sel_r; /* Right segment of selection */ + GradientEditorDragMode control_drag_mode; /* What is being dragged? */ + guint32 control_click_time; /* Time when mouse was pressed */ + gboolean control_compress; /* Compressing/expanding handles */ + gint control_last_x; /* Last mouse position when dragging */ + gdouble control_last_gx; /* Last position (wrt gradient) when dragging */ + gdouble control_orig_pos; /* Original click position when dragging */ + + /* Split uniformly dialog */ + gint split_parts; + + /* Replicate dialog */ + gint replicate_times; + + /* Saved colors */ + GimpRGB saved_colors[GRAD_NUM_COLORS]; + + /* Color dialogs */ + GimpGradientSegment *left_saved_segments; + gboolean left_saved_dirty; + + GimpGradientSegment *right_saved_segments; + gboolean right_saved_dirty; +}; + + +GradientEditor * gradient_editor_new (Gimp *gimp); + +void gradient_editor_set_gradient (GradientEditor *gradient_editor, + GimpGradient *gradient); +void gradient_editor_free (GradientEditor *gradient_editor); + +void gradient_editor_update (GradientEditor *gradient_editor, + GradientEditorUpdateMask flags); #endif /* __GRADIENT_EDITOR_H__ */ diff --git a/app/gui/gui-types.h b/app/gui/gui-types.h index 3b15a9333b..172a5ce13c 100644 --- a/app/gui/gui-types.h +++ b/app/gui/gui-types.h @@ -25,6 +25,7 @@ typedef struct _ColorNotebook ColorNotebook; +typedef struct _GradientEditor GradientEditor; typedef struct _InfoDialog InfoDialog; typedef struct _NavigationDialog NavigationDialog; diff --git a/app/gui/menus.c b/app/gui/menus.c index 80a43e691d..59fe3ac03b 100644 --- a/app/gui/menus.c +++ b/app/gui/menus.c @@ -53,6 +53,7 @@ #include "documents-commands.h" #include "edit-commands.h" #include "file-commands.h" +#include "gradient-editor-commands.h" #include "gradients-commands.h" #include "image-commands.h" #include "layers-commands.h" @@ -1446,6 +1447,324 @@ static GimpItemFactoryEntry patterns_entries[] = }; +/***** *****/ + +static GimpItemFactoryEntry gradient_editor_entries[] = +{ + { { N_("/Left Endpoint's Color..."), NULL, + gradient_editor_left_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Left Color From/Left Neighbor's Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/FG Color"), NULL, + gradient_editor_load_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/BG Color"), NULL, + gradient_editor_load_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Left Color From/---"), + + { { "/Load Left Color From/01", NULL, + gradient_editor_load_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/02", NULL, + gradient_editor_load_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/03", NULL, + gradient_editor_load_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/04", NULL, + gradient_editor_load_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/05", NULL, + gradient_editor_load_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/06", NULL, + gradient_editor_load_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/07", NULL, + gradient_editor_load_left_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/08", NULL, + gradient_editor_load_left_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/09", NULL, + gradient_editor_load_left_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/10", NULL, + gradient_editor_load_left_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Left Color To")), + + { { "/Save Left Color To/01", NULL, + gradient_editor_save_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/02", NULL, + gradient_editor_save_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/03", NULL, + gradient_editor_save_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/04", NULL, + gradient_editor_save_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/05", NULL, + gradient_editor_save_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/06", NULL, + gradient_editor_save_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/07", NULL, + gradient_editor_save_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/08", NULL, + gradient_editor_save_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/09", NULL, + gradient_editor_save_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/10", NULL, + gradient_editor_save_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Right Endpoint's Color..."), NULL, + gradient_editor_right_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Right Color From/Right Neighbor's Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/FG Color"), NULL, + gradient_editor_load_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/BG Color"), NULL, + gradient_editor_load_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Right Color From/---"), + + { { "/Load Right Color From/01", NULL, + gradient_editor_load_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/02", NULL, + gradient_editor_load_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/03", NULL, + gradient_editor_load_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/04", NULL, + gradient_editor_load_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/05", NULL, + gradient_editor_load_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/06", NULL, + gradient_editor_load_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/07", NULL, + gradient_editor_load_right_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/08", NULL, + gradient_editor_load_right_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/09", NULL, + gradient_editor_load_right_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/10", NULL, + gradient_editor_load_right_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Right Color To")), + + { { "/Save Right Color To/01", NULL, + gradient_editor_save_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/02", NULL, + gradient_editor_save_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/03", NULL, + gradient_editor_save_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/04", NULL, + gradient_editor_save_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/05", NULL, + gradient_editor_save_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/06", NULL, + gradient_editor_save_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/07", NULL, + gradient_editor_save_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/08", NULL, + gradient_editor_save_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/09", NULL, + gradient_editor_save_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/10", NULL, + gradient_editor_save_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/blendingfunction/Linear"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_LINEAR, "" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Curved"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_CURVED, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Sinusodial"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SINE, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (increasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_INCREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (decreasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_DECREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/(Varies)"), NULL, NULL, + 0, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + + { { N_("/coloringtype/RGB"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_RGB, "" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (counter-clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CCW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/(Varies)"), NULL, NULL, + 0, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { "/flip", "F", + gradient_editor_flip_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/replicate", "R", + gradient_editor_replicate_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splitmidpoint", "S", + gradient_editor_split_midpoint_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splituniformly", "U", + gradient_editor_split_uniformly_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/delete", "D", + gradient_editor_delete_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/recenter", "C", + gradient_editor_recenter_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/redistribute", "C", + gradient_editor_redistribute_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Blend Endpoints' Colors"), "B", + gradient_editor_blend_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Blend Endpoints' Opacity"), "B", + gradient_editor_blend_opacity_cmd_callback, 0 }, + NULL, + NULL, NULL }, +}; + + /***** *****/ static GimpItemFactoryEntry gradients_entries[] = @@ -1601,20 +1920,21 @@ static GimpItemFactoryEntry documents_entries[] = static gboolean menus_initialized = FALSE; -static GtkItemFactory *toolbox_factory = NULL; -static GtkItemFactory *image_factory = NULL; -static GtkItemFactory *load_factory = NULL; -static GtkItemFactory *save_factory = NULL; -static GtkItemFactory *layers_factory = NULL; -static GtkItemFactory *channels_factory = NULL; -static GtkItemFactory *paths_factory = NULL; -static GtkItemFactory *dialogs_factory = NULL; -static GtkItemFactory *brushes_factory = NULL; -static GtkItemFactory *patterns_factory = NULL; -static GtkItemFactory *gradients_factory = NULL; -static GtkItemFactory *palettes_factory = NULL; -static GtkItemFactory *buffers_factory = NULL; -static GtkItemFactory *documents_factory = NULL; +static GtkItemFactory *toolbox_factory = NULL; +static GtkItemFactory *image_factory = NULL; +static GtkItemFactory *load_factory = NULL; +static GtkItemFactory *save_factory = NULL; +static GtkItemFactory *layers_factory = NULL; +static GtkItemFactory *channels_factory = NULL; +static GtkItemFactory *paths_factory = NULL; +static GtkItemFactory *dialogs_factory = NULL; +static GtkItemFactory *brushes_factory = NULL; +static GtkItemFactory *patterns_factory = NULL; +static GtkItemFactory *gradient_editor_factory = NULL; +static GtkItemFactory *gradients_factory = NULL; +static GtkItemFactory *palettes_factory = NULL; +static GtkItemFactory *buffers_factory = NULL; +static GtkItemFactory *documents_factory = NULL; /* public functions */ @@ -1760,6 +2080,13 @@ menus_init (Gimp *gimp) gimp, FALSE); + gradient_editor_factory = menus_item_factory_new (GTK_TYPE_MENU, + "", "gradient_editor", + G_N_ELEMENTS (gradient_editor_entries), + gradient_editor_entries, + gimp, + FALSE); + gradients_factory = menus_item_factory_new (GTK_TYPE_MENU, "", "gradients", G_N_ELEMENTS (gradients_entries), @@ -1931,6 +2258,12 @@ menus_exit (Gimp *gimp) patterns_factory = NULL; } + if (gradient_editor_factory) + { + g_object_unref (G_OBJECT (gradient_editor_factory)); + gradient_editor_factory = NULL; + } + if (gradients_factory) { g_object_unref (G_OBJECT (gradients_factory)); @@ -2205,6 +2538,12 @@ menus_get_patterns_factory (void) return patterns_factory; } +GtkItemFactory * +menus_get_gradient_editor_factory (void) +{ + return gradient_editor_factory; +} + GtkItemFactory * menus_get_gradients_factory (void) { @@ -2264,6 +2603,222 @@ menus_create_item_from_full_path (GimpItemFactoryEntry *entry, menus_create_item (item_factory, entry, callback_data, 2, TRUE, FALSE); } +void +menus_set_active (gchar *path, + gboolean active) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), active); + else + widget = NULL; + } + + if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) + g_warning ("Unable to set \"active\" for menu which doesn't exist:\n%s", + path); +} + +void +menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget; + GtkWidget *preview = NULL; + GtkWidget *label = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (color != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + +#define COLOR_BOX_WIDTH 24 +#define COLOR_BOX_HEIGHT 16 + + if (! ifactory) + return; + + widget = gtk_item_factory_get_widget (ifactory, path); + + if (! widget) + return; + + if (GTK_IS_HBOX (GTK_BIN (widget)->child)) + { + preview = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "preview"); + label = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "label"); + } + else if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + GtkWidget *hbox; + + label = GTK_BIN (widget)->child; + + g_object_ref (G_OBJECT (label)); + + gtk_container_remove (GTK_CONTAINER (widget), label); + + hbox = gtk_hbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (widget), hbox); + gtk_widget_show (hbox); + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (preview), + COLOR_BOX_WIDTH, COLOR_BOX_HEIGHT); + gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0); + gtk_widget_show (preview); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + g_object_unref (G_OBJECT (label)); + + g_object_set_data (G_OBJECT (hbox), "preview", preview); + g_object_set_data (G_OBJECT (hbox), "label", label); + } + + if (preview) + { + guchar rows[3][COLOR_BOX_WIDTH * 3]; + gint x, y; + gint r0, g0, b0; + gint r1, g1, b1; + guchar *p0, *p1, *p2; + + /* Fill rows */ + + r0 = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.0; + r1 = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + g0 = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.0; + g1 = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + b0 = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.0; + b1 = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + p0 = rows[0]; + p1 = rows[1]; + p2 = rows[2]; + + for (x = 0; x < COLOR_BOX_WIDTH; x++) + { + if ((x == 0) || (x == (COLOR_BOX_WIDTH - 1))) + { + *p0++ = 0; + *p0++ = 0; + *p0++ = 0; + + *p1++ = 0; + *p1++ = 0; + *p1++ = 0; + } + else if ((x / GIMP_CHECK_SIZE) & 1) + { + *p0++ = r1; + *p0++ = g1; + *p0++ = b1; + + *p1++ = r0; + *p1++ = g0; + *p1++ = b0; + } + else + { + *p0++ = r0; + *p0++ = g0; + *p0++ = b0; + + *p1++ = r1; + *p1++ = g1; + *p1++ = b1; + } + + *p2++ = 0; + *p2++ = 0; + *p2++ = 0; + } + + /* Fill preview */ + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, 0, COLOR_BOX_WIDTH); + + for (y = 1; y < (COLOR_BOX_HEIGHT - 1); y++) + if ((y / GIMP_CHECK_SIZE) & 1) + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[1], + 0, y, COLOR_BOX_WIDTH); + else + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[0], + 0, y, COLOR_BOX_WIDTH); + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, y, COLOR_BOX_WIDTH); + } + + if (label && set_label) + { + gchar *str; + + str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), + color->r, color->g, color->b, color->a); + + gtk_label_set_text (GTK_LABEL (label), str); + + g_free (str); + } + +#undef COLOR_BOX_WIDTH +#undef COLOR_BOX_HEIGHT +} + +void +menus_set_label (gchar *path, + const gchar *label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (label != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget) + { + if (GTK_IS_MENU (widget)) + { + widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); + } + + if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), label); + } + } + } +} + void menus_set_sensitive (gchar *path, gboolean sensitive) @@ -2290,11 +2845,11 @@ menus_set_sensitive (gchar *path, } void -menus_set_state (gchar *path, - gboolean state) +menus_set_visible (gchar *path, + gboolean visible) { GtkItemFactory *ifactory; - GtkWidget *widget = NULL; + GtkWidget *widget; g_return_if_fail (path != NULL); g_return_if_fail (menus_initialized); @@ -2305,15 +2860,14 @@ menus_set_state (gchar *path, { widget = gtk_item_factory_get_widget (ifactory, path); - if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), state); - else - widget = NULL; + if (widget) + { + if (visible) + gtk_widget_show (widget); + else + gtk_widget_hide (widget); + } } - - if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) - g_warning ("Unable to set state for menu which doesn't exist:\n%s", - path); } void diff --git a/app/gui/menus.h b/app/gui/menus.h index 02b2e1cce6..079a73ea65 100644 --- a/app/gui/menus.h +++ b/app/gui/menus.h @@ -33,34 +33,43 @@ struct _GimpItemFactoryEntry }; -void menus_init (Gimp *gimp); -void menus_exit (Gimp *gimp); -void menus_restore (Gimp *gimp); +void menus_init (Gimp *gimp); +void menus_exit (Gimp *gimp); +void menus_restore (Gimp *gimp); -GtkItemFactory * menus_get_toolbox_factory (void); -GtkItemFactory * menus_get_image_factory (void); -GtkItemFactory * menus_get_load_factory (void); -GtkItemFactory * menus_get_save_factory (void); -GtkItemFactory * menus_get_layers_factory (void); -GtkItemFactory * menus_get_channels_factory (void); -GtkItemFactory * menus_get_paths_factory (void); -GtkItemFactory * menus_get_dialogs_factory (void); -GtkItemFactory * menus_get_brushes_factory (void); -GtkItemFactory * menus_get_patterns_factory (void); -GtkItemFactory * menus_get_gradients_factory (void); -GtkItemFactory * menus_get_palettes_factory (void); -GtkItemFactory * menus_get_buffers_factory (void); -GtkItemFactory * menus_get_documents_factory (void); +GtkItemFactory * menus_get_toolbox_factory (void); +GtkItemFactory * menus_get_image_factory (void); +GtkItemFactory * menus_get_load_factory (void); +GtkItemFactory * menus_get_save_factory (void); +GtkItemFactory * menus_get_layers_factory (void); +GtkItemFactory * menus_get_channels_factory (void); +GtkItemFactory * menus_get_paths_factory (void); +GtkItemFactory * menus_get_dialogs_factory (void); +GtkItemFactory * menus_get_brushes_factory (void); +GtkItemFactory * menus_get_patterns_factory (void); +GtkItemFactory * menus_get_gradient_editor_factory (void); +GtkItemFactory * menus_get_gradients_factory (void); +GtkItemFactory * menus_get_palettes_factory (void); +GtkItemFactory * menus_get_buffers_factory (void); +GtkItemFactory * menus_get_documents_factory (void); void menus_create_item_from_full_path (GimpItemFactoryEntry *entry, gchar *domain_name, gpointer callback_data); +void menus_set_active (gchar *path, + gboolean state); +void menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label); +void menus_set_label (gchar *path, + const gchar *label); void menus_set_sensitive (gchar *path, gboolean sensitive); -void menus_set_state (gchar *path, - gboolean state); +void menus_set_visible (gchar *path, + gboolean visible); + void menus_destroy (gchar *path); diff --git a/app/gui/test-commands.c b/app/gui/test-commands.c index c0e3ad349f..6f4ddde6d2 100644 --- a/app/gui/test-commands.c +++ b/app/gui/test-commands.c @@ -23,9 +23,7 @@ #include "libgimpmath/gimpmath.h" #include "libgimpwidgets/gimpwidgets.h" -#include "core/core-types.h" -#include "tools/tools-types.h" -#include "widgets/widgets-types.h" +#include "gui-types.h" #include "core/gimp.h" #include "core/gimpchannel.h" @@ -50,7 +48,6 @@ #include "tools/tool_manager.h" #include "dialogs.h" -#include "gradient-editor.h" #include "gimprc.h" diff --git a/app/menus/menus.c b/app/menus/menus.c index 80a43e691d..59fe3ac03b 100644 --- a/app/menus/menus.c +++ b/app/menus/menus.c @@ -53,6 +53,7 @@ #include "documents-commands.h" #include "edit-commands.h" #include "file-commands.h" +#include "gradient-editor-commands.h" #include "gradients-commands.h" #include "image-commands.h" #include "layers-commands.h" @@ -1446,6 +1447,324 @@ static GimpItemFactoryEntry patterns_entries[] = }; +/***** *****/ + +static GimpItemFactoryEntry gradient_editor_entries[] = +{ + { { N_("/Left Endpoint's Color..."), NULL, + gradient_editor_left_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Left Color From/Left Neighbor's Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/FG Color"), NULL, + gradient_editor_load_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/BG Color"), NULL, + gradient_editor_load_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Left Color From/---"), + + { { "/Load Left Color From/01", NULL, + gradient_editor_load_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/02", NULL, + gradient_editor_load_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/03", NULL, + gradient_editor_load_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/04", NULL, + gradient_editor_load_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/05", NULL, + gradient_editor_load_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/06", NULL, + gradient_editor_load_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/07", NULL, + gradient_editor_load_left_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/08", NULL, + gradient_editor_load_left_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/09", NULL, + gradient_editor_load_left_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/10", NULL, + gradient_editor_load_left_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Left Color To")), + + { { "/Save Left Color To/01", NULL, + gradient_editor_save_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/02", NULL, + gradient_editor_save_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/03", NULL, + gradient_editor_save_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/04", NULL, + gradient_editor_save_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/05", NULL, + gradient_editor_save_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/06", NULL, + gradient_editor_save_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/07", NULL, + gradient_editor_save_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/08", NULL, + gradient_editor_save_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/09", NULL, + gradient_editor_save_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/10", NULL, + gradient_editor_save_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Right Endpoint's Color..."), NULL, + gradient_editor_right_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Right Color From/Right Neighbor's Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/FG Color"), NULL, + gradient_editor_load_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/BG Color"), NULL, + gradient_editor_load_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Right Color From/---"), + + { { "/Load Right Color From/01", NULL, + gradient_editor_load_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/02", NULL, + gradient_editor_load_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/03", NULL, + gradient_editor_load_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/04", NULL, + gradient_editor_load_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/05", NULL, + gradient_editor_load_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/06", NULL, + gradient_editor_load_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/07", NULL, + gradient_editor_load_right_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/08", NULL, + gradient_editor_load_right_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/09", NULL, + gradient_editor_load_right_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/10", NULL, + gradient_editor_load_right_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Right Color To")), + + { { "/Save Right Color To/01", NULL, + gradient_editor_save_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/02", NULL, + gradient_editor_save_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/03", NULL, + gradient_editor_save_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/04", NULL, + gradient_editor_save_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/05", NULL, + gradient_editor_save_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/06", NULL, + gradient_editor_save_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/07", NULL, + gradient_editor_save_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/08", NULL, + gradient_editor_save_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/09", NULL, + gradient_editor_save_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/10", NULL, + gradient_editor_save_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/blendingfunction/Linear"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_LINEAR, "" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Curved"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_CURVED, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Sinusodial"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SINE, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (increasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_INCREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (decreasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_DECREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/(Varies)"), NULL, NULL, + 0, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + + { { N_("/coloringtype/RGB"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_RGB, "" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (counter-clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CCW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/(Varies)"), NULL, NULL, + 0, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { "/flip", "F", + gradient_editor_flip_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/replicate", "R", + gradient_editor_replicate_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splitmidpoint", "S", + gradient_editor_split_midpoint_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splituniformly", "U", + gradient_editor_split_uniformly_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/delete", "D", + gradient_editor_delete_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/recenter", "C", + gradient_editor_recenter_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/redistribute", "C", + gradient_editor_redistribute_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Blend Endpoints' Colors"), "B", + gradient_editor_blend_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Blend Endpoints' Opacity"), "B", + gradient_editor_blend_opacity_cmd_callback, 0 }, + NULL, + NULL, NULL }, +}; + + /***** *****/ static GimpItemFactoryEntry gradients_entries[] = @@ -1601,20 +1920,21 @@ static GimpItemFactoryEntry documents_entries[] = static gboolean menus_initialized = FALSE; -static GtkItemFactory *toolbox_factory = NULL; -static GtkItemFactory *image_factory = NULL; -static GtkItemFactory *load_factory = NULL; -static GtkItemFactory *save_factory = NULL; -static GtkItemFactory *layers_factory = NULL; -static GtkItemFactory *channels_factory = NULL; -static GtkItemFactory *paths_factory = NULL; -static GtkItemFactory *dialogs_factory = NULL; -static GtkItemFactory *brushes_factory = NULL; -static GtkItemFactory *patterns_factory = NULL; -static GtkItemFactory *gradients_factory = NULL; -static GtkItemFactory *palettes_factory = NULL; -static GtkItemFactory *buffers_factory = NULL; -static GtkItemFactory *documents_factory = NULL; +static GtkItemFactory *toolbox_factory = NULL; +static GtkItemFactory *image_factory = NULL; +static GtkItemFactory *load_factory = NULL; +static GtkItemFactory *save_factory = NULL; +static GtkItemFactory *layers_factory = NULL; +static GtkItemFactory *channels_factory = NULL; +static GtkItemFactory *paths_factory = NULL; +static GtkItemFactory *dialogs_factory = NULL; +static GtkItemFactory *brushes_factory = NULL; +static GtkItemFactory *patterns_factory = NULL; +static GtkItemFactory *gradient_editor_factory = NULL; +static GtkItemFactory *gradients_factory = NULL; +static GtkItemFactory *palettes_factory = NULL; +static GtkItemFactory *buffers_factory = NULL; +static GtkItemFactory *documents_factory = NULL; /* public functions */ @@ -1760,6 +2080,13 @@ menus_init (Gimp *gimp) gimp, FALSE); + gradient_editor_factory = menus_item_factory_new (GTK_TYPE_MENU, + "", "gradient_editor", + G_N_ELEMENTS (gradient_editor_entries), + gradient_editor_entries, + gimp, + FALSE); + gradients_factory = menus_item_factory_new (GTK_TYPE_MENU, "", "gradients", G_N_ELEMENTS (gradients_entries), @@ -1931,6 +2258,12 @@ menus_exit (Gimp *gimp) patterns_factory = NULL; } + if (gradient_editor_factory) + { + g_object_unref (G_OBJECT (gradient_editor_factory)); + gradient_editor_factory = NULL; + } + if (gradients_factory) { g_object_unref (G_OBJECT (gradients_factory)); @@ -2205,6 +2538,12 @@ menus_get_patterns_factory (void) return patterns_factory; } +GtkItemFactory * +menus_get_gradient_editor_factory (void) +{ + return gradient_editor_factory; +} + GtkItemFactory * menus_get_gradients_factory (void) { @@ -2264,6 +2603,222 @@ menus_create_item_from_full_path (GimpItemFactoryEntry *entry, menus_create_item (item_factory, entry, callback_data, 2, TRUE, FALSE); } +void +menus_set_active (gchar *path, + gboolean active) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), active); + else + widget = NULL; + } + + if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) + g_warning ("Unable to set \"active\" for menu which doesn't exist:\n%s", + path); +} + +void +menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget; + GtkWidget *preview = NULL; + GtkWidget *label = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (color != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + +#define COLOR_BOX_WIDTH 24 +#define COLOR_BOX_HEIGHT 16 + + if (! ifactory) + return; + + widget = gtk_item_factory_get_widget (ifactory, path); + + if (! widget) + return; + + if (GTK_IS_HBOX (GTK_BIN (widget)->child)) + { + preview = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "preview"); + label = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "label"); + } + else if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + GtkWidget *hbox; + + label = GTK_BIN (widget)->child; + + g_object_ref (G_OBJECT (label)); + + gtk_container_remove (GTK_CONTAINER (widget), label); + + hbox = gtk_hbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (widget), hbox); + gtk_widget_show (hbox); + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (preview), + COLOR_BOX_WIDTH, COLOR_BOX_HEIGHT); + gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0); + gtk_widget_show (preview); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + g_object_unref (G_OBJECT (label)); + + g_object_set_data (G_OBJECT (hbox), "preview", preview); + g_object_set_data (G_OBJECT (hbox), "label", label); + } + + if (preview) + { + guchar rows[3][COLOR_BOX_WIDTH * 3]; + gint x, y; + gint r0, g0, b0; + gint r1, g1, b1; + guchar *p0, *p1, *p2; + + /* Fill rows */ + + r0 = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.0; + r1 = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + g0 = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.0; + g1 = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + b0 = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.0; + b1 = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + p0 = rows[0]; + p1 = rows[1]; + p2 = rows[2]; + + for (x = 0; x < COLOR_BOX_WIDTH; x++) + { + if ((x == 0) || (x == (COLOR_BOX_WIDTH - 1))) + { + *p0++ = 0; + *p0++ = 0; + *p0++ = 0; + + *p1++ = 0; + *p1++ = 0; + *p1++ = 0; + } + else if ((x / GIMP_CHECK_SIZE) & 1) + { + *p0++ = r1; + *p0++ = g1; + *p0++ = b1; + + *p1++ = r0; + *p1++ = g0; + *p1++ = b0; + } + else + { + *p0++ = r0; + *p0++ = g0; + *p0++ = b0; + + *p1++ = r1; + *p1++ = g1; + *p1++ = b1; + } + + *p2++ = 0; + *p2++ = 0; + *p2++ = 0; + } + + /* Fill preview */ + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, 0, COLOR_BOX_WIDTH); + + for (y = 1; y < (COLOR_BOX_HEIGHT - 1); y++) + if ((y / GIMP_CHECK_SIZE) & 1) + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[1], + 0, y, COLOR_BOX_WIDTH); + else + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[0], + 0, y, COLOR_BOX_WIDTH); + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, y, COLOR_BOX_WIDTH); + } + + if (label && set_label) + { + gchar *str; + + str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), + color->r, color->g, color->b, color->a); + + gtk_label_set_text (GTK_LABEL (label), str); + + g_free (str); + } + +#undef COLOR_BOX_WIDTH +#undef COLOR_BOX_HEIGHT +} + +void +menus_set_label (gchar *path, + const gchar *label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (label != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget) + { + if (GTK_IS_MENU (widget)) + { + widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); + } + + if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), label); + } + } + } +} + void menus_set_sensitive (gchar *path, gboolean sensitive) @@ -2290,11 +2845,11 @@ menus_set_sensitive (gchar *path, } void -menus_set_state (gchar *path, - gboolean state) +menus_set_visible (gchar *path, + gboolean visible) { GtkItemFactory *ifactory; - GtkWidget *widget = NULL; + GtkWidget *widget; g_return_if_fail (path != NULL); g_return_if_fail (menus_initialized); @@ -2305,15 +2860,14 @@ menus_set_state (gchar *path, { widget = gtk_item_factory_get_widget (ifactory, path); - if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), state); - else - widget = NULL; + if (widget) + { + if (visible) + gtk_widget_show (widget); + else + gtk_widget_hide (widget); + } } - - if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) - g_warning ("Unable to set state for menu which doesn't exist:\n%s", - path); } void diff --git a/app/menus/menus.h b/app/menus/menus.h index 02b2e1cce6..079a73ea65 100644 --- a/app/menus/menus.h +++ b/app/menus/menus.h @@ -33,34 +33,43 @@ struct _GimpItemFactoryEntry }; -void menus_init (Gimp *gimp); -void menus_exit (Gimp *gimp); -void menus_restore (Gimp *gimp); +void menus_init (Gimp *gimp); +void menus_exit (Gimp *gimp); +void menus_restore (Gimp *gimp); -GtkItemFactory * menus_get_toolbox_factory (void); -GtkItemFactory * menus_get_image_factory (void); -GtkItemFactory * menus_get_load_factory (void); -GtkItemFactory * menus_get_save_factory (void); -GtkItemFactory * menus_get_layers_factory (void); -GtkItemFactory * menus_get_channels_factory (void); -GtkItemFactory * menus_get_paths_factory (void); -GtkItemFactory * menus_get_dialogs_factory (void); -GtkItemFactory * menus_get_brushes_factory (void); -GtkItemFactory * menus_get_patterns_factory (void); -GtkItemFactory * menus_get_gradients_factory (void); -GtkItemFactory * menus_get_palettes_factory (void); -GtkItemFactory * menus_get_buffers_factory (void); -GtkItemFactory * menus_get_documents_factory (void); +GtkItemFactory * menus_get_toolbox_factory (void); +GtkItemFactory * menus_get_image_factory (void); +GtkItemFactory * menus_get_load_factory (void); +GtkItemFactory * menus_get_save_factory (void); +GtkItemFactory * menus_get_layers_factory (void); +GtkItemFactory * menus_get_channels_factory (void); +GtkItemFactory * menus_get_paths_factory (void); +GtkItemFactory * menus_get_dialogs_factory (void); +GtkItemFactory * menus_get_brushes_factory (void); +GtkItemFactory * menus_get_patterns_factory (void); +GtkItemFactory * menus_get_gradient_editor_factory (void); +GtkItemFactory * menus_get_gradients_factory (void); +GtkItemFactory * menus_get_palettes_factory (void); +GtkItemFactory * menus_get_buffers_factory (void); +GtkItemFactory * menus_get_documents_factory (void); void menus_create_item_from_full_path (GimpItemFactoryEntry *entry, gchar *domain_name, gpointer callback_data); +void menus_set_active (gchar *path, + gboolean state); +void menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label); +void menus_set_label (gchar *path, + const gchar *label); void menus_set_sensitive (gchar *path, gboolean sensitive); -void menus_set_state (gchar *path, - gboolean state); +void menus_set_visible (gchar *path, + gboolean visible); + void menus_destroy (gchar *path); diff --git a/app/widgets/gimpdock.c b/app/widgets/gimpdock.c index 3d0ce6593c..4a3d758a76 100644 --- a/app/widgets/gimpdock.c +++ b/app/widgets/gimpdock.c @@ -185,6 +185,9 @@ gimp_dock_style_set (GtkWidget *widget, GList *list; gint separator_height; + if (GTK_WIDGET_CLASS (parent_class)->style_set) + GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); + gtk_widget_style_get (widget, "separator_height", &separator_height, NULL); diff --git a/app/widgets/gimpgradienteditor.c b/app/widgets/gimpgradienteditor.c index 79d022178b..ceca3d9882 100644 --- a/app/widgets/gimpgradienteditor.c +++ b/app/widgets/gimpgradienteditor.c @@ -72,10 +72,9 @@ #include "widgets/gimpdnd.h" -#include "color-notebook.h" #include "gradient-editor.h" +#include "gradient-editor-commands.h" -#include "errors.h" #include "gimprc.h" #include "libgimp/gimpintl.h" @@ -90,11 +89,6 @@ #define GRAD_PREVIEW_HEIGHT 64 #define GRAD_CONTROL_HEIGHT 10 -#define GRAD_COLOR_BOX_WIDTH 24 -#define GRAD_COLOR_BOX_HEIGHT 16 - -#define GRAD_NUM_COLORS 10 - #define GRAD_MOVE_TIME 150 /* ms between mouse click and detection of movement in gradient control */ @@ -114,179 +108,52 @@ GDK_BUTTON1_MOTION_MASK) -enum -{ - GRAD_UPDATE_GRADIENT = 1 << 0, - GRAD_UPDATE_PREVIEW = 1 << 1, - GRAD_UPDATE_CONTROL = 1 << 2, - GRAD_RESET_CONTROL = 1 << 3 -}; +/* local function prototypes */ -/* Gradient editor type */ +static void gradient_editor_gradient_changed (GimpContext *context, + GimpGradient *gradient, + GradientEditor *editor); +static void gradient_editor_close_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_name_activate (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_name_focus_out (GtkWidget *widget, + GdkEvent *event, + GradientEditor *editor); +static void gradient_editor_drop_gradient (GtkWidget *widget, + GimpViewable *viewable, + gpointer data); +static void gradient_editor_scrollbar_update (GtkAdjustment *adjustment, + GradientEditor *editor); +static void gradient_editor_zoom_all_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_zoom_out_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_zoom_in_callback (GtkWidget *widget, + GradientEditor *editor); +static void gradient_editor_instant_update_update (GtkWidget *widget, + GradientEditor *editor); -typedef enum -{ - GRAD_DRAG_NONE = 0, - GRAD_DRAG_LEFT, - GRAD_DRAG_MIDDLE, - GRAD_DRAG_ALL -} control_drag_mode_t; +static void gradient_editor_set_hint (GradientEditor *editor, + const gchar *str); -struct _GradientEditor -{ - GtkWidget *shell; - - GtkWidget *name; - - GtkWidget *hint_label; - GtkWidget *scrollbar; - GtkWidget *preview; - GtkWidget *control; - - GimpContext *context; - - /* Zoom and scrollbar */ - guint zoom_factor; - GtkObject *scroll_data; - - /* Instant update */ - gboolean instant_update; - - /* Gradient preview */ - guchar *preview_rows[2]; /* For caching redraw info */ - gint preview_last_x; - gboolean preview_button_down; - - /* Gradient control */ - GdkPixmap *control_pixmap; - GimpGradientSegment *control_drag_segment; /* Segment which is being dragged */ - GimpGradientSegment *control_sel_l; /* Left segment of selection */ - GimpGradientSegment *control_sel_r; /* Right segment of selection */ - control_drag_mode_t control_drag_mode; /* What is being dragged? */ - guint32 control_click_time; /* Time when mouse was pressed */ - gboolean control_compress; /* Compressing/expanding handles */ - gint control_last_x; /* Last mouse position when dragging */ - gdouble control_last_gx; /* Last position (wrt gradient) when dragging */ - gdouble control_orig_pos; /* Original click position when dragging */ - - GtkWidget *control_main_popup; /* Popup menu */ - GtkWidget *control_blending_label; /* Blending function label */ - GtkWidget *control_coloring_label; /* Coloring type label */ - GtkWidget *control_split_m_label; /* Split at midpoint label */ - GtkWidget *control_split_u_label; /* Split uniformly label */ - GtkWidget *control_delete_menu_item; /* Delete menu item */ - GtkWidget *control_delete_label; /* Delete label */ - GtkWidget *control_recenter_label; /* Re-center label */ - GtkWidget *control_redistribute_label; /* Re-distribute label */ - GtkWidget *control_flip_label; /* Flip label */ - GtkWidget *control_replicate_label; /* Replicate label */ - GtkWidget *control_blend_colors_menu_item; /* Blend colors menu item */ - GtkWidget *control_blend_opacity_menu_item; /* Blend opacity menu item */ - GtkWidget *control_left_load_popup; /* Left endpoint load menu */ - GtkWidget *control_left_save_popup; /* Left endpoint save menu */ - GtkWidget *control_right_load_popup; /* Right endpoint load menu */ - GtkWidget *control_right_save_popup; /* Right endpoint save menu */ - GtkWidget *control_blending_popup; /* Blending function menu */ - GtkWidget *control_coloring_popup; /* Coloring type menu */ - GtkWidget *control_sel_ops_popup; /* Selection ops menu */ - - GtkAccelGroup *accel_group; - - /* Blending and coloring menus */ - GtkWidget *control_blending_items[5 + 1]; /* Add 1 for the "Varies" item */ - GtkWidget *control_coloring_items[3 + 1]; - - /* Split uniformly dialog */ - gint split_parts; - - /* Replicate dialog */ - gint replicate_times; - - /* Saved colors */ - GimpRGB saved_colors[GRAD_NUM_COLORS]; - - GtkWidget *left_load_color_boxes[GRAD_NUM_COLORS + 3]; - GtkWidget *left_load_labels[GRAD_NUM_COLORS + 3]; - - GtkWidget *left_save_color_boxes[GRAD_NUM_COLORS]; - GtkWidget *left_save_labels[GRAD_NUM_COLORS]; - - GtkWidget *right_load_color_boxes[GRAD_NUM_COLORS + 3]; - GtkWidget *right_load_labels[GRAD_NUM_COLORS + 3]; - - GtkWidget *right_save_color_boxes[GRAD_NUM_COLORS]; - GtkWidget *right_save_labels[GRAD_NUM_COLORS]; - - /* Color dialogs */ - GtkWidget *left_color_preview; - GimpGradientSegment *left_saved_segments; - gboolean left_saved_dirty; - - GtkWidget *right_color_preview; - GimpGradientSegment *right_saved_segments; - gboolean right_saved_dirty; -}; - - -/***** Local functions *****/ - -static void gradient_editor_name_activate (GtkWidget *widget, - GradientEditor *gradient_editor); -static void gradient_editor_name_focus_out (GtkWidget *widget, - GdkEvent *event, - GradientEditor *gradient_editor); -static void gradient_editor_drop_gradient (GtkWidget *widget, - GimpViewable *viewable, - gpointer data); -static void gradient_editor_gradient_changed (GimpContext *context, - GimpGradient *gradient, - GradientEditor *gradient_editor); - -/* Gradient editor functions */ - -static void ed_update_editor (GradientEditor *gradient_editor, - gint flags); - -static void ed_set_hint (GradientEditor *gradient_editor, - gchar *str); - -static void ed_initialize_saved_colors (GradientEditor *gradient_editor); - -/* Main dialog button callbacks & functions */ - -static void ed_close_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Zoom, scrollbar & instant update callbacks */ - -static void ed_scrollbar_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor); -static void ed_zoom_all_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_zoom_out_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_zoom_in_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void ed_instant_update_update (GtkWidget *widget, - GradientEditor *gradient_editor); - /* Gradient preview functions */ static gint preview_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor); -static void preview_set_hint (GradientEditor *gradient_editor, + GradientEditor *editor); +static void preview_set_hint (GradientEditor *editor, gint x); -static void preview_set_foreground (GradientEditor *gradient_editor, +static void preview_set_foreground (GradientEditor *editor, gint x); -static void preview_set_background (GradientEditor *gradient_editor, +static void preview_set_background (GradientEditor *editor, gint x); -static void preview_update (GradientEditor *gradient_editor, +static void preview_update (GradientEditor *editor, gboolean recalculate); -static void preview_fill_image (GradientEditor *gradient_editor, +static void preview_fill_image (GradientEditor *editor, gint width, gint height, gdouble left, @@ -296,27 +163,27 @@ static void preview_fill_image (GradientEditor *gradient_edi static gint control_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor); -static void control_do_hint (GradientEditor *gradient_editor, + GradientEditor *editor); +static void control_do_hint (GradientEditor *editor, gint x, gint y); -static void control_button_press (GradientEditor *gradient_editor, +static void control_button_press (GradientEditor *editor, gint x, gint y, guint button, guint state); -static gboolean control_point_in_handle (GradientEditor *gradient_editor, +static gboolean control_point_in_handle (GradientEditor *editor, GimpGradient *gradient, gint x, gint y, GimpGradientSegment *seg, - control_drag_mode_t handle); -static void control_select_single_segment (GradientEditor *gradient_editor, + GradientEditorDragMode handle); +static void control_select_single_segment (GradientEditor *editor, GimpGradientSegment *seg); -static void control_extend_selection (GradientEditor *gradient_editor, +static void control_extend_selection (GradientEditor *editor, GimpGradientSegment *seg, gdouble pos); -static void control_motion (GradientEditor *gradient_editor, +static void control_motion (GradientEditor *editor, GimpGradient *gradient, gint x); @@ -329,28 +196,28 @@ static void control_compress_range (GimpGradientSegment *range_l, gdouble new_l, gdouble new_r); -static double control_move (GradientEditor *gradient_editor, +static double control_move (GradientEditor *editor, GimpGradientSegment *range_l, GimpGradientSegment *range_r, gdouble delta); /* Control update/redraw functions */ -static void control_update (GradientEditor *gradient_editor, +static void control_update (GradientEditor *editor, GimpGradient *gradient, gboolean recalculate); -static void control_draw (GradientEditor *gradient_editor, +static void control_draw (GradientEditor *editor, GimpGradient *gradient, GdkPixmap *pixmap, gint width, gint height, gdouble left, gdouble right); -static void control_draw_normal_handle (GradientEditor *gradient_editor, +static void control_draw_normal_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height); -static void control_draw_middle_handle (GradientEditor *gradient_editor, +static void control_draw_middle_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height); @@ -360,162 +227,25 @@ static void control_draw_handle (GdkPixmap *pixmap, gint xpos, gint height); -static gint control_calc_p_pos (GradientEditor *gradient_editor, +static gint control_calc_p_pos (GradientEditor *editor, gdouble pos); -static gdouble control_calc_g_pos (GradientEditor *gradient_editor, +static gdouble control_calc_g_pos (GradientEditor *editor, gint pos); -/* Control popup functions */ - -static void cpopup_create_main_menu (GradientEditor *gradient_editor); -static void cpopup_do_popup (GradientEditor *gradient_editor); -static GtkWidget * cpopup_create_color_item (GtkWidget **color_box, - GtkWidget **label); -static GtkWidget * cpopup_create_menu_item_with_label (gchar *str, - GtkWidget **label); - -static void cpopup_adjust_menus (GradientEditor *gradient_editor); -static void cpopup_adjust_blending_menu (GradientEditor *gradient_editor); -static void cpopup_adjust_coloring_menu (GradientEditor *gradient_editor); -static void cpopup_check_selection_params (GradientEditor *gradient_editor, - gint *equal_blending, - gint *equal_coloring); - -static void cpopup_render_color_box (GtkPreview *preview, - GimpRGB *color); - -static GtkWidget * cpopup_create_load_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - gchar *label1, - gchar *label2, - GtkSignalFunc callback, - gchar accel_key_0, - guint8 accel_mods_0, - gchar accel_key_1, - guint8 accel_mods_1, - gchar accel_key_2, - guint8 accel_mods_2); -static GtkWidget * cpopup_create_save_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - GtkSignalFunc callback); - -static void cpopup_update_saved_color (GradientEditor *gradient_editor, - gint n, - GimpRGB *color); - -static void cpopup_load_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_save_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_load_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_save_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static GimpGradientSegment * cpopup_save_selection(GradientEditor *gradient_editor); -static void cpopup_replace_selection (GradientEditor *gradient_editor, - GimpGradientSegment *replace_seg); - -/* ----- */ - -static void cpopup_set_left_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_set_right_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_left_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data); -static void cpopup_right_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data); - -/* ----- */ - -static GtkWidget * cpopup_create_blending_menu (GradientEditor *gradient_editor); -static void cpopup_blending_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static GtkWidget * cpopup_create_coloring_menu (GradientEditor *gradient_editor); -static void cpopup_coloring_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* ----- */ - -static void cpopup_split_midpoint_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_midpoint (GimpGradient *gradient, - GimpGradientSegment *lseg, - GimpGradientSegment **newl, - GimpGradientSegment **newr); - -static void cpopup_split_uniform_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_split_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_split_uniform (GimpGradient *gradient, - GimpGradientSegment *lseg, - gint parts, - GimpGradientSegment **newl, - GimpGradientSegment **newr); - -static void cpopup_delete_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_recenter_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_redistribute_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Control popup -> Selection operations functions */ - -static GtkWidget * cpopup_create_sel_ops_menu (GradientEditor *gradient_editor); - -static void cpopup_flip_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_replicate_scale_update (GtkAdjustment *widget, - GradientEditor *gradient_editor); -static void cpopup_do_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_replicate_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor); - -static void cpopup_blend_colors (GtkWidget *widget, - GradientEditor *gradient_editor); -static void cpopup_blend_opacity (GtkWidget *widget, - GradientEditor *gradient_editor); - -/* Blend function */ - -static void cpopup_blend_endpoints (GradientEditor *gradient_editor, - GimpRGB *left, - GimpRGB *right, - gint blend_colors, - gint blend_opacity); - /* Segment functions */ static void seg_get_closest_handle (GimpGradient *grad, gdouble pos, GimpGradientSegment **seg, - control_drag_mode_t *handle); + GradientEditorDragMode *handle); -/***** Public gradient editor functions *****/ +/* public functions */ GradientEditor * gradient_editor_new (Gimp *gimp) { - GradientEditor *gradient_editor; + GradientEditor *editor; GtkWidget *main_vbox; GtkWidget *hbox; GtkWidget *vbox; @@ -523,33 +253,32 @@ gradient_editor_new (Gimp *gimp) GtkWidget *button; GtkWidget *image; GtkWidget *frame; - gint i; - gradient_editor = g_new (GradientEditor, 1); + editor = g_new (GradientEditor, 1); - gradient_editor->context = gimp_create_context (gimp, NULL, NULL); + editor->context = gimp_create_context (gimp, NULL, NULL); - g_signal_connect (G_OBJECT (gradient_editor->context), "gradient_changed", + g_signal_connect (G_OBJECT (editor->context), "gradient_changed", G_CALLBACK (gradient_editor_gradient_changed), - gradient_editor); + editor); /* Shell and main vbox */ - gradient_editor->shell = + editor->shell = gimp_dialog_new (_("Gradient Editor"), "gradient_editor", gimp_standard_help_func, "dialogs/gradient_editor/gradient_editor.html", GTK_WIN_POS_NONE, FALSE, TRUE, FALSE, - "_delete_event_", ed_close_callback, - gradient_editor, NULL, NULL, FALSE, TRUE, + "_delete_event_", gradient_editor_close_callback, + editor, NULL, NULL, FALSE, TRUE, NULL); main_vbox = gtk_vbox_new (FALSE, 4); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (gradient_editor->shell)->vbox), - main_vbox); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editor->shell)->vbox), + main_vbox); gtk_widget_show (main_vbox); vbox = gtk_vbox_new (FALSE, 1); @@ -557,16 +286,16 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (vbox); /* Gradient's name */ - gradient_editor->name = gtk_entry_new (); - gtk_box_pack_start (GTK_BOX (vbox), gradient_editor->name, FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->name); + editor->name = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (vbox), editor->name, FALSE, FALSE, 0); + gtk_widget_show (editor->name); - g_signal_connect (G_OBJECT (gradient_editor->name), "activate", + g_signal_connect (G_OBJECT (editor->name), "activate", G_CALLBACK (gradient_editor_name_activate), - gradient_editor); - g_signal_connect (G_OBJECT (gradient_editor->name), "focus_out_event", + editor); + g_signal_connect (G_OBJECT (editor->name), "focus_out_event", G_CALLBACK (gradient_editor_name_focus_out), - gradient_editor); + editor); /* Frame for gradient preview and gradient control */ frame = gtk_frame_new (NULL); @@ -579,120 +308,82 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (vbox2); /* Gradient preview */ - gradient_editor->preview_rows[0] = NULL; - gradient_editor->preview_rows[1] = NULL; - gradient_editor->preview_last_x = 0; - gradient_editor->preview_button_down = FALSE; + editor->preview_rows[0] = NULL; + editor->preview_rows[1] = NULL; + editor->preview_last_x = 0; + editor->preview_button_down = FALSE; - gradient_editor->preview = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_set_dither (GTK_PREVIEW (gradient_editor->preview), GDK_RGB_DITHER_MAX); - gtk_preview_size (GTK_PREVIEW (gradient_editor->preview), + editor->preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_set_dither (GTK_PREVIEW (editor->preview), GDK_RGB_DITHER_MAX); + gtk_preview_size (GTK_PREVIEW (editor->preview), GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT); /* Enable auto-resizing of the preview but ensure a minimal size */ - gtk_widget_set_usize (gradient_editor->preview, + gtk_widget_set_usize (editor->preview, GRAD_PREVIEW_WIDTH, GRAD_PREVIEW_HEIGHT); - gtk_preview_set_expand (GTK_PREVIEW (gradient_editor->preview), TRUE); + gtk_preview_set_expand (GTK_PREVIEW (editor->preview), TRUE); - gtk_widget_set_events (gradient_editor->preview, GRAD_PREVIEW_EVENT_MASK); + gtk_widget_set_events (editor->preview, GRAD_PREVIEW_EVENT_MASK); - g_signal_connect (G_OBJECT (gradient_editor->preview), "event", + g_signal_connect (G_OBJECT (editor->preview), "event", G_CALLBACK (preview_events), - gradient_editor); + editor); - gimp_gtk_drag_dest_set_by_type (gradient_editor->preview, + gimp_gtk_drag_dest_set_by_type (editor->preview, GTK_DEST_DEFAULT_ALL, GIMP_TYPE_GRADIENT, GDK_ACTION_COPY); - gimp_dnd_viewable_dest_set (GTK_WIDGET (gradient_editor->preview), + gimp_dnd_viewable_dest_set (GTK_WIDGET (editor->preview), GIMP_TYPE_GRADIENT, gradient_editor_drop_gradient, - gradient_editor); + editor); - gtk_box_pack_start (GTK_BOX (vbox2), gradient_editor->preview, TRUE, TRUE, 0); - gtk_widget_show (gradient_editor->preview); + gtk_box_pack_start (GTK_BOX (vbox2), editor->preview, TRUE, TRUE, 0); + gtk_widget_show (editor->preview); /* Gradient control */ - gradient_editor->control_pixmap = NULL; - gradient_editor->control_drag_segment = NULL; - gradient_editor->control_sel_l = NULL; - gradient_editor->control_sel_r = NULL; - gradient_editor->control_drag_mode = GRAD_DRAG_NONE; - gradient_editor->control_click_time = 0; - gradient_editor->control_compress = FALSE; - gradient_editor->control_last_x = 0; - gradient_editor->control_last_gx = 0.0; - gradient_editor->control_orig_pos = 0.0; - gradient_editor->control_main_popup = NULL; - gradient_editor->control_blending_label = NULL; - gradient_editor->control_coloring_label = NULL; - gradient_editor->control_split_m_label = NULL; - gradient_editor->control_split_u_label = NULL; - gradient_editor->control_delete_menu_item = NULL; - gradient_editor->control_delete_label = NULL; - gradient_editor->control_recenter_label = NULL; - gradient_editor->control_redistribute_label = NULL; - gradient_editor->control_flip_label = NULL; - gradient_editor->control_replicate_label = NULL; - gradient_editor->control_blend_colors_menu_item = NULL; - gradient_editor->control_blend_opacity_menu_item = NULL; - gradient_editor->control_left_load_popup = NULL; - gradient_editor->control_left_save_popup = NULL; - gradient_editor->control_right_load_popup = NULL; - gradient_editor->control_right_save_popup = NULL; - gradient_editor->control_blending_popup = NULL; - gradient_editor->control_coloring_popup = NULL; - gradient_editor->control_sel_ops_popup = NULL; + editor->control_pixmap = NULL; + editor->control_drag_segment = NULL; + editor->control_sel_l = NULL; + editor->control_sel_r = NULL; + editor->control_drag_mode = GRAD_DRAG_NONE; + editor->control_click_time = 0; + editor->control_compress = FALSE; + editor->control_last_x = 0; + editor->control_last_gx = 0.0; + editor->control_orig_pos = 0.0; - gradient_editor->accel_group = NULL; - - for (i = 0; - i < (sizeof (gradient_editor->control_blending_items) / - sizeof (gradient_editor->control_blending_items[0])); - i++) - gradient_editor->control_blending_items[i] = NULL; - - for (i = 0; - i < (sizeof (gradient_editor->control_coloring_items) / - sizeof (gradient_editor->control_coloring_items[0])); - i++) - gradient_editor->control_coloring_items[i] = NULL; - - gradient_editor->control = gtk_drawing_area_new (); - gtk_drawing_area_size (GTK_DRAWING_AREA (gradient_editor->control), + editor->control = gtk_drawing_area_new (); + gtk_drawing_area_size (GTK_DRAWING_AREA (editor->control), GRAD_PREVIEW_WIDTH, GRAD_CONTROL_HEIGHT); - gtk_widget_set_events (gradient_editor->control, GRAD_CONTROL_EVENT_MASK); - gtk_box_pack_start (GTK_BOX (vbox2), gradient_editor->control, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->control); + gtk_widget_set_events (editor->control, GRAD_CONTROL_EVENT_MASK); + gtk_box_pack_start (GTK_BOX (vbox2), editor->control, FALSE, FALSE, 0); + gtk_widget_show (editor->control); - g_signal_connect (G_OBJECT (gradient_editor->control), "event", + g_signal_connect (G_OBJECT (editor->control), "event", G_CALLBACK (control_events), - gradient_editor); + editor); /* Scrollbar */ - gradient_editor->zoom_factor = 1; + editor->zoom_factor = 1; - gradient_editor->scroll_data = - gtk_adjustment_new (0.0, 0.0, 1.0, - 1.0 * GRAD_SCROLLBAR_STEP_SIZE, - 1.0 * GRAD_SCROLLBAR_PAGE_SIZE, - 1.0); + editor->scroll_data = gtk_adjustment_new (0.0, 0.0, 1.0, + 1.0 * GRAD_SCROLLBAR_STEP_SIZE, + 1.0 * GRAD_SCROLLBAR_PAGE_SIZE, + 1.0); - g_signal_connect (G_OBJECT (gradient_editor->scroll_data), "value_changed", - G_CALLBACK (ed_scrollbar_update), - gradient_editor); - g_signal_connect (G_OBJECT (gradient_editor->scroll_data), "changed", - G_CALLBACK (ed_scrollbar_update), - gradient_editor); + g_signal_connect (G_OBJECT (editor->scroll_data), "value_changed", + G_CALLBACK (gradient_editor_scrollbar_update), + editor); + g_signal_connect (G_OBJECT (editor->scroll_data), "changed", + G_CALLBACK (gradient_editor_scrollbar_update), + editor); - gradient_editor->scrollbar = - gtk_hscrollbar_new (GTK_ADJUSTMENT (gradient_editor->scroll_data)); - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (editor->scroll_data)); + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_CONTINUOUS); - gtk_box_pack_start (GTK_BOX (vbox), gradient_editor->scrollbar, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->scrollbar); + gtk_box_pack_start (GTK_BOX (vbox), editor->scrollbar, FALSE, FALSE, 0); + gtk_widget_show (editor->scrollbar); /* Horizontal box for zoom controls and instant update toggle */ hbox = gtk_hbox_new (FALSE, 4); @@ -710,8 +401,8 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (image); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_out_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_out_callback), + editor); button = gtk_button_new (); GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT); @@ -723,8 +414,8 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (image); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_in_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_in_callback), + editor); /* Zoom all button */ button = gtk_button_new_with_label (_("Zoom all")); @@ -735,11 +426,11 @@ gradient_editor_new (Gimp *gimp) GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT); g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ed_zoom_all_callback), - gradient_editor); + G_CALLBACK (gradient_editor_zoom_all_callback), + editor); /* Instant update toggle */ - gradient_editor->instant_update = TRUE; + editor->instant_update = TRUE; button = gtk_check_button_new_with_label (_("Instant update")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); @@ -747,35 +438,79 @@ gradient_editor_new (Gimp *gimp) gtk_widget_show (button); g_signal_connect (G_OBJECT (button), "toggled", - G_CALLBACK (ed_instant_update_update), - gradient_editor); + G_CALLBACK (gradient_editor_instant_update_update), + editor); /* Hint bar */ - hbox = GTK_DIALOG (gradient_editor->shell)->action_area; + hbox = GTK_DIALOG (editor->shell)->action_area; gtk_container_set_border_width (GTK_CONTAINER (hbox), 4); gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE); - gradient_editor->hint_label = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (gradient_editor->hint_label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), gradient_editor->hint_label, - FALSE, FALSE, 0); - gtk_widget_show (gradient_editor->hint_label); + editor->hint_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (editor->hint_label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), editor->hint_label, FALSE, FALSE, 0); + gtk_widget_show (editor->hint_label); /* Initialize other data */ - gradient_editor->left_color_preview = NULL; - gradient_editor->left_saved_segments = NULL; - gradient_editor->left_saved_dirty = FALSE; + editor->left_saved_segments = NULL; + editor->left_saved_dirty = FALSE; - gradient_editor->right_color_preview = NULL; - gradient_editor->right_saved_segments = NULL; - gradient_editor->right_saved_dirty = FALSE; + editor->right_saved_segments = NULL; + editor->right_saved_dirty = FALSE; - ed_initialize_saved_colors (gradient_editor); - cpopup_create_main_menu (gradient_editor); + editor->saved_colors[0].r = 0.0; /* Black */ + editor->saved_colors[0].g = 0.0; + editor->saved_colors[0].b = 0.0; + editor->saved_colors[0].a = 1.0; + + editor->saved_colors[1].r = 0.5; /* 50% Gray */ + editor->saved_colors[1].g = 0.5; + editor->saved_colors[1].b = 0.5; + editor->saved_colors[1].a = 1.0; + + editor->saved_colors[2].r = 1.0; /* White */ + editor->saved_colors[2].g = 1.0; + editor->saved_colors[2].b = 1.0; + editor->saved_colors[2].a = 1.0; + + editor->saved_colors[3].r = 0.0; /* Clear */ + editor->saved_colors[3].g = 0.0; + editor->saved_colors[3].b = 0.0; + editor->saved_colors[3].a = 0.0; + + editor->saved_colors[4].r = 1.0; /* Red */ + editor->saved_colors[4].g = 0.0; + editor->saved_colors[4].b = 0.0; + editor->saved_colors[4].a = 1.0; + + editor->saved_colors[5].r = 1.0; /* Yellow */ + editor->saved_colors[5].g = 1.0; + editor->saved_colors[5].b = 0.0; + editor->saved_colors[5].a = 1.0; + + editor->saved_colors[6].r = 0.0; /* Green */ + editor->saved_colors[6].g = 1.0; + editor->saved_colors[6].b = 0.0; + editor->saved_colors[6].a = 1.0; + + editor->saved_colors[7].r = 0.0; /* Cyan */ + editor->saved_colors[7].g = 1.0; + editor->saved_colors[7].b = 1.0; + editor->saved_colors[7].a = 1.0; + + editor->saved_colors[8].r = 0.0; /* Blue */ + editor->saved_colors[8].g = 0.0; + editor->saved_colors[8].b = 1.0; + editor->saved_colors[8].a = 1.0; + + editor->saved_colors[9].r = 1.0; /* Magenta */ + editor->saved_colors[9].g = 0.0; + editor->saved_colors[9].b = 1.0; + editor->saved_colors[9].a = 1.0; if (gimp_container_num_children (gimp->gradient_factory->container)) { - gimp_context_set_gradient (gradient_editor->context, + gimp_context_set_gradient (editor->context, GIMP_GRADIENT (gimp_container_get_child_by_index (gimp->gradient_factory->container, 0))); } else @@ -788,38 +523,80 @@ gradient_editor_new (Gimp *gimp) GIMP_OBJECT (gradient)); } - gtk_widget_show (gradient_editor->shell); + gtk_widget_show (editor->shell); - return gradient_editor; + return editor; } void -gradient_editor_set_gradient (GradientEditor *gradient_editor, +gradient_editor_set_gradient (GradientEditor *editor, GimpGradient *gradient) { - g_return_if_fail (gradient_editor != NULL); + g_return_if_fail (editor != NULL); g_return_if_fail (GIMP_IS_GRADIENT (gradient)); - gimp_context_set_gradient (gradient_editor->context, gradient); + gimp_context_set_gradient (editor->context, gradient); } void -gradient_editor_free (GradientEditor *gradient_editor) +gradient_editor_free (GradientEditor *editor) { - g_return_if_fail (gradient_editor != NULL); + g_return_if_fail (editor != NULL); +} + +void +gradient_editor_update (GradientEditor *editor, + GradientEditorUpdateMask flags) +{ + GimpGradient *gradient; + + gradient = gimp_context_get_gradient (editor->context); + + if (flags & GRAD_UPDATE_GRADIENT) + { + preview_update (editor, TRUE); + } + + if (flags & GRAD_UPDATE_PREVIEW) + preview_update (editor, TRUE); + + if (flags & GRAD_UPDATE_CONTROL) + control_update (editor, gradient, FALSE); + + if (flags & GRAD_RESET_CONTROL) + control_update (editor, gradient, TRUE); } /* private functions */ +static void +gradient_editor_gradient_changed (GimpContext *context, + GimpGradient *gradient, + GradientEditor *editor) +{ + gtk_entry_set_text (GTK_ENTRY (editor->name), + gimp_object_get_name (GIMP_OBJECT (gradient))); + + gradient_editor_update (editor, GRAD_UPDATE_PREVIEW | GRAD_RESET_CONTROL); +} + +static void +gradient_editor_close_callback (GtkWidget *widget, + GradientEditor *editor) +{ + if (GTK_WIDGET_VISIBLE (editor->shell)) + gtk_widget_hide (editor->shell); +} + static void gradient_editor_name_activate (GtkWidget *widget, - GradientEditor *gradient_editor) + GradientEditor *editor) { GimpGradient *gradient; const gchar *entry_text; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); @@ -829,9 +606,9 @@ gradient_editor_name_activate (GtkWidget *widget, static void gradient_editor_name_focus_out (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { - gradient_editor_name_activate (widget, gradient_editor); + gradient_editor_name_activate (widget, editor); } static void @@ -839,182 +616,50 @@ gradient_editor_drop_gradient (GtkWidget *widget, GimpViewable *viewable, gpointer data) { - GradientEditor *gradient_editor; + GradientEditor *editor; - gradient_editor = (GradientEditor *) data; + editor = (GradientEditor *) data; - gradient_editor_set_gradient (gradient_editor, - GIMP_GRADIENT (viewable)); + gradient_editor_set_gradient (editor, GIMP_GRADIENT (viewable)); } static void -gradient_editor_gradient_changed (GimpContext *context, - GimpGradient *gradient, - GradientEditor *gradient_editor) -{ - gtk_entry_set_text (GTK_ENTRY (gradient_editor->name), - gimp_object_get_name (GIMP_OBJECT (gradient))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_PREVIEW | GRAD_RESET_CONTROL); -} - -/*****/ - -static void -ed_update_editor (GradientEditor *gradient_editor, - gint flags) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (flags & GRAD_UPDATE_GRADIENT) - { - preview_update (gradient_editor, TRUE); - } - - if (flags & GRAD_UPDATE_PREVIEW) - preview_update (gradient_editor, TRUE); - - if (flags & GRAD_UPDATE_CONTROL) - control_update (gradient_editor, gradient, FALSE); - - if (flags & GRAD_RESET_CONTROL) - control_update (gradient_editor, gradient, TRUE); -} - -static void -ed_set_hint (GradientEditor *gradient_editor, - gchar *str) -{ - gtk_label_set_text (GTK_LABEL (gradient_editor->hint_label), str); -} - -static void -ed_initialize_saved_colors (GradientEditor *gradient_editor) -{ - gint i; - - for (i = 0; i < (GRAD_NUM_COLORS + 3); i++) - { - gradient_editor->left_load_color_boxes[i] = NULL; - gradient_editor->left_load_labels[i] = NULL; - - gradient_editor->right_load_color_boxes[i] = NULL; - gradient_editor->right_load_labels[i] = NULL; - } - - for (i = 0; i < GRAD_NUM_COLORS; i++) - { - gradient_editor->left_save_color_boxes[i] = NULL; - gradient_editor->left_save_labels[i] = NULL; - - gradient_editor->right_save_color_boxes[i] = NULL; - gradient_editor->right_save_labels[i] = NULL; - } - - gradient_editor->saved_colors[0].r = 0.0; /* Black */ - gradient_editor->saved_colors[0].g = 0.0; - gradient_editor->saved_colors[0].b = 0.0; - gradient_editor->saved_colors[0].a = 1.0; - - gradient_editor->saved_colors[1].r = 0.5; /* 50% Gray */ - gradient_editor->saved_colors[1].g = 0.5; - gradient_editor->saved_colors[1].b = 0.5; - gradient_editor->saved_colors[1].a = 1.0; - - gradient_editor->saved_colors[2].r = 1.0; /* White */ - gradient_editor->saved_colors[2].g = 1.0; - gradient_editor->saved_colors[2].b = 1.0; - gradient_editor->saved_colors[2].a = 1.0; - - gradient_editor->saved_colors[3].r = 0.0; /* Clear */ - gradient_editor->saved_colors[3].g = 0.0; - gradient_editor->saved_colors[3].b = 0.0; - gradient_editor->saved_colors[3].a = 0.0; - - gradient_editor->saved_colors[4].r = 1.0; /* Red */ - gradient_editor->saved_colors[4].g = 0.0; - gradient_editor->saved_colors[4].b = 0.0; - gradient_editor->saved_colors[4].a = 1.0; - - gradient_editor->saved_colors[5].r = 1.0; /* Yellow */ - gradient_editor->saved_colors[5].g = 1.0; - gradient_editor->saved_colors[5].b = 0.0; - gradient_editor->saved_colors[5].a = 1.0; - - gradient_editor->saved_colors[6].r = 0.0; /* Green */ - gradient_editor->saved_colors[6].g = 1.0; - gradient_editor->saved_colors[6].b = 0.0; - gradient_editor->saved_colors[6].a = 1.0; - - gradient_editor->saved_colors[7].r = 0.0; /* Cyan */ - gradient_editor->saved_colors[7].g = 1.0; - gradient_editor->saved_colors[7].b = 1.0; - gradient_editor->saved_colors[7].a = 1.0; - - gradient_editor->saved_colors[8].r = 0.0; /* Blue */ - gradient_editor->saved_colors[8].g = 0.0; - gradient_editor->saved_colors[8].b = 1.0; - gradient_editor->saved_colors[8].a = 1.0; - - gradient_editor->saved_colors[9].r = 1.0; /* Magenta */ - gradient_editor->saved_colors[9].g = 0.0; - gradient_editor->saved_colors[9].b = 1.0; - gradient_editor->saved_colors[9].a = 1.0; -} - - -/***** Main gradient editor dialog callbacks *****/ - -static void -ed_close_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - if (GTK_WIDGET_VISIBLE (gradient_editor->shell)) - gtk_widget_hide (gradient_editor->shell); -} - - -/***** Zoom, scrollbar & instant update callbacks *****/ - -static void -ed_scrollbar_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) +gradient_editor_scrollbar_update (GtkAdjustment *adjustment, + GradientEditor *editor) { gchar *str; str = g_strdup_printf (_("Zoom factor: %d:1 Displaying [%0.6f, %0.6f]"), - gradient_editor->zoom_factor, adjustment->value, + editor->zoom_factor, adjustment->value, adjustment->value + adjustment->page_size); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); - ed_update_editor (gradient_editor, GRAD_UPDATE_PREVIEW | GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_PREVIEW | GRAD_UPDATE_CONTROL); } static void -ed_zoom_all_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_all_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - gradient_editor->zoom_factor = 1; + editor->zoom_factor = 1; adjustment->value = 0.0; adjustment->page_size = 1.0; adjustment->step_increment = 1.0 * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = 1.0 * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_zoom_out_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_out_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; gdouble old_value; @@ -1022,17 +667,17 @@ ed_zoom_out_callback (GtkWidget *widget, gdouble old_page_size; gdouble page_size; - if (gradient_editor->zoom_factor <= 1) + if (editor->zoom_factor <= 1) return; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); old_value = adjustment->value; old_page_size = adjustment->page_size; - gradient_editor->zoom_factor--; + editor->zoom_factor--; - page_size = 1.0 / gradient_editor->zoom_factor; + page_size = 1.0 / editor->zoom_factor; value = old_value - (page_size - old_page_size) / 2.0; if (value < 0.0) @@ -1045,59 +690,67 @@ ed_zoom_out_callback (GtkWidget *widget, adjustment->step_increment = page_size * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = page_size * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_zoom_in_callback (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_zoom_in_callback (GtkWidget *widget, + GradientEditor *editor) { GtkAdjustment *adjustment; gdouble old_value; gdouble old_page_size; gdouble page_size; - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); old_value = adjustment->value; old_page_size = adjustment->page_size; - gradient_editor->zoom_factor++; + editor->zoom_factor++; - page_size = 1.0 / gradient_editor->zoom_factor; + page_size = 1.0 / editor->zoom_factor; adjustment->value = old_value + (old_page_size - page_size) / 2.0; adjustment->page_size = page_size; adjustment->step_increment = page_size * GRAD_SCROLLBAR_STEP_SIZE; adjustment->page_increment = page_size * GRAD_SCROLLBAR_PAGE_SIZE; - gtk_adjustment_changed (GTK_ADJUSTMENT (gradient_editor->scroll_data)); + gtk_adjustment_changed (GTK_ADJUSTMENT (editor->scroll_data)); } static void -ed_instant_update_update (GtkWidget *widget, - GradientEditor *gradient_editor) +gradient_editor_instant_update_update (GtkWidget *widget, + GradientEditor *editor) { if (GTK_TOGGLE_BUTTON (widget)->active) { - gradient_editor->instant_update = TRUE; - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->instant_update = TRUE; + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_CONTINUOUS); } else { - gradient_editor->instant_update = FALSE; - gtk_range_set_update_policy (GTK_RANGE (gradient_editor->scrollbar), + editor->instant_update = FALSE; + gtk_range_set_update_policy (GTK_RANGE (editor->scrollbar), GTK_UPDATE_DELAYED); } } +static void +gradient_editor_set_hint (GradientEditor *editor, + const gchar *str) +{ + gtk_label_set_text (GTK_LABEL (editor->hint_label), str); +} + + /***** Gradient preview functions *****/ static gint preview_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { gint x, y; GdkEventButton *bevent; @@ -1107,57 +760,57 @@ preview_events (GtkWidget *widget, switch (event->type) { case GDK_EXPOSE: - preview_update (gradient_editor, FALSE); + preview_update (editor, FALSE); return FALSE; case GDK_LEAVE_NOTIFY: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); break; case GDK_MOTION_NOTIFY: - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); mevent = (GdkEventMotion *) event; - if (x != gradient_editor->preview_last_x) + if (x != editor->preview_last_x) { - gradient_editor->preview_last_x = x; + editor->preview_last_x = x; - if (gradient_editor->preview_button_down) + if (editor->preview_button_down) { if (mevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); } else { - preview_set_hint (gradient_editor, x); + preview_set_hint (editor, x); } } break; case GDK_BUTTON_PRESS: - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); bevent = (GdkEventButton *) event; switch (bevent->button) { case 1: - gradient_editor->preview_last_x = x; - gradient_editor->preview_button_down = TRUE; + editor->preview_last_x = x; + editor->preview_button_down = TRUE; if (bevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); break; case 3: - cpopup_do_popup (gradient_editor); + gradient_editor_show_context_menu (editor); break; default: @@ -1172,13 +825,13 @@ preview_events (GtkWidget *widget, if (sevent->state & GDK_SHIFT_MASK) { if (sevent->direction == GDK_SCROLL_UP) - ed_zoom_in_callback (NULL, gradient_editor); + gradient_editor_zoom_in_callback (NULL, editor); else - ed_zoom_out_callback (NULL, gradient_editor); + gradient_editor_zoom_out_callback (NULL, editor); } else { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value + ((sevent->direction == GDK_SCROLL_UP) ? -adj->page_increment / 2 : @@ -1192,18 +845,18 @@ preview_events (GtkWidget *widget, break; case GDK_BUTTON_RELEASE: - if (gradient_editor->preview_button_down) + if (editor->preview_button_down) { - gtk_widget_get_pointer (gradient_editor->preview, &x, &y); + gtk_widget_get_pointer (editor->preview, &x, &y); bevent = (GdkEventButton *) event; - gradient_editor->preview_last_x = x; - gradient_editor->preview_button_down = FALSE; + editor->preview_last_x = x; + editor->preview_button_down = FALSE; if (bevent->state & GDK_CONTROL_MASK) - preview_set_background (gradient_editor, x); + preview_set_background (editor, x); else - preview_set_foreground (gradient_editor, x); + preview_set_foreground (editor, x); break; } @@ -1217,7 +870,7 @@ preview_events (GtkWidget *widget, } static void -preview_set_hint (GradientEditor *gradient_editor, +preview_set_hint (GradientEditor *editor, gint x) { gdouble xpos; @@ -1225,11 +878,10 @@ preview_set_hint (GradientEditor *gradient_editor, GimpHSV hsv; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); - gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), - xpos, &rgb); + gimp_gradient_get_color_at (gimp_context_get_gradient (editor->context), + xpos, &rgb); gimp_rgb_to_hsv (&rgb, &hsv); @@ -1246,24 +898,25 @@ preview_set_hint (GradientEditor *gradient_editor, hsv.v, rgb.a); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } static void -preview_set_foreground (GradientEditor *gradient_editor, +preview_set_foreground (GradientEditor *editor, gint x) { GimpRGB color; gdouble xpos; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); - gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), - xpos, &color); + xpos = control_calc_g_pos (editor, x); - gimp_context_set_foreground (gimp_get_user_context (gradient_editor->context->gimp), &color); + gimp_gradient_get_color_at (gimp_context_get_gradient (editor->context), + xpos, &color); + + gimp_context_set_foreground (gimp_get_user_context (editor->context->gimp), + &color); str = g_strdup_printf (_("Foreground color set to RGB (%d, %d, %d) <-> " "(%0.3f, %0.3f, %0.3f)"), @@ -1272,24 +925,25 @@ preview_set_foreground (GradientEditor *gradient_editor, (gint) (color.b * 255.0), color.r, color.g, color.b); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } static void -preview_set_background (GradientEditor *gradient_editor, +preview_set_background (GradientEditor *editor, gint x) { GimpRGB color; gdouble xpos; gchar *str; - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); gimp_gradient_get_color_at - (gimp_context_get_gradient (gradient_editor->context), + (gimp_context_get_gradient (editor->context), xpos, &color); - gimp_context_set_background (gimp_get_user_context (gradient_editor->context->gimp), &color); + gimp_context_set_background (gimp_get_user_context (editor->context->gimp), + &color); str = g_strdup_printf (_("Background color to RGB (%d, %d, %d) <-> " "(%0.3f, %0.3f, %0.3f)"), @@ -1298,14 +952,14 @@ preview_set_background (GradientEditor *gradient_editor, (gint) (color.b * 255.0), color.r, color.g, color.b); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); g_free (str); } /*****/ static void -preview_update (GradientEditor *gradient_editor, +preview_update (GradientEditor *editor, gboolean recalculate) { glong rowsiz; @@ -1316,30 +970,30 @@ preview_update (GradientEditor *gradient_editor, static guint16 last_width = 0; static guint16 last_height = 0; - if (! GTK_WIDGET_DRAWABLE (gradient_editor->preview)) + if (! GTK_WIDGET_DRAWABLE (editor->preview)) return; /* See whether we have to re-create the preview widget * (note that the preview automatically follows the size of it's container) */ - width = gradient_editor->preview->allocation.width; - height = gradient_editor->preview->allocation.height; + width = editor->preview->allocation.width; + height = editor->preview->allocation.height; - if (! gradient_editor->preview_rows[0] || - ! gradient_editor->preview_rows[1] || + if (! editor->preview_rows[0] || + ! editor->preview_rows[1] || (width != last_width) || (height != last_height)) { - if (gradient_editor->preview_rows[0]) - g_free (gradient_editor->preview_rows[0]); + if (editor->preview_rows[0]) + g_free (editor->preview_rows[0]); - if (gradient_editor->preview_rows[1]) - g_free (gradient_editor->preview_rows[1]); + if (editor->preview_rows[1]) + g_free (editor->preview_rows[1]); rowsiz = width * 3 * sizeof (guchar); - gradient_editor->preview_rows[0] = g_malloc (rowsiz); - gradient_editor->preview_rows[1] = g_malloc (rowsiz); + editor->preview_rows[0] = g_malloc (rowsiz); + editor->preview_rows[1] = g_malloc (rowsiz); recalculate = TRUE; /* Force recalculation */ } @@ -1350,19 +1004,19 @@ preview_update (GradientEditor *gradient_editor, /* Have to redraw? */ if (recalculate) { - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - preview_fill_image (gradient_editor, + preview_fill_image (editor, width, height, adjustment->value, adjustment->value + adjustment->page_size); - gtk_widget_draw (gradient_editor->preview, NULL); + gtk_widget_draw (editor->preview, NULL); } } static void -preview_fill_image (GradientEditor *gradient_editor, +preview_fill_image (GradientEditor *editor, gint width, gint height, gdouble left, @@ -1375,12 +1029,12 @@ preview_fill_image (GradientEditor *gradient_editor, GimpRGB color; gdouble c0, c1; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); dx = (right - left) / (width - 1); cur_x = left; - p0 = gradient_editor->preview_rows[0]; - p1 = gradient_editor->preview_rows[1]; + p0 = editor->preview_rows[0]; + p1 = editor->preview_rows[1]; /* Create lines to fill the image */ for (x = 0; x < width; x++) @@ -1413,11 +1067,11 @@ preview_fill_image (GradientEditor *gradient_editor, for (y = 0; y < height; y++) { if ((y / GIMP_CHECK_SIZE) & 1) - gtk_preview_draw_row (GTK_PREVIEW (gradient_editor->preview), - gradient_editor->preview_rows[1], 0, y, width); + gtk_preview_draw_row (GTK_PREVIEW (editor->preview), + editor->preview_rows[1], 0, y, width); else - gtk_preview_draw_row (GTK_PREVIEW (gradient_editor->preview), - gradient_editor->preview_rows[0], 0, y, width); + gtk_preview_draw_row (GTK_PREVIEW (editor->preview), + editor->preview_rows[0], 0, y, width); } } @@ -1434,7 +1088,7 @@ preview_fill_image (GradientEditor *gradient_editor, static gint control_events (GtkWidget *widget, GdkEvent *event, - GradientEditor *gradient_editor) + GradientEditor *editor) { GimpGradient *gradient; GdkEventButton *bevent; @@ -1442,97 +1096,97 @@ control_events (GtkWidget *widget, gint x, y; guint32 time; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); switch (event->type) { case GDK_EXPOSE: - control_update (gradient_editor, gradient, FALSE); + control_update (editor, gradient, FALSE); break; case GDK_LEAVE_NOTIFY: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); break; case GDK_BUTTON_PRESS: - if (gradient_editor->control_drag_mode == GRAD_DRAG_NONE) + if (editor->control_drag_mode == GRAD_DRAG_NONE) { - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); bevent = (GdkEventButton *) event; - gradient_editor->control_last_x = x; - gradient_editor->control_click_time = bevent->time; + editor->control_last_x = x; + editor->control_click_time = bevent->time; - control_button_press (gradient_editor, + control_button_press (editor, x, y, bevent->button, bevent->state); - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) gtk_grab_add (widget); } break; case GDK_BUTTON_RELEASE: - ed_set_hint (gradient_editor, ""); + gradient_editor_set_hint (editor, ""); - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) { gtk_grab_remove (widget); - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); time = ((GdkEventButton *) event)->time; - if ((time - gradient_editor->control_click_time) >= GRAD_MOVE_TIME) + if ((time - editor->control_click_time) >= GRAD_MOVE_TIME) { - if (! gradient_editor->instant_update) + if (! editor->instant_update) gimp_data_dirty (GIMP_DATA (gradient)); - ed_update_editor (gradient_editor, - GRAD_UPDATE_GRADIENT); /* Possible move */ + /* Possible move */ + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT); } - else if ((gradient_editor->control_drag_mode == GRAD_DRAG_MIDDLE) || - (gradient_editor->control_drag_mode == GRAD_DRAG_ALL)) + else if ((editor->control_drag_mode == GRAD_DRAG_MIDDLE) || + (editor->control_drag_mode == GRAD_DRAG_ALL)) { - seg = gradient_editor->control_drag_segment; + seg = editor->control_drag_segment; - if ((gradient_editor->control_drag_mode == GRAD_DRAG_ALL) && - gradient_editor->control_compress) - control_extend_selection (gradient_editor, seg, - control_calc_g_pos (gradient_editor, + if ((editor->control_drag_mode == GRAD_DRAG_ALL) && + editor->control_compress) + control_extend_selection (editor, seg, + control_calc_g_pos (editor, x)); else - control_select_single_segment (gradient_editor, seg); + control_select_single_segment (editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } - gradient_editor->control_drag_mode = GRAD_DRAG_NONE; - gradient_editor->control_compress = FALSE; + editor->control_drag_mode = GRAD_DRAG_NONE; + editor->control_compress = FALSE; - control_do_hint (gradient_editor, x, y); + control_do_hint (editor, x, y); } break; case GDK_MOTION_NOTIFY: - gtk_widget_get_pointer (gradient_editor->control, &x, &y); + gtk_widget_get_pointer (editor->control, &x, &y); - if (x != gradient_editor->control_last_x) + if (x != editor->control_last_x) { - gradient_editor->control_last_x = x; + editor->control_last_x = x; - if (gradient_editor->control_drag_mode != GRAD_DRAG_NONE) + if (editor->control_drag_mode != GRAD_DRAG_NONE) { time = ((GdkEventButton *) event)->time; - if ((time - gradient_editor->control_click_time) >= GRAD_MOVE_TIME) - control_motion (gradient_editor, gradient, x); + if ((time - editor->control_click_time) >= GRAD_MOVE_TIME) + control_motion (editor, gradient, x); } else { - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); - control_do_hint (gradient_editor, x, y); + control_do_hint (editor, x, y); } } break; @@ -1545,26 +1199,26 @@ control_events (GtkWidget *widget, } static void -control_do_hint (GradientEditor *gradient_editor, +control_do_hint (GradientEditor *editor, gint x, gint y) { - GimpGradient *gradient; - GimpGradientSegment *seg; - control_drag_mode_t handle; - gboolean in_handle; - double pos; + GimpGradient *gradient; + GimpGradientSegment *seg; + GradientEditorDragMode handle; + gboolean in_handle; + double pos; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); if ((pos < 0.0) || (pos > 1.0)) return; seg_get_closest_handle (gradient, pos, &seg, &handle); - in_handle = control_point_in_handle (gradient_editor, gradient, + in_handle = control_point_in_handle (editor, gradient, x, y, seg, handle); if (in_handle) @@ -1575,53 +1229,61 @@ control_do_hint (GradientEditor *gradient_editor, if (seg != NULL) { if (seg->prev != NULL) - ed_set_hint (gradient_editor, - _("Drag: move Shift+drag: move & compress")); + gradient_editor_set_hint (editor, + _("Drag: move " + "+Drag: move & compress")); else - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection")); } else { - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection")); } break; case GRAD_DRAG_MIDDLE: - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection " - "Drag: move")); + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection " + "Drag: move")); break; default: - g_warning ("in_handle is true yet we got handle type %d", - (int) handle); + g_warning ("%s: in_handle is true, but received handle type %d.", + G_STRLOC, in_handle); break; } } else - ed_set_hint (gradient_editor, - _("Click: select Shift+click: extend selection " - "Drag: move Shift+drag: move & compress")); + { + gradient_editor_set_hint (editor, + _("Click: select " + "+Click: extend selection " + "Drag: move " + "+Drag: move & compress")); + } } static void -control_button_press (GradientEditor *gradient_editor, +control_button_press (GradientEditor *editor, gint x, gint y, guint button, guint state) { - GimpGradient *gradient; - GimpGradientSegment *seg; - control_drag_mode_t handle; - double xpos; - gboolean in_handle; + GimpGradient *gradient; + GimpGradientSegment *seg; + GradientEditorDragMode handle; + double xpos; + gboolean in_handle; - gradient = gimp_context_get_gradient (gradient_editor->context); + gradient = gimp_context_get_gradient (editor->context); switch (button) { @@ -1629,13 +1291,13 @@ control_button_press (GradientEditor *gradient_editor, break; case 3: - cpopup_do_popup (gradient_editor); + gradient_editor_show_context_menu (editor); return; /* wheelmouse support */ case 4: { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value - adj->page_increment / 2; new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size); @@ -1645,7 +1307,7 @@ control_button_press (GradientEditor *gradient_editor, case 5: { - GtkAdjustment *adj = GTK_ADJUSTMENT (gradient_editor->scroll_data); + GtkAdjustment *adj = GTK_ADJUSTMENT (editor->scroll_data); gfloat new_value = adj->value + adj->page_increment / 2; new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size); @@ -1659,11 +1321,11 @@ control_button_press (GradientEditor *gradient_editor, /* Find the closest handle */ - xpos = control_calc_g_pos (gradient_editor, x); + xpos = control_calc_g_pos (editor, x); seg_get_closest_handle (gradient, xpos, &seg, &handle); - in_handle = control_point_in_handle (gradient_editor, gradient, + in_handle = control_point_in_handle (editor, gradient, x, y, seg, handle); /* Now see what we have */ @@ -1680,25 +1342,25 @@ control_button_press (GradientEditor *gradient_editor, { if (seg->prev != NULL) { - gradient_editor->control_drag_mode = GRAD_DRAG_LEFT; - gradient_editor->control_drag_segment = seg; - gradient_editor->control_compress = TRUE; + editor->control_drag_mode = GRAD_DRAG_LEFT; + editor->control_drag_segment = seg; + editor->control_compress = TRUE; } else { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } } else if (seg->prev != NULL) { - gradient_editor->control_drag_mode = GRAD_DRAG_LEFT; - gradient_editor->control_drag_segment = seg; + editor->control_drag_mode = GRAD_DRAG_LEFT; + editor->control_drag_segment = seg; } else { - control_select_single_segment (gradient_editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_select_single_segment (editor, seg); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } return; @@ -1710,13 +1372,13 @@ control_button_press (GradientEditor *gradient_editor, if (state & GDK_SHIFT_MASK) { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } else { - control_select_single_segment (gradient_editor, seg); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_select_single_segment (editor, seg); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } return; @@ -1727,20 +1389,20 @@ control_button_press (GradientEditor *gradient_editor, case GRAD_DRAG_MIDDLE: if (state & GDK_SHIFT_MASK) { - control_extend_selection (gradient_editor, seg, xpos); - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + control_extend_selection (editor, seg, xpos); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } else { - gradient_editor->control_drag_mode = GRAD_DRAG_MIDDLE; - gradient_editor->control_drag_segment = seg; + editor->control_drag_mode = GRAD_DRAG_MIDDLE; + editor->control_drag_segment = seg; } return; default: - g_warning ("in_handle is true yet we got handle type %d", - (int) handle); + g_warning ("%s: in_handle is true, but received handle type %d.", + G_STRLOC, in_handle); return; } } @@ -1748,25 +1410,25 @@ control_button_press (GradientEditor *gradient_editor, { seg = gimp_gradient_get_segment_at (gradient, xpos); - gradient_editor->control_drag_mode = GRAD_DRAG_ALL; - gradient_editor->control_drag_segment = seg; - gradient_editor->control_last_gx = xpos; - gradient_editor->control_orig_pos = xpos; + editor->control_drag_mode = GRAD_DRAG_ALL; + editor->control_drag_segment = seg; + editor->control_last_gx = xpos; + editor->control_orig_pos = xpos; if (state & GDK_SHIFT_MASK) - gradient_editor->control_compress = TRUE; + editor->control_compress = TRUE; return; } } static gboolean -control_point_in_handle (GradientEditor *gradient_editor, - GimpGradient *gradient, - gint x, - gint y, - GimpGradientSegment *seg, - control_drag_mode_t handle) +control_point_in_handle (GradientEditor *editor, + GimpGradient *gradient, + gint x, + gint y, + GimpGradientSegment *seg, + GradientEditorDragMode handle) { gint handle_pos; @@ -1775,23 +1437,23 @@ control_point_in_handle (GradientEditor *gradient_editor, case GRAD_DRAG_LEFT: if (seg) { - handle_pos = control_calc_p_pos (gradient_editor, seg->left); + handle_pos = control_calc_p_pos (editor, seg->left); } else { seg = gimp_gradient_segment_get_last (gradient->segments); - handle_pos = control_calc_p_pos (gradient_editor, seg->right); + handle_pos = control_calc_p_pos (editor, seg->right); } break; case GRAD_DRAG_MIDDLE: - handle_pos = control_calc_p_pos (gradient_editor, seg->middle); + handle_pos = control_calc_p_pos (editor, seg->middle); break; default: - g_warning ("can not handle drag mode %d", (gint) handle); + g_warning ("%s: Cannot handle drag mode %d.", G_STRLOC, handle); return FALSE; } @@ -1806,29 +1468,29 @@ control_point_in_handle (GradientEditor *gradient_editor, /*****/ static void -control_select_single_segment (GradientEditor *gradient_editor, +control_select_single_segment (GradientEditor *editor, GimpGradientSegment *seg) { - gradient_editor->control_sel_l = seg; - gradient_editor->control_sel_r = seg; + editor->control_sel_l = seg; + editor->control_sel_r = seg; } static void -control_extend_selection (GradientEditor *gradient_editor, +control_extend_selection (GradientEditor *editor, GimpGradientSegment *seg, gdouble pos) { - if (fabs (pos - gradient_editor->control_sel_l->left) < - fabs (pos - gradient_editor->control_sel_r->right)) - gradient_editor->control_sel_l = seg; + if (fabs (pos - editor->control_sel_l->left) < + fabs (pos - editor->control_sel_r->right)) + editor->control_sel_l = seg; else - gradient_editor->control_sel_r = seg; + editor->control_sel_r = seg; } /*****/ static void -control_motion (GradientEditor *gradient_editor, +control_motion (GradientEditor *editor, GimpGradient *gradient, gint x) { @@ -1837,76 +1499,75 @@ control_motion (GradientEditor *gradient_editor, gdouble delta; gchar *str = NULL; - seg = gradient_editor->control_drag_segment; + seg = editor->control_drag_segment; - switch (gradient_editor->control_drag_mode) + switch (editor->control_drag_mode) { case GRAD_DRAG_LEFT: - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); - if (! gradient_editor->control_compress) + if (! editor->control_compress) seg->prev->right = seg->left = CLAMP (pos, seg->prev->middle + EPSILON, seg->middle - EPSILON); else - control_compress_left (gradient_editor->control_sel_l, - gradient_editor->control_sel_r, + control_compress_left (editor->control_sel_l, + editor->control_sel_r, seg, pos); str = g_strdup_printf (_("Handle position: %0.6f"), seg->left); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); break; case GRAD_DRAG_MIDDLE: - pos = control_calc_g_pos (gradient_editor, x); + pos = control_calc_g_pos (editor, x); seg->middle = CLAMP (pos, seg->left + EPSILON, seg->right - EPSILON); str = g_strdup_printf (_("Handle position: %0.6f"), seg->middle); - ed_set_hint (gradient_editor, str); + gradient_editor_set_hint (editor, str); break; case GRAD_DRAG_ALL: - pos = control_calc_g_pos (gradient_editor, x); - delta = pos - gradient_editor->control_last_gx; + pos = control_calc_g_pos (editor, x); + delta = pos - editor->control_last_gx; - if ((seg->left >= gradient_editor->control_sel_l->left) && - (seg->right <= gradient_editor->control_sel_r->right)) - delta = control_move (gradient_editor, - gradient_editor->control_sel_l, - gradient_editor->control_sel_r, delta); + if ((seg->left >= editor->control_sel_l->left) && + (seg->right <= editor->control_sel_r->right)) + delta = control_move (editor, + editor->control_sel_l, + editor->control_sel_r, delta); else - delta = control_move (gradient_editor, seg, seg, delta); + delta = control_move (editor, seg, seg, delta); - gradient_editor->control_last_gx += delta; + editor->control_last_gx += delta; str = g_strdup_printf (_("Distance: %0.6f"), - gradient_editor->control_last_gx - - gradient_editor->control_orig_pos); - ed_set_hint (gradient_editor, str); + editor->control_last_gx - + editor->control_orig_pos); + gradient_editor_set_hint (editor, str); break; default: - gimp_fatal_error ("Attempt to move bogus handle %d", - (gint) gradient_editor->control_drag_mode); + g_warning ("%s: Attempting to move bogus handle %d.", + G_STRLOC, editor->control_drag_mode); break; } if (str) g_free (str); - if (gradient_editor->instant_update) + if (editor->instant_update) { gimp_data_dirty (GIMP_DATA (gradient)); - ed_update_editor (gradient_editor, - GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); } else { - ed_update_editor (gradient_editor, GRAD_UPDATE_CONTROL); + gradient_editor_update (editor, GRAD_UPDATE_CONTROL); } } @@ -2028,10 +1689,10 @@ control_compress_range (GimpGradientSegment *range_l, /*****/ static gdouble -control_move (GradientEditor *gradient_editor, +control_move (GradientEditor *editor, GimpGradientSegment *range_l, GimpGradientSegment *range_r, - gdouble delta) + gdouble delta) { gdouble lbound, rbound; gint is_first, is_last; @@ -2044,7 +1705,7 @@ control_move (GradientEditor *gradient_editor, /* Calculate drag bounds */ - if (! gradient_editor->control_compress) + if (! editor->control_compress) { if (!is_first) lbound = range_l->prev->middle + EPSILON; @@ -2119,7 +1780,7 @@ control_move (GradientEditor *gradient_editor, if (!is_first) { - if (! gradient_editor->control_compress) + if (! editor->control_compress) range_l->prev->right = range_l->left; else control_compress_range (range_l->prev, range_l->prev, @@ -2128,7 +1789,7 @@ control_move (GradientEditor *gradient_editor, if (!is_last) { - if (! gradient_editor->control_compress) + if (! editor->control_compress) range_r->next->left = range_r->right; else control_compress_range (range_r->next, range_r->next, @@ -2141,7 +1802,7 @@ control_move (GradientEditor *gradient_editor, /*****/ static void -control_update (GradientEditor *gradient_editor, +control_update (GradientEditor *editor, GimpGradient *gradient, gboolean recalculate) { @@ -2149,27 +1810,27 @@ control_update (GradientEditor *gradient_editor, gint cwidth, cheight; gint pwidth, pheight; - if (! GTK_WIDGET_DRAWABLE (gradient_editor->control)) + if (! GTK_WIDGET_DRAWABLE (editor->control)) return; /* See whether we have to re-create the control pixmap * depending on the preview's width */ - cwidth = gradient_editor->preview->allocation.width; + cwidth = editor->preview->allocation.width; cheight = GRAD_CONTROL_HEIGHT; - if (gradient_editor->control_pixmap) - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + if (editor->control_pixmap) + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); - if (! gradient_editor->control_pixmap || + if (! editor->control_pixmap || (cwidth != pwidth) || (cheight != pheight)) { - if (gradient_editor->control_pixmap) - gdk_drawable_unref (gradient_editor->control_pixmap); + if (editor->control_pixmap) + gdk_drawable_unref (editor->control_pixmap); - gradient_editor->control_pixmap = - gdk_pixmap_new (gradient_editor->control->window, cwidth, cheight, -1); + editor->control_pixmap = + gdk_pixmap_new (editor->control->window, cwidth, cheight, -1); recalculate = TRUE; } @@ -2180,27 +1841,27 @@ control_update (GradientEditor *gradient_editor, /* Have to reset the selection? */ if (recalculate) - control_select_single_segment (gradient_editor, gradient->segments); + control_select_single_segment (editor, gradient->segments); /* Redraw pixmap */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); - control_draw (gradient_editor, + control_draw (editor, gradient, - gradient_editor->control_pixmap, + editor->control_pixmap, cwidth, cheight, adjustment->value, adjustment->value + adjustment->page_size); - gdk_draw_drawable (gradient_editor->control->window, - gradient_editor->control->style->black_gc, - gradient_editor->control_pixmap, + gdk_draw_drawable (editor->control->window, + editor->control->style->black_gc, + editor->control_pixmap, 0, 0, 0, 0, cwidth, cheight); } static void -control_draw (GradientEditor *gradient_editor, +control_draw (GradientEditor *editor, GimpGradient *gradient, GdkPixmap *pixmap, gint width, @@ -2208,25 +1869,25 @@ control_draw (GradientEditor *gradient_editor, gdouble left, gdouble right) { - gint sel_l, sel_r; - gdouble g_pos; - GimpGradientSegment *seg; - control_drag_mode_t handle; + gint sel_l, sel_r; + gdouble g_pos; + GimpGradientSegment *seg; + GradientEditorDragMode handle; /* Clear the pixmap */ - gdk_draw_rectangle (pixmap, gradient_editor->control->style->bg_gc[GTK_STATE_NORMAL], + gdk_draw_rectangle (pixmap, editor->control->style->bg_gc[GTK_STATE_NORMAL], TRUE, 0, 0, width, height); /* Draw selection */ - sel_l = control_calc_p_pos (gradient_editor, - gradient_editor->control_sel_l->left); - sel_r = control_calc_p_pos (gradient_editor, - gradient_editor->control_sel_r->right); + sel_l = control_calc_p_pos (editor, + editor->control_sel_l->left); + sel_r = control_calc_p_pos (editor, + editor->control_sel_r->right); gdk_draw_rectangle (pixmap, - gradient_editor->control->style->dark_gc[GTK_STATE_NORMAL], + editor->control->style->dark_gc[GTK_STATE_NORMAL], TRUE, sel_l, 0, sel_r - sel_l + 1, height); /* Draw handles */ @@ -2235,13 +1896,13 @@ control_draw (GradientEditor *gradient_editor, while (seg) { - control_draw_normal_handle (gradient_editor, pixmap, seg->left, height); - control_draw_middle_handle (gradient_editor, pixmap, seg->middle, height); + control_draw_normal_handle (editor, pixmap, seg->left, height); + control_draw_middle_handle (editor, pixmap, seg->middle, height); /* Draw right handle only if this is the last segment */ if (seg->next == NULL) - control_draw_normal_handle (gradient_editor, pixmap, seg->right, height); + control_draw_normal_handle (editor, pixmap, seg->right, height); /* Next! */ @@ -2250,7 +1911,7 @@ control_draw (GradientEditor *gradient_editor, /* Draw the handle which is closest to the mouse position */ - g_pos = control_calc_g_pos (gradient_editor, gradient_editor->control_last_x); + g_pos = control_calc_g_pos (editor, editor->control_last_x); seg_get_closest_handle (gradient, CLAMP (g_pos, 0.0, 1.0), &seg, &handle); @@ -2259,21 +1920,21 @@ control_draw (GradientEditor *gradient_editor, case GRAD_DRAG_LEFT: if (seg) { - control_draw_normal_handle (gradient_editor, pixmap, + control_draw_normal_handle (editor, pixmap, seg->left, height); } else { seg = gimp_gradient_segment_get_last (gradient->segments); - control_draw_normal_handle (gradient_editor, pixmap, + control_draw_normal_handle (editor, pixmap, seg->right, height); } break; case GRAD_DRAG_MIDDLE: - control_draw_middle_handle (gradient_editor, pixmap, seg->middle, height); + control_draw_middle_handle (editor, pixmap, seg->middle, height); break; default: @@ -2282,27 +1943,27 @@ control_draw (GradientEditor *gradient_editor, } static void -control_draw_normal_handle (GradientEditor *gradient_editor, +control_draw_normal_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height) { control_draw_handle (pixmap, - gradient_editor->control->style->black_gc, - gradient_editor->control->style->black_gc, - control_calc_p_pos (gradient_editor, pos), height); + editor->control->style->black_gc, + editor->control->style->black_gc, + control_calc_p_pos (editor, pos), height); } static void -control_draw_middle_handle (GradientEditor *gradient_editor, +control_draw_middle_handle (GradientEditor *editor, GdkPixmap *pixmap, gdouble pos, gint height) { control_draw_handle (pixmap, - gradient_editor->control->style->black_gc, - gradient_editor->control->style->bg_gc[GTK_STATE_PRELIGHT], - control_calc_p_pos (gradient_editor, pos), height); + editor->control->style->black_gc, + editor->control->style->bg_gc[GTK_STATE_PRELIGHT], + control_calc_p_pos (editor, pos), height); } static void @@ -2330,7 +1991,7 @@ control_draw_handle (GdkPixmap *pixmap, /*****/ static gint -control_calc_p_pos (GradientEditor *gradient_editor, +control_calc_p_pos (GradientEditor *editor, gdouble pos) { gint pwidth, pheight; @@ -2342,14 +2003,14 @@ control_calc_p_pos (GradientEditor *gradient_editor, * and the gradient control's handles. */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); return RINT ((pwidth - 1) * (pos - adjustment->value) / adjustment->page_size); } static gdouble -control_calc_g_pos (GradientEditor *gradient_editor, +control_calc_g_pos (GradientEditor *editor, gint pos) { gint pwidth, pheight; @@ -2357,2209 +2018,19 @@ control_calc_g_pos (GradientEditor *gradient_editor, /* Calculate the gradient position that corresponds to widget's coordinates */ - adjustment = GTK_ADJUSTMENT (gradient_editor->scroll_data); - gdk_drawable_get_size (gradient_editor->control_pixmap, &pwidth, &pheight); + adjustment = GTK_ADJUSTMENT (editor->scroll_data); + gdk_drawable_get_size (editor->control_pixmap, &pwidth, &pheight); return adjustment->page_size * pos / (pwidth - 1) + adjustment->value; } -/***** Control popup functions *****/ - -static void -cpopup_create_main_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkWidget *label; - GtkAccelGroup *accel_group; - - menu = gtk_menu_new (); - accel_group = gtk_accel_group_new (); - - gradient_editor->accel_group = accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - gtk_window_add_accel_group (GTK_WINDOW (gradient_editor->shell), accel_group); - - /* Left endpoint */ - menuitem = cpopup_create_color_item (&gradient_editor->left_color_preview, - &label); - gtk_label_set_text (GTK_LABEL (label), _("Left endpoint's color")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_set_left_color_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'L', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Load from")); - gradient_editor->control_left_load_popup = - cpopup_create_load_menu (gradient_editor, - gradient_editor->left_load_color_boxes, - gradient_editor->left_load_labels, - _("Left neighbor's right endpoint"), - _("Right endpoint"), - G_CALLBACK (cpopup_load_left_callback), - 'L', GDK_CONTROL_MASK, - 'L', GDK_MOD1_MASK, - 'F', GDK_CONTROL_MASK); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), - gradient_editor->control_left_load_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Save to")); - gradient_editor->control_left_save_popup = - cpopup_create_save_menu (gradient_editor, - gradient_editor->left_save_color_boxes, - gradient_editor->left_save_labels, - G_CALLBACK (cpopup_save_left_callback)); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_left_save_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Right endpoint */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = cpopup_create_color_item (&gradient_editor->right_color_preview, - &label); - gtk_label_set_text (GTK_LABEL (label), _("Right endpoint's color")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_set_right_color_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'R', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Load from")); - gradient_editor->control_right_load_popup = - cpopup_create_load_menu (gradient_editor, - gradient_editor->right_load_color_boxes, - gradient_editor->right_load_labels, - _("Right neighbor's left endpoint"), - _("Left endpoint"), - G_CALLBACK (cpopup_load_right_callback), - 'R', GDK_CONTROL_MASK, - 'R', GDK_MOD1_MASK, - 'F', GDK_MOD1_MASK); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_right_load_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Save to")); - gradient_editor->control_right_save_popup = - cpopup_create_save_menu (gradient_editor, - gradient_editor->right_save_color_boxes, - gradient_editor->right_save_labels, - G_CALLBACK (cpopup_save_right_callback)); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_right_save_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Blending function */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_blending_label); - gradient_editor->control_blending_popup = - cpopup_create_blending_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_blending_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Coloring type */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_coloring_label); - gradient_editor->control_coloring_popup = - cpopup_create_coloring_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), - gradient_editor->control_coloring_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Operations */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Split at midpoint */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_split_m_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_split_midpoint_callback), - gradient_editor); - gtk_widget_add_accelerator(menuitem, "activate", - accel_group, - 'S', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Split uniformly */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_split_u_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_split_uniform_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'U', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Delete */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_delete_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_delete_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_delete_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'D', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Recenter */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_recenter_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_recenter_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'C', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Redistribute */ - menuitem = cpopup_create_menu_item_with_label ("", &gradient_editor->control_redistribute_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_redistribute_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'C', GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Selection ops */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Selection operations")); - gradient_editor->control_sel_ops_popup = - cpopup_create_sel_ops_menu (gradient_editor); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), - gradient_editor->control_sel_ops_popup); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - /* Done */ - gradient_editor->control_main_popup = menu; -} - -static void -cpopup_do_popup (GradientEditor *gradient_editor) -{ - cpopup_adjust_menus (gradient_editor); - - gtk_menu_popup (GTK_MENU (gradient_editor->control_main_popup), - NULL, NULL, NULL, NULL, 3, 0); -} - -/***** Create a single menu item *****/ - -static GtkWidget * -cpopup_create_color_item (GtkWidget **color_box, - GtkWidget **label) -{ - GtkWidget *menuitem; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *wcolor_box; - GtkWidget *wlabel; - - menuitem = gtk_menu_item_new(); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (menuitem), hbox); - gtk_widget_show (hbox); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - wcolor_box = gtk_preview_new (GTK_PREVIEW_COLOR); - gtk_preview_set_dither (GTK_PREVIEW (wcolor_box), GDK_RGB_DITHER_MAX); - gtk_preview_size (GTK_PREVIEW (wcolor_box), - GRAD_COLOR_BOX_WIDTH, GRAD_COLOR_BOX_HEIGHT); - gtk_box_pack_start (GTK_BOX (vbox), wcolor_box, FALSE, FALSE, 2); - gtk_widget_show (wcolor_box); - - if (color_box) - *color_box = wcolor_box; - - wlabel = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (wlabel), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), wlabel, FALSE, FALSE, 4); - gtk_widget_show (wlabel); - - if (label) - *label = wlabel; - - return menuitem; -} - -static GtkWidget * -cpopup_create_menu_item_with_label (gchar *str, - GtkWidget **label) -{ - GtkWidget *menuitem; - GtkWidget *accel_label; - - menuitem = gtk_menu_item_new (); - - accel_label = gtk_accel_label_new (str); - gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5); - gtk_container_add (GTK_CONTAINER (menuitem), accel_label); - gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), - GTK_WIDGET (menuitem)); - gtk_widget_show (accel_label); - - if (label) - *label = accel_label; - - return menuitem; -} - -/***** Update all menus *****/ - -static void -cpopup_adjust_menus (GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg; - gint i; - GimpRGB fg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Render main menu color boxes */ - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_color_preview), - &gradient_editor->control_sel_l->left_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_color_preview), - &gradient_editor->control_sel_r->right_color); - - /* Render load color from endpoint color boxes */ - - if (gradient_editor->control_sel_l->prev != NULL) - seg = gradient_editor->control_sel_l->prev; - else - seg = gimp_gradient_segment_get_last (gradient_editor->control_sel_l); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[0]), - &seg->right_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[1]), - &gradient_editor->control_sel_r->right_color); - - if (gradient_editor->control_sel_r->next != NULL) - seg = gradient_editor->control_sel_r->next; - else - seg = gradient->segments; - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[0]), - &seg->left_color); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[1]), - &gradient_editor->control_sel_l->left_color); - - /* Render Foreground color boxes */ - - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[2]), - &fg); - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[2]), - &fg); - - /* Render saved color boxes */ - - for (i = 0; i < GRAD_NUM_COLORS; i++) - cpopup_update_saved_color (gradient_editor, - i, &gradient_editor->saved_colors[i]); - - /* Adjust labels */ - - if (gradient_editor->control_sel_l == gradient_editor->control_sel_r) - { - gtk_label_set_text (GTK_LABEL (gradient_editor->control_blending_label), - _("Blending function for segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_coloring_label), - _("Coloring type for segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_m_label), - _("Split segment at midpoint")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_u_label), - _("Split segment uniformly")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_delete_label), - _("Delete segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_recenter_label), - _("Re-center segment's midpoint")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_redistribute_label), - _("Re-distribute handles in segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_flip_label), - _("Flip segment")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_replicate_label), - _("Replicate segment")); - } - else - { - gtk_label_set_text (GTK_LABEL (gradient_editor->control_blending_label), - _("Blending function for selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_coloring_label), - _("Coloring type for selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_m_label), - _("Split segments at midpoints")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_split_u_label), - _("Split segments uniformly")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_delete_label), - _("Delete selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_recenter_label), - _("Re-center midpoints in selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_redistribute_label), - _("Re-distribute handles in selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_flip_label), - _("Flip selection")); - gtk_label_set_text (GTK_LABEL (gradient_editor->control_replicate_label), - _("Replicate selection")); - } - - /* Adjust blending and coloring menus */ - cpopup_adjust_blending_menu (gradient_editor); - cpopup_adjust_coloring_menu (gradient_editor); - - /* Can invoke delete? */ - if ((gradient_editor->control_sel_l->prev == NULL) && - (gradient_editor->control_sel_r->next == NULL)) - gtk_widget_set_sensitive (gradient_editor->control_delete_menu_item, FALSE); - else - gtk_widget_set_sensitive (gradient_editor->control_delete_menu_item, TRUE); - - /* Can invoke blend colors / opacity? */ - if (gradient_editor->control_sel_l == gradient_editor->control_sel_r) - { - gtk_widget_set_sensitive (gradient_editor->control_blend_colors_menu_item, - FALSE); - gtk_widget_set_sensitive (gradient_editor->control_blend_opacity_menu_item, - FALSE); - } - else - { - gtk_widget_set_sensitive (gradient_editor->control_blend_colors_menu_item, - TRUE); - gtk_widget_set_sensitive (gradient_editor->control_blend_opacity_menu_item, - TRUE); - } -} - -static void -cpopup_adjust_blending_menu (GradientEditor *gradient_editor) -{ - gint equal; - glong i, num_items; - gint type; - - cpopup_check_selection_params (gradient_editor, &equal, NULL); - - /* Block activate signals */ - num_items = (sizeof (gradient_editor->control_blending_items) / - sizeof (gradient_editor->control_blending_items[0])); - - type = (int) gradient_editor->control_sel_l->type; - - for (i = 0; i < num_items; i++) - gtk_signal_handler_block_by_data - (GTK_OBJECT (gradient_editor->control_blending_items[i]), - gradient_editor); - - /* Set state */ - if (equal) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_blending_items[type]), TRUE); - gtk_widget_hide (gradient_editor->control_blending_items[num_items - 1]); - } - else - { - gtk_widget_show (gradient_editor->control_blending_items[num_items - 1]); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_blending_items[num_items - 1]), TRUE); - } - - /* Unblock signals */ - for (i = 0; i < num_items; i++) - gtk_signal_handler_unblock_by_data (GTK_OBJECT (gradient_editor->control_blending_items[i]), - gradient_editor); -} - -static void -cpopup_adjust_coloring_menu (GradientEditor *gradient_editor) -{ - gint equal; - glong i, num_items; - gint coloring; - - cpopup_check_selection_params (gradient_editor, NULL, &equal); - - /* Block activate signals */ - num_items = (sizeof (gradient_editor->control_coloring_items) / - sizeof (gradient_editor->control_coloring_items[0])); - - coloring = (int) gradient_editor->control_sel_l->color; - - for (i = 0; i < num_items; i++) - gtk_signal_handler_block_by_data (GTK_OBJECT (gradient_editor->control_coloring_items[i]), - gradient_editor); - - /* Set state */ - if (equal) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_coloring_items[coloring]), TRUE); - gtk_widget_hide (gradient_editor->control_coloring_items[num_items - 1]); - } - else - { - gtk_widget_show (gradient_editor->control_coloring_items[num_items - 1]); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gradient_editor->control_coloring_items[num_items - 1]), TRUE); - } - - /* Unblock signals */ - for (i = 0; i < num_items; i++) - gtk_signal_handler_unblock_by_data (GTK_OBJECT (gradient_editor->control_coloring_items[i]), - gradient_editor); -} - -static void -cpopup_check_selection_params (GradientEditor *gradient_editor, - gint *equal_blending, - gint *equal_coloring) -{ - GimpGradientSegmentType type; - GimpGradientSegmentColor color; - gint etype, ecolor; - GimpGradientSegment *seg, *aseg; - - type = gradient_editor->control_sel_l->type; - color = gradient_editor->control_sel_l->color; - - etype = 1; - ecolor = 1; - - seg = gradient_editor->control_sel_l; - - do - { - etype = etype && (seg->type == type); - ecolor = ecolor && (seg->color == color); - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - if (equal_blending) - *equal_blending = etype; - - if (equal_coloring) - *equal_coloring = ecolor; -} - -/*****/ - -static void -cpopup_render_color_box (GtkPreview *preview, - GimpRGB *color) -{ - guchar rows[3][GRAD_COLOR_BOX_WIDTH * 3]; - gint x, y; - gint r0, g0, b0; - gint r1, g1, b1; - guchar *p0, *p1, *p2; - - /* Fill rows */ - - r0 = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.0; - r1 = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - g0 = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.0; - g1 = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - b0 = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.0; - b1 = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.0; - - p0 = rows[0]; - p1 = rows[1]; - p2 = rows[2]; - - for (x = 0; x < GRAD_COLOR_BOX_WIDTH; x++) - { - if ((x == 0) || (x == (GRAD_COLOR_BOX_WIDTH - 1))) - { - *p0++ = 0; - *p0++ = 0; - *p0++ = 0; - - *p1++ = 0; - *p1++ = 0; - *p1++ = 0; - } - else - if ((x / GIMP_CHECK_SIZE) & 1) - { - *p0++ = r1; - *p0++ = g1; - *p0++ = b1; - - *p1++ = r0; - *p1++ = g0; - *p1++ = b0; - } - else - { - *p0++ = r0; - *p0++ = g0; - *p0++ = b0; - - *p1++ = r1; - *p1++ = g1; - *p1++ = b1; - } - - *p2++ = 0; - *p2++ = 0; - *p2++ = 0; - } - - /* Fill preview */ - - gtk_preview_draw_row (preview, rows[2], 0, 0, GRAD_COLOR_BOX_WIDTH); - - for (y = 1; y < (GRAD_COLOR_BOX_HEIGHT - 1); y++) - if ((y / GIMP_CHECK_SIZE) & 1) - gtk_preview_draw_row (preview, rows[1], 0, y, GRAD_COLOR_BOX_WIDTH); - else - gtk_preview_draw_row (preview, rows[0], 0, y, GRAD_COLOR_BOX_WIDTH); - - gtk_preview_draw_row (preview, rows[2], 0, y, GRAD_COLOR_BOX_WIDTH); -} - -/***** Creale load & save menus *****/ - -static GtkWidget * -cpopup_create_load_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - gchar *label1, - gchar *label2, - GCallback callback, - gchar accel_key_0, guint8 accel_mods_0, - gchar accel_key_1, guint8 accel_mods_1, - gchar accel_key_2, guint8 accel_mods_2) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkAccelGroup *accel_group; - gint i; - - menu = gtk_menu_new (); - accel_group = gradient_editor->accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - - /* Create items */ - for (i = 0; i < (GRAD_NUM_COLORS + 3); i++) - { - if (i == 3) - { - /* Insert separator between "to fetch" and "saved" colors */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - } - - menuitem = cpopup_create_color_item (&color_boxes[i], &labels[i]); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_object_set_data (G_OBJECT (menuitem), "user_data", - GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - callback, - gradient_editor); - - switch (i) - { - case 0: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_0, accel_mods_0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - case 1: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_1, accel_mods_1, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - case 2: - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - accel_key_2, accel_mods_2, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - break; - - default: - break; - } - } - - /* Set labels */ - gtk_label_set_text (GTK_LABEL (labels[0]), label1); - gtk_label_set_text (GTK_LABEL (labels[1]), label2); - gtk_label_set_text (GTK_LABEL (labels[2]), _("FG color")); - - return menu; -} - -static GtkWidget * -cpopup_create_save_menu (GradientEditor *gradient_editor, - GtkWidget **color_boxes, - GtkWidget **labels, - GCallback callback) -{ - GtkWidget *menu; - GtkWidget *menuitem; - gint i; - - menu = gtk_menu_new (); - - for (i = 0; i < GRAD_NUM_COLORS; i++) - { - menuitem = cpopup_create_color_item (&color_boxes[i], &labels[i]); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - callback, - gradient_editor); - } - - return menu; -} - -static void -cpopup_update_saved_color (GradientEditor *gradient_editor, - gint n, - GimpRGB *color) -{ - gchar *str; - - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_load_color_boxes[n + 3]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->left_save_color_boxes[n]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_load_color_boxes[n + 3]), - color); - cpopup_render_color_box (GTK_PREVIEW (gradient_editor->right_save_color_boxes[n]), - color); - - str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), - color->r, - color->g, - color->b, - color->a); - - gtk_label_set_text (GTK_LABEL (gradient_editor->left_load_labels[n + 3]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->left_save_labels[n]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->right_load_labels[n + 3]), str); - gtk_label_set_text (GTK_LABEL (gradient_editor->right_save_labels[n]), str); - - g_free (str); - - gradient_editor->saved_colors[n] = *color; -} - -/*****/ - -static void -cpopup_load_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradientSegment *seg; - GimpRGB fg; - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - switch (i) - { - case 0: /* Fetch from left neighbor's right endpoint */ - if (gradient_editor->control_sel_l->prev != NULL) - seg = gradient_editor->control_sel_l->prev; - else - seg = gimp_gradient_segment_get_last (gradient_editor->control_sel_l); - - cpopup_blend_endpoints (gradient_editor, - &seg->right_color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - case 1: /* Fetch from right endpoint */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->right_color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - case 2: /* Fetch from FG color */ - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - cpopup_blend_endpoints (gradient_editor, - &fg, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - - default: /* Load a color */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->saved_colors[i - 3], - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - break; - } - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_save_left_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient_editor->saved_colors[i] = gradient_editor->control_sel_l->left_color; -} - -static void -cpopup_load_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg; - GimpRGB fg; - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (i) - { - case 0: /* Fetch from right neighbor's left endpoint */ - if (gradient_editor->control_sel_r->next != NULL) - seg = gradient_editor->control_sel_r->next; - else - seg = gradient->segments; - - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - &seg->left_color, - TRUE, TRUE); - break; - - case 1: /* Fetch from left endpoint */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_l->left_color, - TRUE, TRUE); - break; - - case 2: /* Fetch from FG color */ - gimp_context_get_foreground (gimp_get_user_context (gradient_editor->context->gimp), &fg); - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &fg, - TRUE, TRUE); - break; - - default: /* Load a color */ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->saved_colors[i - 3], - TRUE, TRUE); - break; - } - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_save_right_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gint i; - - i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - gradient_editor->saved_colors[i] = gradient_editor->control_sel_r->right_color; -} - -/*****/ - -static GimpGradientSegment * -cpopup_save_selection (GradientEditor *gradient_editor) -{ - GimpGradientSegment *seg, *prev, *tmp; - GimpGradientSegment *oseg, *oaseg; - - prev = NULL; - oseg = gradient_editor->control_sel_l; - tmp = NULL; - - do - { - seg = gimp_gradient_segment_new (); - - *seg = *oseg; /* Copy everything */ - - if (prev == NULL) - tmp = seg; /* Remember first segment */ - else - prev->next = seg; - - seg->prev = prev; - seg->next = NULL; - - prev = seg; - oaseg = oseg; - oseg = oseg->next; - } - while (oaseg != gradient_editor->control_sel_r); - - return tmp; -} - -static void -cpopup_replace_selection (GradientEditor *gradient_editor, - GimpGradientSegment *replace_seg) -{ - GimpGradient *gradient; - GimpGradientSegment *lseg, *rseg; - GimpGradientSegment *replace_last; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Remember left and right segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - replace_last = gimp_gradient_segment_get_last (replace_seg); - - /* Free old selection */ - - gradient_editor->control_sel_r->next = NULL; - - gimp_gradient_segments_free (gradient_editor->control_sel_l); - - /* Link in new segments */ - - if (lseg) - lseg->next = replace_seg; - else - gradient->segments = replace_seg; - - replace_seg->prev = lseg; - - if (rseg) - rseg->prev = replace_last; - - replace_last->next = rseg; - - gradient_editor->control_sel_l = replace_seg; - gradient_editor->control_sel_r = replace_last; - - gradient->last_visited = NULL; /* Force re-search */ -} - -/***** Color dialogs for left and right endpoint *****/ - -static void -cpopup_set_left_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gradient_editor->left_saved_dirty = GIMP_DATA (gradient)->dirty; - gradient_editor->left_saved_segments = cpopup_save_selection (gradient_editor); - - color_notebook_new (_("Left Endpoint Color"), - &gradient_editor->control_sel_l->left_color, - (ColorNotebookCallback) cpopup_left_color_changed, - gradient_editor, - gradient_editor->instant_update, - TRUE); - - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_set_right_color_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gradient_editor->right_saved_dirty = GIMP_DATA (gradient)->dirty; - gradient_editor->right_saved_segments = cpopup_save_selection (gradient_editor); - - color_notebook_new (_("Right Endpoint Color"), - &gradient_editor->control_sel_l->right_color, - (ColorNotebookCallback) cpopup_right_color_changed, - gradient_editor, - gradient_editor->instant_update, - TRUE); - - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_left_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data) -{ - GradientEditor *gradient_editor; - GimpGradient *gradient; - - gradient_editor = (GradientEditor *) data; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (state) - { - case COLOR_NOTEBOOK_OK: - cpopup_blend_endpoints (gradient_editor, - (GimpRGB *) color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - gimp_gradient_segments_free (gradient_editor->left_saved_segments); - gimp_data_dirty (GIMP_DATA (gradient)); - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - - case COLOR_NOTEBOOK_UPDATE: - cpopup_blend_endpoints (gradient_editor, - (GimpRGB *) color, - &gradient_editor->control_sel_r->right_color, - TRUE, TRUE); - gimp_data_dirty (GIMP_DATA (gradient)); - break; - - case COLOR_NOTEBOOK_CANCEL: - cpopup_replace_selection (gradient_editor, - gradient_editor->left_saved_segments); - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); - GIMP_DATA (gradient)->dirty = gradient_editor->left_saved_dirty; - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - } - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_right_color_changed (ColorNotebook *cnb, - const GimpRGB *color, - ColorNotebookState state, - gpointer data) -{ - GradientEditor *gradient_editor; - GimpGradient *gradient; - - gradient_editor = (GradientEditor *) data; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - switch (state) - { - case COLOR_NOTEBOOK_UPDATE: - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - (GimpRGB *) color, - TRUE, TRUE); - gimp_data_dirty (GIMP_DATA (gradient)); - break; - - case COLOR_NOTEBOOK_OK: - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_r->left_color, - (GimpRGB *) color, - TRUE, TRUE); - gimp_gradient_segments_free (gradient_editor->right_saved_segments); - gimp_data_dirty (GIMP_DATA (gradient)); - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - - case COLOR_NOTEBOOK_CANCEL: - cpopup_replace_selection (gradient_editor, - gradient_editor->right_saved_segments); - GIMP_DATA (gradient)->dirty = gradient_editor->right_saved_dirty; - color_notebook_free (cnb); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - break; - } - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Blending menu *****/ - -static GtkWidget * -cpopup_create_blending_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GSList *group; - gint i; - - static const gchar *blending_types[] = - { - N_("Linear"), - N_("Curved"), - N_("Sinusoidal"), - N_("Spherical (increasing)"), - N_("Spherical (decreasing)") - }; - - menu = gtk_menu_new (); - group = NULL; - - for (i = 0; i < G_N_ELEMENTS (gradient_editor->control_blending_items); i++) - { - if (i == (G_N_ELEMENTS (gradient_editor->control_blending_items) - 1)) - { - menuitem = gtk_radio_menu_item_new_with_label (group, _("(Varies)")); - } - else - { - menuitem = - gtk_radio_menu_item_new_with_label (group, - gettext (blending_types[i])); - } - - group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - gradient_editor->control_blending_items[i] = menuitem; - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blending_callback), - gradient_editor); - } - - /* "Varies" is always disabled */ - gtk_widget_set_sensitive (gradient_editor->control_blending_items[G_N_ELEMENTS (gradient_editor->control_blending_items) - 1], FALSE); - - return menu; -} - -static void -cpopup_blending_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegmentType type; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (!GTK_CHECK_MENU_ITEM (widget)->active) - return; /* Do nothing if the menu item is being deactivated */ - - type = (GimpGradientSegmentType) - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - seg = gradient_editor->control_sel_l; - - do - { - seg->type = type; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Coloring menu *****/ - -static GtkWidget * -cpopup_create_coloring_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GSList *group; - gint i; - - static const gchar *coloring_types[] = - { - N_("Plain RGB"), - N_("HSV (counter-clockwise hue)"), - N_("HSV (clockwise hue)") - }; - - menu = gtk_menu_new (); - group = NULL; - - for (i = 0; i < G_N_ELEMENTS (gradient_editor->control_coloring_items); i++) - { - if (i == (G_N_ELEMENTS (gradient_editor->control_coloring_items) - 1)) - { - menuitem = gtk_radio_menu_item_new_with_label(group, _("(Varies)")); - } - else - { - menuitem = - gtk_radio_menu_item_new_with_label (group, - gettext (coloring_types[i])); - } - - group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); - - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - gradient_editor->control_coloring_items[i] = menuitem; - - g_object_set_data (G_OBJECT (menuitem), "user_data", GINT_TO_POINTER (i)); - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_coloring_callback), - gradient_editor); - } - - /* "Varies" is always disabled */ - gtk_widget_set_sensitive (gradient_editor->control_coloring_items[G_N_ELEMENTS (gradient_editor->control_coloring_items) - 1], FALSE); - - return menu; -} - -static void -cpopup_coloring_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegmentColor color; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - if (! GTK_CHECK_MENU_ITEM (widget)->active) - return; /* Do nothing if the menu item is being deactivated */ - - color = (GimpGradientSegmentColor) - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "user_data")); - - seg = gradient_editor->control_sel_l; - - do - { - seg->color = color; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/*****/ - -static void -cpopup_split_midpoint_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *lseg, *rseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - seg = gradient_editor->control_sel_l; - - do - { - cpopup_split_midpoint (gradient, seg, &lseg, &rseg); - seg = rseg->next; - } - while (lseg != gradient_editor->control_sel_r); - - gradient_editor->control_sel_r = rseg; - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_split_midpoint (GimpGradient *gradient, - GimpGradientSegment *lseg, - GimpGradientSegment **newl, - GimpGradientSegment **newr) -{ - GimpRGB color; - GimpGradientSegment *newseg; - - /* Get color at original segment's midpoint */ - gimp_gradient_get_color_at (gradient, lseg->middle, &color); - - /* Create a new segment and insert it in the list */ - - newseg = gimp_gradient_segment_new (); - - newseg->prev = lseg; - newseg->next = lseg->next; - - lseg->next = newseg; - - if (newseg->next) - newseg->next->prev = newseg; - - /* Set coordinates of new segment */ - - newseg->left = lseg->middle; - newseg->right = lseg->right; - newseg->middle = (newseg->left + newseg->right) / 2.0; - - /* Set coordinates of original segment */ - - lseg->right = newseg->left; - lseg->middle = (lseg->left + lseg->right) / 2.0; - - /* Set colors of both segments */ - - newseg->right_color = lseg->right_color; - - lseg->right_color.r = newseg->left_color.r = color.r; - lseg->right_color.g = newseg->left_color.g = color.g; - lseg->right_color.b = newseg->left_color.b = color.b; - lseg->right_color.a = newseg->left_color.a = color.a; - - /* Set parameters of new segment */ - - newseg->type = lseg->type; - newseg->color = lseg->color; - - /* Done */ - - *newl = lseg; - *newr = newseg; -} - -/*****/ - -static void -cpopup_split_uniform_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GtkWidget *dialog; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *scale; - GtkObject *scale_data; - - /* Create dialog window */ - dialog = - gimp_dialog_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("Split segment uniformly") : - _("Split segments uniformly"), - "gradient_segment_split_uniformly", - gimp_standard_help_func, - "dialogs/gradient_editor/split_segments_uniformly.html", - GTK_WIN_POS_MOUSE, - FALSE, TRUE, FALSE, - - GTK_STOCK_CANCEL, cpopup_split_uniform_cancel_callback, - gradient_editor, NULL, NULL, FALSE, TRUE, - - _("Split"), cpopup_split_uniform_split_callback, - gradient_editor, NULL, NULL, TRUE, FALSE, - - NULL); - - /* The main vbox */ - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); - gtk_widget_show (vbox); - - /* Instructions */ - label = gtk_label_new (_("Please select the number of uniform parts")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - label = - gtk_label_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("in which you want to split the selected segment") : - _("in which you want to split the segments in the selection")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* Scale */ - gradient_editor->split_parts = 2; - scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); - - scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 4); - gtk_widget_show (scale); - - g_signal_connect (G_OBJECT (scale_data), "value_changed", - G_CALLBACK (cpopup_split_uniform_scale_update), - gradient_editor); - - /* Show! */ - gtk_widget_show (dialog); - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_split_uniform_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) -{ - gradient_editor->split_parts = ROUND (adjustment->value + 0.5); -} - -static void -cpopup_split_uniform_split_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg, *lseg, *rseg, *lsel; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - - seg = gradient_editor->control_sel_l; - lsel = NULL; - - do - { - aseg = seg; - - cpopup_split_uniform (gradient, seg, - gradient_editor->split_parts, &lseg, &rseg); - - if (seg == gradient_editor->control_sel_l) - lsel = lseg; - - seg = rseg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gradient_editor->control_sel_l = lsel; - gradient_editor->control_sel_r = rseg; - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_split_uniform_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); -} - -static void -cpopup_split_uniform (GimpGradient *gradient, - GimpGradientSegment *lseg, - gint parts, - GimpGradientSegment **newl, - GimpGradientSegment **newr) -{ - GimpGradientSegment *seg, *prev, *tmp; - gdouble seg_len; - gint i; - - seg_len = (lseg->right - lseg->left) / parts; /* Length of divisions */ - - seg = NULL; - prev = NULL; - tmp = NULL; - - for (i = 0; i < parts; i++) - { - seg = gimp_gradient_segment_new (); - - if (i == 0) - tmp = seg; /* Remember first segment */ - - seg->left = lseg->left + i * seg_len; - seg->right = lseg->left + (i + 1) * seg_len; - seg->middle = (seg->left + seg->right) / 2.0; - - gimp_gradient_get_color_at (gradient, seg->left, &seg->left_color); - gimp_gradient_get_color_at (gradient, seg->right, &seg->right_color); - - seg->type = lseg->type; - seg->color = lseg->color; - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - } - - /* Fix edges */ - - tmp->left_color = lseg->left_color; - - seg->right_color = lseg->right_color; - - tmp->left = lseg->left; - seg->right = lseg->right; /* To squish accumulative error */ - - /* Link in list */ - - tmp->prev = lseg->prev; - seg->next = lseg->next; - - if (lseg->prev) - lseg->prev->next = tmp; - else - gradient->segments = tmp; /* We are on leftmost segment */ - - if (lseg->next) - lseg->next->prev = seg; - - gradient->last_visited = NULL; /* Force re-search */ - - /* Done */ - - *newl = tmp; - *newr = seg; - - /* Delete old segment */ - - gimp_gradient_segment_free (lseg); -} - -/*****/ - -static void -cpopup_delete_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *lseg, *rseg, *seg, *aseg, *next; - double join; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Remember segments to the left and to the right of the selection */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - /* Cannot delete all the segments in the gradient */ - - if ((lseg == NULL) && (rseg == NULL)) - return; - - /* Calculate join point */ - - join = (gradient_editor->control_sel_l->left + - gradient_editor->control_sel_r->right) / 2.0; - - if (lseg == NULL) - join = 0.0; - else if (rseg == NULL) - join = 1.0; - - /* Move segments */ - - if (lseg != NULL) - control_compress_range (lseg, lseg, lseg->left, join); - - if (rseg != NULL) - control_compress_range (rseg, rseg, join, rseg->right); - - /* Link */ - - if (lseg) - lseg->next = rseg; - - if (rseg) - rseg->prev = lseg; - - /* Delete old segments */ - - seg = gradient_editor->control_sel_l; - - do - { - next = seg->next; - aseg = seg; - - gimp_gradient_segment_free (seg); - - seg = next; - } - while (aseg != gradient_editor->control_sel_r); - - /* Change selection */ - - if (rseg) - { - gradient_editor->control_sel_l = rseg; - gradient_editor->control_sel_r = rseg; - } - else - { - gradient_editor->control_sel_l = lseg; - gradient_editor->control_sel_r = lseg; - } - - if (lseg == NULL) - gradient->segments = rseg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_recenter_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - seg = gradient_editor->control_sel_l; - - do - { - seg->middle = (seg->left + seg->right) / 2.0; - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_redistribute_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *seg, *aseg; - gdouble left, right, seg_len; - gint num_segs; - gint i; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - /* Count number of segments in selection */ - - num_segs = 0; - seg = gradient_editor->control_sel_l; - - do - { - num_segs++; - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); - - /* Calculate new segment length */ - - left = gradient_editor->control_sel_l->left; - right = gradient_editor->control_sel_r->right; - seg_len = (right - left) / num_segs; - - /* Redistribute */ - - seg = gradient_editor->control_sel_l; - - for (i = 0; i < num_segs; i++) - { - seg->left = left + i * seg_len; - seg->right = left + (i + 1) * seg_len; - seg->middle = (seg->left + seg->right) / 2.0; - - seg = seg->next; - } - - /* Fix endpoints to squish accumulative error */ - - gradient_editor->control_sel_l->left = left; - gradient_editor->control_sel_r->right = right; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - - -/***** Control popup -> selection options functions *****/ - -static GtkWidget * -cpopup_create_sel_ops_menu (GradientEditor *gradient_editor) -{ - GtkWidget *menu; - GtkWidget *menuitem; - GtkAccelGroup *accel_group; - - menu = gtk_menu_new (); - accel_group = gradient_editor->accel_group; - - gtk_menu_set_accel_group (GTK_MENU (menu), accel_group); - - /* Flip */ - menuitem = - cpopup_create_menu_item_with_label ("", &gradient_editor->control_flip_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_flip_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'F', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Replicate */ - menuitem = - cpopup_create_menu_item_with_label ("", &gradient_editor->control_replicate_label); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_replicate_callback), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'M', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - /* Blend colors / opacity */ - menuitem = gtk_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (_("Blend endpoints' colors")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_blend_colors_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blend_colors), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'B', 0, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - menuitem = gtk_menu_item_new_with_label (_("Blend endpoints' opacity")); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - gtk_widget_show (menuitem); - gradient_editor->control_blend_opacity_menu_item = menuitem; - - g_signal_connect (G_OBJECT (menuitem), "activate", - G_CALLBACK (cpopup_blend_opacity), - gradient_editor); - gtk_widget_add_accelerator (menuitem, "activate", - accel_group, - 'B', GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED); - - return menu; -} - -static void -cpopup_flip_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - GimpGradientSegment *oseg, *oaseg; - GimpGradientSegment *seg, *prev, *tmp; - GimpGradientSegment *lseg, *rseg; - gdouble left, right; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - left = gradient_editor->control_sel_l->left; - right = gradient_editor->control_sel_r->right; - - /* Build flipped segments */ - - prev = NULL; - oseg = gradient_editor->control_sel_r; - tmp = NULL; - - do - { - seg = gimp_gradient_segment_new (); - - if (prev == NULL) - { - seg->left = left; - tmp = seg; /* Remember first segment */ - } - else - seg->left = left + right - oseg->right; - - seg->middle = left + right - oseg->middle; - seg->right = left + right - oseg->left; - - seg->left_color = oseg->right_color; - - seg->right_color = oseg->left_color; - - switch (oseg->type) - { - case GRAD_SPHERE_INCREASING: - seg->type = GRAD_SPHERE_DECREASING; - break; - - case GRAD_SPHERE_DECREASING: - seg->type = GRAD_SPHERE_INCREASING; - break; - - default: - seg->type = oseg->type; - } - - switch (oseg->color) - { - case GRAD_HSV_CCW: - seg->color = GRAD_HSV_CW; - break; - - case GRAD_HSV_CW: - seg->color = GRAD_HSV_CCW; - break; - - default: - seg->color = oseg->color; - } - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - - oaseg = oseg; - oseg = oseg->prev; /* Move backwards! */ - } - while (oaseg != gradient_editor->control_sel_l); - - seg->right = right; /* Squish accumulative error */ - - /* Free old segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - oseg = gradient_editor->control_sel_l; - - do - { - oaseg = oseg->next; - gimp_gradient_segment_free (oseg); - oseg = oaseg; - } - while (oaseg != rseg); - - /* Link in new segments */ - - if (lseg) - lseg->next = tmp; - else - gradient->segments = tmp; - - tmp->prev = lseg; - - seg->next = rseg; - - if (rseg) - rseg->prev = seg; - - /* Reset selection */ - - gradient_editor->control_sel_l = tmp; - gradient_editor->control_sel_r = seg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GtkWidget *dialog; - GtkWidget *vbox; - GtkWidget *label; - GtkWidget *scale; - GtkObject *scale_data; - - /* Create dialog window */ - dialog = - gimp_dialog_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("Replicate segment") : - _("Replicate selection"), - "gradient_segment_replicate", - gimp_standard_help_func, - "dialogs/gradient_editor/replicate_segment.html", - GTK_WIN_POS_MOUSE, - FALSE, TRUE, FALSE, - - _("Replicate"), cpopup_do_replicate_callback, - gradient_editor, NULL, NULL, FALSE, FALSE, - GTK_STOCK_CANCEL, cpopup_replicate_cancel_callback, - gradient_editor, NULL, NULL, TRUE, TRUE, - - NULL); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox); - gtk_widget_show (vbox); - - /* Instructions */ - label = gtk_label_new (_("Please select the number of times")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - label = gtk_label_new ((gradient_editor->control_sel_l == - gradient_editor->control_sel_r) ? - _("you want to replicate the selected segment") : - _("you want to replicate the selection")); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - /* Scale */ - gradient_editor->replicate_times = 2; - scale_data = gtk_adjustment_new (2.0, 2.0, 21.0, 1.0, 1.0, 1.0); - - scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data)); - gtk_scale_set_digits (GTK_SCALE (scale), 0); - gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 4); - gtk_widget_show (scale); - - g_signal_connect (G_OBJECT (scale_data), "value_changed", - G_CALLBACK (cpopup_replicate_scale_update), - gradient_editor); - - /* Show! */ - gtk_widget_show (dialog); - gtk_widget_set_sensitive (gradient_editor->shell, FALSE); -} - -static void -cpopup_replicate_scale_update (GtkAdjustment *adjustment, - GradientEditor *gradient_editor) -{ - gradient_editor->replicate_times = (int) (adjustment->value + 0.5); -} - -static void -cpopup_do_replicate_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - GimpGradient *gradient; - gdouble sel_left, sel_right, sel_len; - gdouble new_left; - gdouble factor; - GimpGradientSegment *prev, *seg, *tmp; - GimpGradientSegment *oseg, *oaseg; - GimpGradientSegment *lseg, *rseg; - gint i; - - gradient = gimp_context_get_gradient (gradient_editor->context); - - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); - - /* Remember original parameters */ - sel_left = gradient_editor->control_sel_l->left; - sel_right = gradient_editor->control_sel_r->right; - sel_len = sel_right - sel_left; - - factor = 1.0 / gradient_editor->replicate_times; - - /* Build replicated segments */ - - prev = NULL; - seg = NULL; - tmp = NULL; - - for (i = 0; i < gradient_editor->replicate_times; i++) - { - /* Build one cycle */ - - new_left = sel_left + i * factor * sel_len; - - oseg = gradient_editor->control_sel_l; - - do - { - seg = gimp_gradient_segment_new (); - - if (prev == NULL) - { - seg->left = sel_left; - tmp = seg; /* Remember first segment */ - } - else - seg->left = new_left + factor * (oseg->left - sel_left); - - seg->middle = new_left + factor * (oseg->middle - sel_left); - seg->right = new_left + factor * (oseg->right - sel_left); - - seg->left_color = oseg->right_color; - - seg->right_color = oseg->right_color; - - seg->type = oseg->type; - seg->color = oseg->color; - - seg->prev = prev; - seg->next = NULL; - - if (prev) - prev->next = seg; - - prev = seg; - - oaseg = oseg; - oseg = oseg->next; - } - while (oaseg != gradient_editor->control_sel_r); - } - - seg->right = sel_right; /* Squish accumulative error */ - - /* Free old segments */ - - lseg = gradient_editor->control_sel_l->prev; - rseg = gradient_editor->control_sel_r->next; - - oseg = gradient_editor->control_sel_l; - - do - { - oaseg = oseg->next; - gimp_gradient_segment_free (oseg); - oseg = oaseg; - } - while (oaseg != rseg); - - /* Link in new segments */ - - if (lseg) - lseg->next = tmp; - else - gradient->segments = tmp; - - tmp->prev = lseg; - - seg->next = rseg; - - if (rseg) - rseg->prev = seg; - - /* Reset selection */ - - gradient_editor->control_sel_l = tmp; - gradient_editor->control_sel_r = seg; - - /* Done */ - - gimp_data_dirty (GIMP_DATA (gradient)); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT | GRAD_UPDATE_CONTROL); -} - -static void -cpopup_replicate_cancel_callback (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - gtk_widget_destroy (gtk_widget_get_toplevel (widget)); - gtk_widget_set_sensitive (gradient_editor->shell, TRUE); -} - -static void -cpopup_blend_colors (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_r->right_color, - TRUE, FALSE); - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -static void -cpopup_blend_opacity (GtkWidget *widget, - GradientEditor *gradient_editor) -{ - cpopup_blend_endpoints (gradient_editor, - &gradient_editor->control_sel_l->left_color, - &gradient_editor->control_sel_r->right_color, - FALSE, TRUE); - - gimp_data_dirty (GIMP_DATA (gimp_context_get_gradient (gradient_editor->context))); - - ed_update_editor (gradient_editor, GRAD_UPDATE_GRADIENT); -} - -/***** Main blend function *****/ - -static void -cpopup_blend_endpoints (GradientEditor *gradient_editor, - GimpRGB *rgb1, - GimpRGB *rgb2, - gboolean blend_colors, - gboolean blend_opacity) -{ - GimpRGB d; - gdouble left, len; - GimpGradientSegment *seg; - GimpGradientSegment *aseg; - - d.r = rgb2->r - rgb1->r; - d.g = rgb2->g - rgb1->g; - d.b = rgb2->b - rgb1->b; - d.a = rgb2->a - rgb1->a; - - left = gradient_editor->control_sel_l->left; - len = gradient_editor->control_sel_r->right - left; - - seg = gradient_editor->control_sel_l; - - do - { - if (blend_colors) - { - seg->left_color.r = rgb1->r + (seg->left - left) / len * d.r; - seg->left_color.g = rgb1->g + (seg->left - left) / len * d.g; - seg->left_color.b = rgb1->b + (seg->left - left) / len * d.b; - - seg->right_color.r = rgb1->r + (seg->right - left) / len * d.r; - seg->right_color.g = rgb1->g + (seg->right - left) / len * d.g; - seg->right_color.b = rgb1->b + (seg->right - left) / len * d.b; - } - - if (blend_opacity) - { - seg->left_color.a = rgb1->a + (seg->left - left) / len * d.a; - seg->right_color.a = rgb1->a + (seg->right - left) / len * d.a; - } - - aseg = seg; - seg = seg->next; - } - while (aseg != gradient_editor->control_sel_r); -} - /***** Segment functions *****/ static void -seg_get_closest_handle (GimpGradient *grad, - gdouble pos, - GimpGradientSegment **seg, - control_drag_mode_t *handle) +seg_get_closest_handle (GimpGradient *grad, + gdouble pos, + GimpGradientSegment **seg, + GradientEditorDragMode *handle) { gdouble l_delta, m_delta, r_delta; diff --git a/app/widgets/gimpgradienteditor.h b/app/widgets/gimpgradienteditor.h index bf4bf14918..abfb2aea90 100644 --- a/app/widgets/gimpgradienteditor.h +++ b/app/widgets/gimpgradienteditor.h @@ -23,14 +23,89 @@ #define __GRADIENT_EDITOR_H__ -typedef struct _GradientEditor GradientEditor; +#define GRAD_NUM_COLORS 10 -GradientEditor * gradient_editor_new (Gimp *gimp); +typedef enum +{ + GRAD_DRAG_NONE = 0, + GRAD_DRAG_LEFT, + GRAD_DRAG_MIDDLE, + GRAD_DRAG_ALL +} GradientEditorDragMode; -void gradient_editor_set_gradient (GradientEditor *gradient_editor, - GimpGradient *gradient); -void gradient_editor_free (GradientEditor *gradient_editor); +typedef enum +{ + GRAD_UPDATE_GRADIENT = 1 << 0, + GRAD_UPDATE_PREVIEW = 1 << 1, + GRAD_UPDATE_CONTROL = 1 << 2, + GRAD_RESET_CONTROL = 1 << 3 +} GradientEditorUpdateMask; + + +struct _GradientEditor +{ + GtkWidget *shell; + + GtkWidget *name; + + GtkWidget *hint_label; + GtkWidget *scrollbar; + GtkWidget *preview; + GtkWidget *control; + + GimpContext *context; + + /* Zoom and scrollbar */ + guint zoom_factor; + GtkObject *scroll_data; + + /* Instant update */ + gboolean instant_update; + + /* Gradient preview */ + guchar *preview_rows[2]; /* For caching redraw info */ + gint preview_last_x; + gboolean preview_button_down; + + /* Gradient control */ + GdkPixmap *control_pixmap; + GimpGradientSegment *control_drag_segment; /* Segment which is being dragged */ + GimpGradientSegment *control_sel_l; /* Left segment of selection */ + GimpGradientSegment *control_sel_r; /* Right segment of selection */ + GradientEditorDragMode control_drag_mode; /* What is being dragged? */ + guint32 control_click_time; /* Time when mouse was pressed */ + gboolean control_compress; /* Compressing/expanding handles */ + gint control_last_x; /* Last mouse position when dragging */ + gdouble control_last_gx; /* Last position (wrt gradient) when dragging */ + gdouble control_orig_pos; /* Original click position when dragging */ + + /* Split uniformly dialog */ + gint split_parts; + + /* Replicate dialog */ + gint replicate_times; + + /* Saved colors */ + GimpRGB saved_colors[GRAD_NUM_COLORS]; + + /* Color dialogs */ + GimpGradientSegment *left_saved_segments; + gboolean left_saved_dirty; + + GimpGradientSegment *right_saved_segments; + gboolean right_saved_dirty; +}; + + +GradientEditor * gradient_editor_new (Gimp *gimp); + +void gradient_editor_set_gradient (GradientEditor *gradient_editor, + GimpGradient *gradient); +void gradient_editor_free (GradientEditor *gradient_editor); + +void gradient_editor_update (GradientEditor *gradient_editor, + GradientEditorUpdateMask flags); #endif /* __GRADIENT_EDITOR_H__ */ diff --git a/app/widgets/gimpitemfactory.c b/app/widgets/gimpitemfactory.c index 80a43e691d..59fe3ac03b 100644 --- a/app/widgets/gimpitemfactory.c +++ b/app/widgets/gimpitemfactory.c @@ -53,6 +53,7 @@ #include "documents-commands.h" #include "edit-commands.h" #include "file-commands.h" +#include "gradient-editor-commands.h" #include "gradients-commands.h" #include "image-commands.h" #include "layers-commands.h" @@ -1446,6 +1447,324 @@ static GimpItemFactoryEntry patterns_entries[] = }; +/***** *****/ + +static GimpItemFactoryEntry gradient_editor_entries[] = +{ + { { N_("/Left Endpoint's Color..."), NULL, + gradient_editor_left_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Left Color From/Left Neighbor's Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/Right Endpoint"), NULL, + gradient_editor_load_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/FG Color"), NULL, + gradient_editor_load_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Left Color From/BG Color"), NULL, + gradient_editor_load_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Left Color From/---"), + + { { "/Load Left Color From/01", NULL, + gradient_editor_load_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/02", NULL, + gradient_editor_load_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/03", NULL, + gradient_editor_load_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/04", NULL, + gradient_editor_load_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/05", NULL, + gradient_editor_load_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/06", NULL, + gradient_editor_load_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/07", NULL, + gradient_editor_load_left_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/08", NULL, + gradient_editor_load_left_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/09", NULL, + gradient_editor_load_left_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Left Color From/10", NULL, + gradient_editor_load_left_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Left Color To")), + + { { "/Save Left Color To/01", NULL, + gradient_editor_save_left_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/02", NULL, + gradient_editor_save_left_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/03", NULL, + gradient_editor_save_left_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/04", NULL, + gradient_editor_save_left_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/05", NULL, + gradient_editor_save_left_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/06", NULL, + gradient_editor_save_left_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/07", NULL, + gradient_editor_save_left_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/08", NULL, + gradient_editor_save_left_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/09", NULL, + gradient_editor_save_left_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Left Color To/10", NULL, + gradient_editor_save_left_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Right Endpoint's Color..."), NULL, + gradient_editor_right_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + { { N_("/Load Right Color From/Right Neighbor's Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/Left Endpoint"), NULL, + gradient_editor_load_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/FG Color"), NULL, + gradient_editor_load_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { N_("/Load Right Color From/BG Color"), NULL, + gradient_editor_load_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/Load Right Color From/---"), + + { { "/Load Right Color From/01", NULL, + gradient_editor_load_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/02", NULL, + gradient_editor_load_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/03", NULL, + gradient_editor_load_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/04", NULL, + gradient_editor_load_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/05", NULL, + gradient_editor_load_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/06", NULL, + gradient_editor_load_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/07", NULL, + gradient_editor_load_right_cmd_callback, 10 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/08", NULL, + gradient_editor_load_right_cmd_callback, 11 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/09", NULL, + gradient_editor_load_right_cmd_callback, 12 }, + NULL, + NULL, NULL }, + { { "/Load Right Color From/10", NULL, + gradient_editor_load_right_cmd_callback, 13 }, + NULL, + NULL, NULL }, + + BRANCH (N_("/Save Right Color To")), + + { { "/Save Right Color To/01", NULL, + gradient_editor_save_right_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/02", NULL, + gradient_editor_save_right_cmd_callback, 1 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/03", NULL, + gradient_editor_save_right_cmd_callback, 2 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/04", NULL, + gradient_editor_save_right_cmd_callback, 3 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/05", NULL, + gradient_editor_save_right_cmd_callback, 4 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/06", NULL, + gradient_editor_save_right_cmd_callback, 5 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/07", NULL, + gradient_editor_save_right_cmd_callback, 6 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/08", NULL, + gradient_editor_save_right_cmd_callback, 7 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/09", NULL, + gradient_editor_save_right_cmd_callback, 8 }, + NULL, + NULL, NULL }, + { { "/Save Right Color To/10", NULL, + gradient_editor_save_right_cmd_callback, 9 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/blendingfunction/Linear"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_LINEAR, "" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Curved"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_CURVED, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Sinusodial"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SINE, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (increasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_INCREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/Spherical (decreasing)"), NULL, + gradient_editor_blending_func_cmd_callback, + GRAD_SPHERE_DECREASING, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + { { N_("/blendingfunction/(Varies)"), NULL, NULL, + 0, "/blendingfunction/Linear" }, + NULL, + NULL, NULL }, + + { { N_("/coloringtype/RGB"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_RGB, "" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (counter-clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CCW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/HSV (clockwise hue)"), NULL, + gradient_editor_coloring_type_cmd_callback, + GRAD_HSV_CW, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + { { N_("/coloringtype/(Varies)"), NULL, NULL, + 0, "/coloringtype/RGB" }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { "/flip", "F", + gradient_editor_flip_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/replicate", "R", + gradient_editor_replicate_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splitmidpoint", "S", + gradient_editor_split_midpoint_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/splituniformly", "U", + gradient_editor_split_uniformly_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/delete", "D", + gradient_editor_delete_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/recenter", "C", + gradient_editor_recenter_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { "/redistribute", "C", + gradient_editor_redistribute_cmd_callback, 0 }, + NULL, + NULL, NULL }, + + SEPARATOR ("/---"), + + { { N_("/Blend Endpoints' Colors"), "B", + gradient_editor_blend_color_cmd_callback, 0 }, + NULL, + NULL, NULL }, + { { N_("/Blend Endpoints' Opacity"), "B", + gradient_editor_blend_opacity_cmd_callback, 0 }, + NULL, + NULL, NULL }, +}; + + /***** *****/ static GimpItemFactoryEntry gradients_entries[] = @@ -1601,20 +1920,21 @@ static GimpItemFactoryEntry documents_entries[] = static gboolean menus_initialized = FALSE; -static GtkItemFactory *toolbox_factory = NULL; -static GtkItemFactory *image_factory = NULL; -static GtkItemFactory *load_factory = NULL; -static GtkItemFactory *save_factory = NULL; -static GtkItemFactory *layers_factory = NULL; -static GtkItemFactory *channels_factory = NULL; -static GtkItemFactory *paths_factory = NULL; -static GtkItemFactory *dialogs_factory = NULL; -static GtkItemFactory *brushes_factory = NULL; -static GtkItemFactory *patterns_factory = NULL; -static GtkItemFactory *gradients_factory = NULL; -static GtkItemFactory *palettes_factory = NULL; -static GtkItemFactory *buffers_factory = NULL; -static GtkItemFactory *documents_factory = NULL; +static GtkItemFactory *toolbox_factory = NULL; +static GtkItemFactory *image_factory = NULL; +static GtkItemFactory *load_factory = NULL; +static GtkItemFactory *save_factory = NULL; +static GtkItemFactory *layers_factory = NULL; +static GtkItemFactory *channels_factory = NULL; +static GtkItemFactory *paths_factory = NULL; +static GtkItemFactory *dialogs_factory = NULL; +static GtkItemFactory *brushes_factory = NULL; +static GtkItemFactory *patterns_factory = NULL; +static GtkItemFactory *gradient_editor_factory = NULL; +static GtkItemFactory *gradients_factory = NULL; +static GtkItemFactory *palettes_factory = NULL; +static GtkItemFactory *buffers_factory = NULL; +static GtkItemFactory *documents_factory = NULL; /* public functions */ @@ -1760,6 +2080,13 @@ menus_init (Gimp *gimp) gimp, FALSE); + gradient_editor_factory = menus_item_factory_new (GTK_TYPE_MENU, + "", "gradient_editor", + G_N_ELEMENTS (gradient_editor_entries), + gradient_editor_entries, + gimp, + FALSE); + gradients_factory = menus_item_factory_new (GTK_TYPE_MENU, "", "gradients", G_N_ELEMENTS (gradients_entries), @@ -1931,6 +2258,12 @@ menus_exit (Gimp *gimp) patterns_factory = NULL; } + if (gradient_editor_factory) + { + g_object_unref (G_OBJECT (gradient_editor_factory)); + gradient_editor_factory = NULL; + } + if (gradients_factory) { g_object_unref (G_OBJECT (gradients_factory)); @@ -2205,6 +2538,12 @@ menus_get_patterns_factory (void) return patterns_factory; } +GtkItemFactory * +menus_get_gradient_editor_factory (void) +{ + return gradient_editor_factory; +} + GtkItemFactory * menus_get_gradients_factory (void) { @@ -2264,6 +2603,222 @@ menus_create_item_from_full_path (GimpItemFactoryEntry *entry, menus_create_item (item_factory, entry, callback_data, 2, TRUE, FALSE); } +void +menus_set_active (gchar *path, + gboolean active) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), active); + else + widget = NULL; + } + + if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) + g_warning ("Unable to set \"active\" for menu which doesn't exist:\n%s", + path); +} + +void +menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget; + GtkWidget *preview = NULL; + GtkWidget *label = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (color != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + +#define COLOR_BOX_WIDTH 24 +#define COLOR_BOX_HEIGHT 16 + + if (! ifactory) + return; + + widget = gtk_item_factory_get_widget (ifactory, path); + + if (! widget) + return; + + if (GTK_IS_HBOX (GTK_BIN (widget)->child)) + { + preview = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "preview"); + label = g_object_get_data (G_OBJECT (GTK_BIN (widget)->child), + "label"); + } + else if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + GtkWidget *hbox; + + label = GTK_BIN (widget)->child; + + g_object_ref (G_OBJECT (label)); + + gtk_container_remove (GTK_CONTAINER (widget), label); + + hbox = gtk_hbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (widget), hbox); + gtk_widget_show (hbox); + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (preview), + COLOR_BOX_WIDTH, COLOR_BOX_HEIGHT); + gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0); + gtk_widget_show (preview); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + g_object_unref (G_OBJECT (label)); + + g_object_set_data (G_OBJECT (hbox), "preview", preview); + g_object_set_data (G_OBJECT (hbox), "label", label); + } + + if (preview) + { + guchar rows[3][COLOR_BOX_WIDTH * 3]; + gint x, y; + gint r0, g0, b0; + gint r1, g1, b1; + guchar *p0, *p1, *p2; + + /* Fill rows */ + + r0 = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.0; + r1 = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + g0 = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.0; + g1 = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + b0 = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.0; + b1 = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.0; + + p0 = rows[0]; + p1 = rows[1]; + p2 = rows[2]; + + for (x = 0; x < COLOR_BOX_WIDTH; x++) + { + if ((x == 0) || (x == (COLOR_BOX_WIDTH - 1))) + { + *p0++ = 0; + *p0++ = 0; + *p0++ = 0; + + *p1++ = 0; + *p1++ = 0; + *p1++ = 0; + } + else if ((x / GIMP_CHECK_SIZE) & 1) + { + *p0++ = r1; + *p0++ = g1; + *p0++ = b1; + + *p1++ = r0; + *p1++ = g0; + *p1++ = b0; + } + else + { + *p0++ = r0; + *p0++ = g0; + *p0++ = b0; + + *p1++ = r1; + *p1++ = g1; + *p1++ = b1; + } + + *p2++ = 0; + *p2++ = 0; + *p2++ = 0; + } + + /* Fill preview */ + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, 0, COLOR_BOX_WIDTH); + + for (y = 1; y < (COLOR_BOX_HEIGHT - 1); y++) + if ((y / GIMP_CHECK_SIZE) & 1) + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[1], + 0, y, COLOR_BOX_WIDTH); + else + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[0], + 0, y, COLOR_BOX_WIDTH); + + gtk_preview_draw_row (GTK_PREVIEW (preview), rows[2], + 0, y, COLOR_BOX_WIDTH); + } + + if (label && set_label) + { + gchar *str; + + str = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"), + color->r, color->g, color->b, color->a); + + gtk_label_set_text (GTK_LABEL (label), str); + + g_free (str); + } + +#undef COLOR_BOX_WIDTH +#undef COLOR_BOX_HEIGHT +} + +void +menus_set_label (gchar *path, + const gchar *label) +{ + GtkItemFactory *ifactory; + GtkWidget *widget = NULL; + + g_return_if_fail (path != NULL); + g_return_if_fail (label != NULL); + g_return_if_fail (menus_initialized); + + ifactory = gtk_item_factory_from_path (path); + + if (ifactory) + { + widget = gtk_item_factory_get_widget (ifactory, path); + + if (widget) + { + if (GTK_IS_MENU (widget)) + { + widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); + } + + if (GTK_IS_LABEL (GTK_BIN (widget)->child)) + { + gtk_label_set_text (GTK_LABEL (GTK_BIN (widget)->child), label); + } + } + } +} + void menus_set_sensitive (gchar *path, gboolean sensitive) @@ -2290,11 +2845,11 @@ menus_set_sensitive (gchar *path, } void -menus_set_state (gchar *path, - gboolean state) +menus_set_visible (gchar *path, + gboolean visible) { GtkItemFactory *ifactory; - GtkWidget *widget = NULL; + GtkWidget *widget; g_return_if_fail (path != NULL); g_return_if_fail (menus_initialized); @@ -2305,15 +2860,14 @@ menus_set_state (gchar *path, { widget = gtk_item_factory_get_widget (ifactory, path); - if (widget && GTK_IS_CHECK_MENU_ITEM (widget)) - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), state); - else - widget = NULL; + if (widget) + { + if (visible) + gtk_widget_show (widget); + else + gtk_widget_hide (widget); + } } - - if ((!ifactory || !widget) && ! strstr (path, "Script-Fu")) - g_warning ("Unable to set state for menu which doesn't exist:\n%s", - path); } void diff --git a/app/widgets/gimpitemfactory.h b/app/widgets/gimpitemfactory.h index 02b2e1cce6..079a73ea65 100644 --- a/app/widgets/gimpitemfactory.h +++ b/app/widgets/gimpitemfactory.h @@ -33,34 +33,43 @@ struct _GimpItemFactoryEntry }; -void menus_init (Gimp *gimp); -void menus_exit (Gimp *gimp); -void menus_restore (Gimp *gimp); +void menus_init (Gimp *gimp); +void menus_exit (Gimp *gimp); +void menus_restore (Gimp *gimp); -GtkItemFactory * menus_get_toolbox_factory (void); -GtkItemFactory * menus_get_image_factory (void); -GtkItemFactory * menus_get_load_factory (void); -GtkItemFactory * menus_get_save_factory (void); -GtkItemFactory * menus_get_layers_factory (void); -GtkItemFactory * menus_get_channels_factory (void); -GtkItemFactory * menus_get_paths_factory (void); -GtkItemFactory * menus_get_dialogs_factory (void); -GtkItemFactory * menus_get_brushes_factory (void); -GtkItemFactory * menus_get_patterns_factory (void); -GtkItemFactory * menus_get_gradients_factory (void); -GtkItemFactory * menus_get_palettes_factory (void); -GtkItemFactory * menus_get_buffers_factory (void); -GtkItemFactory * menus_get_documents_factory (void); +GtkItemFactory * menus_get_toolbox_factory (void); +GtkItemFactory * menus_get_image_factory (void); +GtkItemFactory * menus_get_load_factory (void); +GtkItemFactory * menus_get_save_factory (void); +GtkItemFactory * menus_get_layers_factory (void); +GtkItemFactory * menus_get_channels_factory (void); +GtkItemFactory * menus_get_paths_factory (void); +GtkItemFactory * menus_get_dialogs_factory (void); +GtkItemFactory * menus_get_brushes_factory (void); +GtkItemFactory * menus_get_patterns_factory (void); +GtkItemFactory * menus_get_gradient_editor_factory (void); +GtkItemFactory * menus_get_gradients_factory (void); +GtkItemFactory * menus_get_palettes_factory (void); +GtkItemFactory * menus_get_buffers_factory (void); +GtkItemFactory * menus_get_documents_factory (void); void menus_create_item_from_full_path (GimpItemFactoryEntry *entry, gchar *domain_name, gpointer callback_data); +void menus_set_active (gchar *path, + gboolean state); +void menus_set_color (gchar *path, + const GimpRGB *color, + gboolean set_label); +void menus_set_label (gchar *path, + const gchar *label); void menus_set_sensitive (gchar *path, gboolean sensitive); -void menus_set_state (gchar *path, - gboolean state); +void menus_set_visible (gchar *path, + gboolean visible); + void menus_destroy (gchar *path);