diff --git a/ChangeLog b/ChangeLog index 673f932ec1..d9732057c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2004-05-27 Michael Natterer + + * app/widgets/widgets-enums.[ch]: added enum GimpActiveColor which + can be one of { FOREGROUND, BACKGROUND }, + + * app/widgets/Makefile.am + * app/widgets/gimpfgbgeditor.[ch]: new widget implementing the + FG/BG/Swap/Default color area known from the toolbox. + + * app/widgets/gimptoolbox-color-area.c: use the new widget. + + * app/widgets/gimpcoloreditor.[ch]: replaced the FG/BG buttons and + the color area by a GimpFgBgEditor. + 2004-05-27 Michael Natterer * app/widgets/gimpdocumentview.c (gimp_document_view_new): diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am index 23a3f277c5..6970a42940 100644 --- a/app/widgets/Makefile.am +++ b/app/widgets/Makefile.am @@ -111,6 +111,8 @@ libappwidgets_a_sources = \ gimpenumwidgets.h \ gimperrorconsole.c \ gimperrorconsole.h \ + gimpfgbgeditor.c \ + gimpfgbgeditor.h \ gimpfiledialog.c \ gimpfiledialog.h \ gimpfontview.c \ diff --git a/app/widgets/gimpcoloreditor.c b/app/widgets/gimpcoloreditor.c index a4d9608546..2ebb56db4f 100644 --- a/app/widgets/gimpcoloreditor.c +++ b/app/widgets/gimpcoloreditor.c @@ -35,6 +35,7 @@ #include "gimpcoloreditor.h" #include "gimpdocked.h" +#include "gimpfgbgeditor.h" #include "gimpsessioninfo.h" #include "gimp-intl.h" @@ -66,11 +67,10 @@ static void gimp_color_editor_color_changed (GimpColorSelector *selector, const GimpRGB *rgb, const GimpHSV *hsv, GimpColorEditor *editor); -static void gimp_color_editor_area_changed (GimpColorArea *color_area, - GimpColorEditor *editor); static void gimp_color_editor_tab_toggled (GtkWidget *widget, GimpColorEditor *editor); -static void gimp_color_editor_fg_bg_toggled (GtkWidget *widget, +static void gimp_color_editor_fg_bg_notify (GtkWidget *widget, + GParamSpec *pspec, GimpColorEditor *editor); static void gimp_color_editor_color_picked (GtkWidget *widget, const GimpRGB *rgb, @@ -90,14 +90,14 @@ gimp_color_editor_get_type (void) static const GTypeInfo editor_info = { sizeof (GimpColorEditorClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_color_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpColorEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_color_editor_init, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gimp_color_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpColorEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_color_editor_init, }; static const GInterfaceInfo docked_iface_info = { @@ -120,11 +120,8 @@ gimp_color_editor_get_type (void) static void gimp_color_editor_class_init (GimpColorEditorClass* klass) { - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = GTK_OBJECT_CLASS (klass); - widget_class = GTK_WIDGET_CLASS (klass); + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); parent_class = g_type_class_peek_parent (klass); @@ -231,71 +228,15 @@ gimp_color_editor_init (GimpColorEditor *editor) editor); } - /* FG/BG toggles */ - { - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *frame; - gint i; + /* FG/BG editor */ + editor->fg_bg = gimp_fg_bg_editor_new (NULL); + gtk_widget_set_size_request (editor->fg_bg, -1, 48); + gtk_box_pack_start (GTK_BOX (editor), editor->fg_bg, FALSE, FALSE, 0); + gtk_widget_show (editor->fg_bg); - static const gchar *labels[] = - { - N_("FG"), N_("BG") - }; - static const gchar *tips[] = - { - N_("Edit Foreground Color"), N_("Edit Background Color") - }; - - hbox = gtk_hbox_new (FALSE, button_spacing); - gtk_box_pack_start (GTK_BOX (editor), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - vbox = gtk_vbox_new (FALSE, button_spacing); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - group = NULL; - - for (i = 0; i < G_N_ELEMENTS (labels); i++) - { - GtkWidget *button; - - button = gtk_radio_button_new_with_mnemonic (group, - gettext (labels[i])); - group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - gtk_widget_show (button); - - gimp_help_set_help_data (button, gettext (tips[i]), NULL); - - g_object_set_data (G_OBJECT (button), "edit_bg", - GINT_TO_POINTER (i == 1)); - - if ((i == 1) == editor->edit_bg) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - - g_signal_connect (button, "toggled", - G_CALLBACK (gimp_color_editor_fg_bg_toggled), - editor); - } - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); - gtk_box_pack_end (GTK_BOX (hbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - - editor->color_area = gimp_color_area_new (&rgb, GIMP_COLOR_AREA_FLAT, - GDK_BUTTON1_MASK | - GDK_BUTTON2_MASK); - gtk_container_add (GTK_CONTAINER (frame), editor->color_area); - gtk_widget_show (editor->color_area); - - g_signal_connect (editor->color_area, "color_changed", - G_CALLBACK (gimp_color_editor_area_changed), - editor); - } + g_signal_connect (editor->fg_bg, "notify::active-color", + G_CALLBACK (gimp_color_editor_fg_bg_notify), + editor); } static void @@ -413,6 +354,8 @@ gimp_color_editor_set_context (GimpDocked *docked, gimp_color_editor_fg_changed (editor->context, &rgb, editor); } } + + gimp_fg_bg_editor_set_context (GIMP_FG_BG_EDITOR (editor->fg_bg), context); } static void @@ -474,20 +417,13 @@ gimp_color_editor_fg_changed (GimpContext *context, g_signal_handlers_block_by_func (editor->notebook, gimp_color_editor_color_changed, editor); - g_signal_handlers_block_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); gimp_color_selector_set_color (GIMP_COLOR_SELECTOR (editor->notebook), rgb, &hsv); - gimp_color_area_set_color (GIMP_COLOR_AREA (editor->color_area), rgb); g_signal_handlers_unblock_by_func (editor->notebook, gimp_color_editor_color_changed, editor); - g_signal_handlers_unblock_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); } } @@ -505,20 +441,13 @@ gimp_color_editor_bg_changed (GimpContext *context, g_signal_handlers_block_by_func (editor->notebook, gimp_color_editor_color_changed, editor); - g_signal_handlers_block_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); gimp_color_selector_set_color (GIMP_COLOR_SELECTOR (editor->notebook), rgb, &hsv); - gimp_color_area_set_color (GIMP_COLOR_AREA (editor->color_area), rgb); g_signal_handlers_unblock_by_func (editor->notebook, gimp_color_editor_color_changed, editor); - g_signal_handlers_unblock_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); } } @@ -555,30 +484,6 @@ gimp_color_editor_color_changed (GimpColorSelector *selector, editor); } } - - g_signal_handlers_block_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); - - gimp_color_area_set_color (GIMP_COLOR_AREA (editor->color_area), rgb); - - g_signal_handlers_unblock_by_func (editor->color_area, - gimp_color_editor_area_changed, - editor); -} - -static void -gimp_color_editor_area_changed (GimpColorArea *color_area, - GimpColorEditor *editor) -{ - GimpRGB rgb; - GimpHSV hsv; - - gimp_color_area_get_color (color_area, &rgb); - gimp_rgb_to_hsv (&rgb, &hsv); - - gimp_color_selector_set_color (GIMP_COLOR_SELECTOR (editor->notebook), - &rgb, &hsv); } static void @@ -607,34 +512,32 @@ gimp_color_editor_tab_toggled (GtkWidget *widget, } static void -gimp_color_editor_fg_bg_toggled (GtkWidget *widget, - GimpColorEditor *editor) +gimp_color_editor_fg_bg_notify (GtkWidget *widget, + GParamSpec *pspec, + GimpColorEditor *editor) { - if (GTK_TOGGLE_BUTTON (widget)->active) + gboolean edit_bg; + + edit_bg = (GIMP_FG_BG_EDITOR (widget)->active_color == + GIMP_ACTIVE_COLOR_BACKGROUND); + + if (edit_bg != editor->edit_bg) { - gboolean edit_bg; + editor->edit_bg = edit_bg; - edit_bg = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), - "edit_bg")); - - if (edit_bg != editor->edit_bg) + if (editor->context) { - editor->edit_bg = edit_bg; + GimpRGB rgb; - if (editor->context) + if (edit_bg) { - GimpRGB rgb; - - if (edit_bg) - { - gimp_context_get_background (editor->context, &rgb); - gimp_color_editor_bg_changed (editor->context, &rgb, editor); - } - else - { - gimp_context_get_foreground (editor->context, &rgb); - gimp_color_editor_fg_changed (editor->context, &rgb, editor); - } + gimp_context_get_background (editor->context, &rgb); + gimp_color_editor_bg_changed (editor->context, &rgb, editor); + } + else + { + gimp_context_get_foreground (editor->context, &rgb); + gimp_color_editor_fg_changed (editor->context, &rgb, editor); } } } @@ -645,5 +548,11 @@ gimp_color_editor_color_picked (GtkWidget *widget, const GimpRGB *rgb, GimpColorEditor *editor) { - gimp_color_area_set_color (GIMP_COLOR_AREA (editor->color_area), rgb); + if (editor->context) + { + if (editor->edit_bg) + gimp_context_set_background (editor->context, rgb); + else + gimp_context_set_foreground (editor->context, rgb); + } } diff --git a/app/widgets/gimpcoloreditor.h b/app/widgets/gimpcoloreditor.h index 76468a1f6e..26422cfedf 100644 --- a/app/widgets/gimpcoloreditor.h +++ b/app/widgets/gimpcoloreditor.h @@ -45,7 +45,7 @@ struct _GimpColorEditor GtkWidget *hbox; GtkWidget *notebook; - GtkWidget *color_area; + GtkWidget *fg_bg; }; struct _GimpColorEditorClass diff --git a/app/widgets/gimpfgbgeditor.c b/app/widgets/gimpfgbgeditor.c new file mode 100644 index 0000000000..90c10bd07b --- /dev/null +++ b/app/widgets/gimpfgbgeditor.c @@ -0,0 +1,632 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpfgbgeditor.c + * Copyright (C) 2004 Michael Natterer + * + * 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 + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "widgets-types.h" + +#include "core/gimpcontext.h" +#include "core/gimpmarshal.h" + +#include "gimpdnd.h" +#include "gimpfgbgeditor.h" + + +enum +{ + PROP_0, + PROP_CONTEXT, + PROP_ACTIVE_COLOR +}; + +enum +{ + COLOR_CLICKED, + LAST_SIGNAL +}; + +typedef enum +{ + INVALID_AREA, + FORE_AREA, + BACK_AREA, + SWAP_AREA, + DEFAULT_AREA +} FgBgTarget; + + +static void gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass); +static void gimp_fg_bg_editor_init (GimpFgBgEditor *editor); + +static void gimp_fg_bg_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_fg_bg_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_fg_bg_editor_destroy (GtkObject *object); +static gboolean gimp_fg_bg_editor_expose (GtkWidget *widget, + GdkEventExpose *eevent); +static gboolean gimp_fg_bg_editor_button_press (GtkWidget *widget, + GdkEventButton *bevent); +static gboolean gimp_fg_bg_editor_button_release (GtkWidget *widget, + GdkEventButton *bevent); + +static void gimp_fg_bg_editor_context_changed (GimpContext *context, + const GimpRGB *color, + GimpFgBgEditor *editor); +static void gimp_fg_bg_editor_drag_color (GtkWidget *widget, + GimpRGB *color, + gpointer data); +static void gimp_fg_bg_editor_drop_color (GtkWidget *widget, + const GimpRGB *color, + gpointer data); + + + +static guint editor_signals[LAST_SIGNAL] = { 0 }; + +static GtkDrawingAreaClass *parent_class = NULL; + + +GType +gimp_fg_bg_editor_get_type (void) +{ + static GType type = 0; + + if (! type) + { + static const GTypeInfo info = + { + sizeof (GimpFgBgEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gimp_fg_bg_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpFgBgEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_fg_bg_editor_init, + }; + + type = g_type_register_static (GTK_TYPE_DRAWING_AREA, + "GimpFgBgEditor", + &info, 0); + } + + return type; +} + +static void +gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + editor_signals[COLOR_CLICKED] = + g_signal_new ("color-clicked", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpFgBgEditorClass, color_clicked), + NULL, NULL, + gimp_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GIMP_TYPE_ACTIVE_COLOR); + + object_class->set_property = gimp_fg_bg_editor_set_property; + object_class->get_property = gimp_fg_bg_editor_get_property; + + gtk_object_class->destroy = gimp_fg_bg_editor_destroy; + + widget_class->expose_event = gimp_fg_bg_editor_expose; + widget_class->button_press_event = gimp_fg_bg_editor_button_press; + widget_class->button_release_event = gimp_fg_bg_editor_button_release; + + g_object_class_install_property (object_class, PROP_CONTEXT, + g_param_spec_object ("context", + NULL, NULL, + GIMP_TYPE_CONTEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ACTIVE_COLOR, + g_param_spec_enum ("active-color", + NULL, NULL, + GIMP_TYPE_ACTIVE_COLOR, + GIMP_ACTIVE_COLOR_FOREGROUND, + G_PARAM_READWRITE)); +} + +static void +gimp_fg_bg_editor_init (GimpFgBgEditor *editor) +{ + editor->context = NULL; + editor->active_color = GIMP_ACTIVE_COLOR_FOREGROUND; + + gtk_widget_add_events (GTK_WIDGET (editor), + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK); + + gimp_dnd_color_source_add (GTK_WIDGET (editor), + gimp_fg_bg_editor_drag_color, NULL); + gimp_dnd_color_dest_add (GTK_WIDGET (editor), + gimp_fg_bg_editor_drop_color, NULL); +} + +static void +gimp_fg_bg_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object); + + switch (property_id) + { + case PROP_CONTEXT: + gimp_fg_bg_editor_set_context (editor, g_value_get_object (value)); + break; + case PROP_ACTIVE_COLOR: + gimp_fg_bg_editor_set_active (editor, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_fg_bg_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object); + + switch (property_id) + { + case PROP_CONTEXT: + g_value_set_object (value, editor->context); + break; + case PROP_ACTIVE_COLOR: + g_value_set_enum (value, editor->active_color); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_fg_bg_editor_destroy (GtkObject *object) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (object); + + if (editor->context) + gimp_fg_bg_editor_set_context (editor, NULL); + + if (editor->render_buf) + { + g_free (editor->render_buf); + editor->render_buf = NULL; + editor->render_buf_size = 0; + } + + if (editor->default_icon) + { + g_object_unref (editor->default_icon); + editor->default_icon = NULL; + } + + if (editor->swap_icon) + { + g_object_unref (editor->swap_icon); + editor->swap_icon = NULL; + } + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gimp_fg_bg_editor_draw_rect (GimpFgBgEditor *editor, + GdkDrawable *drawable, + GdkGC *gc, + gint x, + gint y, + gint width, + gint height, + const GimpRGB *color) +{ + gint rowstride; + guchar r, g, b; + gint xx, yy; + guchar *bp; + + gimp_rgb_get_uchar (color, &r, &g, &b); + + rowstride = 3 * ((width + 3) & -4); + + if (! editor->render_buf || editor->render_buf_size < height * rowstride) + { + editor->render_buf_size = rowstride * height; + + g_free (editor->render_buf); + editor->render_buf = g_malloc (editor->render_buf_size); + } + + bp = editor->render_buf; + for (xx = 0; xx < width; xx++) + { + *bp++ = r; + *bp++ = g; + *bp++ = b; + } + + bp = editor->render_buf; + + for (yy = 1; yy < height; yy++) + { + bp += rowstride; + memcpy (bp, editor->render_buf, rowstride); + } + + gdk_draw_rgb_image (drawable, gc, x, y, width, height, + GDK_RGB_DITHER_MAX, + editor->render_buf, + rowstride); +} + +static gboolean +gimp_fg_bg_editor_expose (GtkWidget *widget, + GdkEventExpose *eevent) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget); + gint width, height; + gint default_w, default_h; + gint swap_w, swap_h; + gint rect_w, rect_h; + GimpRGB color; + + if (! GTK_WIDGET_DRAWABLE (widget)) + return FALSE; + + width = widget->allocation.width; + height = widget->allocation.height; + + /* draw the default colors pixbuf */ + if (! editor->default_icon) + editor->default_icon = gtk_widget_render_icon (widget, + GIMP_STOCK_DEFAULT_COLORS, + GTK_ICON_SIZE_MENU, NULL); + + default_w = gdk_pixbuf_get_width (editor->default_icon); + default_h = gdk_pixbuf_get_height (editor->default_icon); + gdk_draw_pixbuf (widget->window, NULL, editor->default_icon, + 0, 0, 0, height - default_h, default_w, default_h, + GDK_RGB_DITHER_NORMAL, 0, 0); + + /* draw the swap colors pixbuf */ + if (! editor->swap_icon) + editor->swap_icon = gtk_widget_render_icon (widget, + GIMP_STOCK_SWAP_COLORS, + GTK_ICON_SIZE_MENU, NULL); + + swap_w = gdk_pixbuf_get_width (editor->swap_icon); + swap_h = gdk_pixbuf_get_height (editor->swap_icon); + gdk_draw_pixbuf (widget->window, NULL, editor->swap_icon, + 0, 0, width - swap_w, 0, swap_w, swap_h, + GDK_RGB_DITHER_NORMAL, 0, 0); + + + rect_h = height - MAX (default_h, swap_h) - 2; + rect_w = width - MAX (default_w, swap_w) - 4; + + if (rect_h > (height * 3 / 4)) + rect_w = MAX (rect_w - (rect_h - ((height * 3 / 4))), + width * 2 / 3); + + editor->rect_width = rect_w; + editor->rect_height = rect_h; + + + /* draw the background area */ + + if (editor->context) + { + gimp_context_get_background (editor->context, &color); + gimp_fg_bg_editor_draw_rect (editor, + widget->window, + widget->style->fg_gc[0], + (width - rect_w), + (height - rect_h), + rect_w, rect_h, + &color); + } + + gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL, + editor->active_color == GIMP_ACTIVE_COLOR_FOREGROUND ? + GTK_SHADOW_OUT : GTK_SHADOW_IN, + NULL, widget, NULL, + (width - rect_w), + (height - rect_h), + rect_w, rect_h); + + + /* draw the foreground area */ + + if (editor->context) + { + gimp_context_get_foreground (editor->context, &color); + gimp_fg_bg_editor_draw_rect (editor, + widget->window, + widget->style->fg_gc[0], + 0, 0, + rect_w, rect_h, + &color); + } + + gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL, + editor->active_color == GIMP_ACTIVE_COLOR_BACKGROUND ? + GTK_SHADOW_OUT : GTK_SHADOW_IN, + NULL, widget, NULL, + 0, 0, + rect_w, rect_h); + + return TRUE; +} + +static FgBgTarget +gimp_fg_bg_editor_target (GimpFgBgEditor *editor, + gint x, + gint y) +{ + gint width = GTK_WIDGET (editor)->allocation.width; + gint height = GTK_WIDGET (editor)->allocation.height; + gint rect_w = editor->rect_width; + gint rect_h = editor->rect_height; + + if (x > 0 && x < rect_w && y > 0 && y < rect_h) + return FORE_AREA; + else if (x > (width - rect_w) && x < width && + y > (height - rect_h) && y < height) + return BACK_AREA; + else if (x > 0 && x < (width - rect_w) && + y > rect_h && y < height) + return DEFAULT_AREA; + else if (x > rect_w && x < width && + y > 0 && y < (height - rect_h)) + return SWAP_AREA; + + return INVALID_AREA; +} + +static gboolean +gimp_fg_bg_editor_button_press (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget); + + if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS) + { + FgBgTarget target = gimp_fg_bg_editor_target (editor, + bevent->x, bevent->y); + + editor->click_target = INVALID_AREA; + + switch (target) + { + case FORE_AREA: + if (editor->active_color != GIMP_ACTIVE_COLOR_FOREGROUND) + gimp_fg_bg_editor_set_active (editor, + GIMP_ACTIVE_COLOR_FOREGROUND); + else + editor->click_target = FORE_AREA; + break; + + case BACK_AREA: + if (editor->active_color != GIMP_ACTIVE_COLOR_BACKGROUND) + gimp_fg_bg_editor_set_active (editor, + GIMP_ACTIVE_COLOR_BACKGROUND); + else + editor->click_target = BACK_AREA; + break; + + case SWAP_AREA: + if (editor->context) + gimp_context_swap_colors (editor->context); + break; + + case DEFAULT_AREA: + if (editor->context) + gimp_context_set_default_colors (editor->context); + break; + + default: + break; + } + + } + + return FALSE; +} + +static gboolean +gimp_fg_bg_editor_button_release (GtkWidget *widget, + GdkEventButton *bevent) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget); + + if (bevent->button == 1) + { + FgBgTarget target = gimp_fg_bg_editor_target (editor, + bevent->x, bevent->y); + + if (target == editor->click_target) + { + switch (target) + { + case FORE_AREA: + g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0, + GIMP_ACTIVE_COLOR_FOREGROUND); + break; + + case BACK_AREA: + g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0, + GIMP_ACTIVE_COLOR_BACKGROUND); + break; + + default: + break; + } + } + + editor->click_target = INVALID_AREA; + } + + return FALSE; +} + + +/* public functions */ + +GtkWidget * +gimp_fg_bg_editor_new (GimpContext *context) +{ + g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL); + + return g_object_new (GIMP_TYPE_FG_BG_EDITOR, + "context", context, + NULL); +} + +void +gimp_fg_bg_editor_set_context (GimpFgBgEditor *editor, + GimpContext *context) +{ + g_return_if_fail (GIMP_IS_FG_BG_EDITOR (editor)); + g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context)); + + if (context == editor->context) + return; + + if (editor->context) + { + g_signal_handlers_disconnect_by_func (editor->context, + gimp_fg_bg_editor_context_changed, + editor); + g_object_unref (editor->context); + editor->context = NULL; + } + + editor->context = context; + + if (context) + { + g_object_ref (context); + + g_signal_connect (context, "foreground_changed", + G_CALLBACK (gimp_fg_bg_editor_context_changed), + editor); + g_signal_connect (context, "background_changed", + G_CALLBACK (gimp_fg_bg_editor_context_changed), + editor); + } + + g_object_notify (G_OBJECT (editor), "context"); +} + +void +gimp_fg_bg_editor_set_active (GimpFgBgEditor *editor, + GimpActiveColor active) +{ + g_return_if_fail (GIMP_IS_FG_BG_EDITOR (editor)); + + editor->active_color = active; + gtk_widget_queue_draw (GTK_WIDGET (editor)); + g_object_notify (G_OBJECT (editor), "active-color"); +} + + +/* private functions */ + +static void +gimp_fg_bg_editor_context_changed (GimpContext *context, + const GimpRGB *color, + GimpFgBgEditor *editor) +{ + gtk_widget_queue_draw (GTK_WIDGET (editor)); +} + +static void +gimp_fg_bg_editor_drag_color (GtkWidget *widget, + GimpRGB *color, + gpointer data) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget); + + if (editor->context) + { + switch (editor->active_color) + { + case GIMP_ACTIVE_COLOR_FOREGROUND: + gimp_context_get_foreground (editor->context, color); + break; + + case GIMP_ACTIVE_COLOR_BACKGROUND: + gimp_context_get_background (editor->context, color); + break; + } + } +} + +static void +gimp_fg_bg_editor_drop_color (GtkWidget *widget, + const GimpRGB *color, + gpointer data) +{ + GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget); + + if (editor->context) + { + switch (editor->active_color) + { + case GIMP_ACTIVE_COLOR_FOREGROUND: + gimp_context_set_foreground (editor->context, color); + break; + + case GIMP_ACTIVE_COLOR_BACKGROUND: + gimp_context_set_background (editor->context, color); + break; + } + } +} diff --git a/app/widgets/gimpfgbgeditor.h b/app/widgets/gimpfgbgeditor.h new file mode 100644 index 0000000000..dd4fee8ec9 --- /dev/null +++ b/app/widgets/gimpfgbgeditor.h @@ -0,0 +1,78 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpfgbgeditor.h + * Copyright (C) 2004 Michael Natterer + * + * 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 __GIMP_FG_BG_EDITOR_H__ +#define __GIMP_FG_BG_EDITOR_H__ + + +#include + + +#define GIMP_TYPE_FG_BG_EDITOR (gimp_fg_bg_editor_get_type ()) +#define GIMP_FG_BG_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_FG_BG_EDITOR, GimpFgBgEditor)) +#define GIMP_FG_BG_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_FG_BG_EDITOR, GimpFgBgEditorClass)) +#define GIMP_IS_FG_BG_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_FG_BG_EDITOR)) +#define GIMP_IS_FG_BG_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_FG_BG_EDITOR)) +#define GIMP_FG_BG_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_FG_BG_EDITOR, GimpFgBgEditorClass)) + + +typedef struct _GimpFgBgEditorClass GimpFgBgEditorClass; + +struct _GimpFgBgEditor +{ + GtkDrawingArea parent_instance; + + GimpContext *context; + GimpActiveColor active_color; + + guchar *render_buf; + gint render_buf_size; + + GdkPixbuf *default_icon; + GdkPixbuf *swap_icon; + + gint rect_width; + gint rect_height; + gint click_target; +}; + +struct _GimpFgBgEditorClass +{ + GtkDrawingAreaClass parent_class; + + /* signals */ + + void (* color_clicked) (GimpFgBgEditor *editor, + GimpActiveColor color); +}; + + +GType gimp_fg_bg_editor_get_type (void) G_GNUC_CONST; + +GtkWidget * gimp_fg_bg_editor_new (GimpContext *context); + +void gimp_fg_bg_editor_set_context (GimpFgBgEditor *editor, + GimpContext *context); +void gimp_fg_bg_editor_set_active (GimpFgBgEditor *editor, + GimpActiveColor active); + + +#endif /* __GIMP_FG_BG_EDITOR_H__ */ diff --git a/app/widgets/gimptoolbox-color-area.c b/app/widgets/gimptoolbox-color-area.c index 0399911136..432a5f84f0 100644 --- a/app/widgets/gimptoolbox-color-area.c +++ b/app/widgets/gimptoolbox-color-area.c @@ -18,11 +18,8 @@ #include "config.h" -#include /* memcpy */ - #include -#include "libgimpcolor/gimpcolor.h" #include "libgimpwidgets/gimpwidgets.h" #include "widgets-types.h" @@ -36,7 +33,7 @@ #include "core/gimpcontext.h" #include "gimpdialogfactory.h" -#include "gimpdnd.h" +#include "gimpfgbgeditor.h" #include "gimptoolbox.h" #include "gimptoolbox-color-area.h" @@ -45,60 +42,25 @@ #include "gimp-intl.h" -typedef enum -{ - FORE_AREA, - BACK_AREA, - SWAP_AREA, - DEFAULT_AREA, - INVALID_AREA -} ColorAreaTarget; - -#define FOREGROUND 0 -#define BACKGROUND 1 - - /* local function prototypes */ -static ColorAreaTarget color_area_target (gint x, - gint y); - -static gboolean color_area_expose_event (GtkWidget *widget, - GdkEventExpose *eevent, +static void color_area_color_clicked (GimpFgBgEditor *editor, + GimpActiveColor active_color, GimpContext *context); -static void color_area_draw_rect (GdkDrawable *drawable, - GdkGC *gc, - gint x, - gint y, - gint width, - gint height, - const GimpRGB *color); - static void color_area_select_callback (ColorNotebook *color_notebook, const GimpRGB *color, ColorNotebookState state, gpointer data); -static void color_area_edit (GimpContext *context, - GtkWidget *widget); -static void color_area_drop_color (GtkWidget *widget, - const GimpRGB *color, - gpointer data); -static void color_area_drag_color (GtkWidget *widget, - GimpRGB *color, - gpointer data); -static gboolean color_area_events (GtkWidget *widget, - GdkEvent *event, - gpointer data); -/* Static variables */ -static GtkWidget *color_area = NULL; -static ColorNotebook *color_notebook = NULL; -static gboolean color_notebook_active = FALSE; -static gint active_color = FOREGROUND; -static gint edit_color; -static GimpRGB revert_fg; -static GimpRGB revert_bg; +/* local variables */ + +static GtkWidget *color_area = NULL; +static ColorNotebook *color_notebook = NULL; +static gboolean color_notebook_active = FALSE; +static GimpActiveColor edit_color; +static GimpRGB revert_fg; +static GimpRGB revert_bg; /* public functions */ @@ -114,31 +76,15 @@ gimp_toolbox_color_area_create (GimpToolbox *toolbox, context = GIMP_DOCK (toolbox)->context; - color_area = gtk_drawing_area_new (); + color_area = gimp_fg_bg_editor_new (context); gtk_widget_set_size_request (color_area, width, height); - gtk_widget_set_events (color_area, - GDK_EXPOSURE_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | + gtk_widget_add_events (color_area, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - g_signal_connect (color_area, "event", - G_CALLBACK (color_area_events), + g_signal_connect (color_area, "color-clicked", + G_CALLBACK (color_area_color_clicked), context); - g_signal_connect (color_area, "expose_event", - G_CALLBACK (color_area_expose_event), - context); - - gimp_dnd_color_source_add (color_area, color_area_drag_color, context); - gimp_dnd_color_dest_add (color_area, color_area_drop_color, context); - - g_signal_connect_swapped (context, "foreground_changed", - G_CALLBACK (gtk_widget_queue_draw), - color_area); - g_signal_connect_swapped (context, "background_changed", - G_CALLBACK (gtk_widget_queue_draw), - color_area); return color_area; } @@ -146,162 +92,6 @@ gimp_toolbox_color_area_create (GimpToolbox *toolbox, /* private functions */ -static ColorAreaTarget -color_area_target (gint x, - gint y) -{ - gint rect_w, rect_h; - gint width, height; - - width = color_area->allocation.width; - height = color_area->allocation.height; - - rect_w = (width * 2) / 3; - rect_h = (height * 2) / 3; - - /* foreground active */ - if (x > 0 && x < rect_w && y > 0 && y < rect_h) - return FORE_AREA; - else if (x > (width - rect_w) && x < width && - y > (height - rect_h) && y < height) - return BACK_AREA; - else if (x > 0 && x < (width - rect_w) && - y > rect_h && y < height) - return DEFAULT_AREA; - else if (x > rect_w && x < width && - y > 0 && y < (height - rect_h)) - return SWAP_AREA; - else - return -1; -} - -static gboolean -color_area_expose_event (GtkWidget *widget, - GdkEventExpose *eevent, - GimpContext *context) -{ - gint rect_w, rect_h; - gint width, height; - gint w, h; - GimpRGB color; - GdkPixbuf *pixbuf; - - if (!GTK_WIDGET_DRAWABLE (color_area)) - return FALSE; - - width = color_area->allocation.width; - height = color_area->allocation.height; - - rect_w = (width * 2) / 3; - rect_h = (height * 2) / 3; - - /* draw the background area */ - gimp_context_get_background (context, &color); - color_area_draw_rect (color_area->window, color_area->style->fg_gc[0], - (width - rect_w), (height - rect_h), rect_w, rect_h, - &color); - - gtk_paint_shadow (color_area->style, color_area->window, GTK_STATE_NORMAL, - active_color == FOREGROUND ? GTK_SHADOW_OUT : GTK_SHADOW_IN, - NULL, color_area, NULL, - (width - rect_w), (height - rect_h), - rect_w, rect_h); - - /* draw the foreground area */ - gimp_context_get_foreground (context, &color); - color_area_draw_rect (color_area->window, color_area->style->fg_gc[0], - 0, 0, rect_w, rect_h, - &color); - - gtk_paint_shadow (color_area->style, color_area->window, GTK_STATE_NORMAL, - active_color == BACKGROUND ? GTK_SHADOW_OUT : GTK_SHADOW_IN, - NULL, color_area, NULL, - 0, 0, - rect_w, rect_h); - - /* draw the default colors pixbuf */ - pixbuf = gtk_widget_render_icon (color_area, GIMP_STOCK_DEFAULT_COLORS, - GTK_ICON_SIZE_MENU, NULL); - w = gdk_pixbuf_get_width (pixbuf); - h = gdk_pixbuf_get_height (pixbuf); - gdk_draw_pixbuf (color_area->window, NULL, pixbuf, - 0, 0, 0, height - h, w, h, - GDK_RGB_DITHER_MAX, 0, 0); - g_object_unref (pixbuf); - - /* draw the swap colors pixbuf */ - pixbuf = gtk_widget_render_icon (color_area, GIMP_STOCK_SWAP_COLORS, - GTK_ICON_SIZE_MENU, NULL); - w = gdk_pixbuf_get_width (pixbuf); - h = gdk_pixbuf_get_height (pixbuf); - gdk_draw_pixbuf (color_area->window, NULL, pixbuf, - 0, 0, width - w, 0, w, h, - GDK_RGB_DITHER_MAX, 0, 0); - g_object_unref (pixbuf); - - return TRUE; -} - -static void -color_area_draw_rect (GdkDrawable *drawable, - GdkGC *gc, - gint x, - gint y, - gint width, - gint height, - const GimpRGB *color) -{ - static guchar *color_area_rgb_buf = NULL; - static gint color_area_rgb_buf_size; - - gint rowstride; - guchar r, g, b; - gint xx, yy; - guchar *bp; - - gimp_rgb_get_uchar (color, &r, &g, &b); - - rowstride = 3 * ((width + 3) & -4); - - if (!color_area_rgb_buf || color_area_rgb_buf_size < height * rowstride) - { - color_area_rgb_buf_size = rowstride * height; - - g_free (color_area_rgb_buf); - color_area_rgb_buf = g_malloc (color_area_rgb_buf_size); - } - - bp = color_area_rgb_buf; - for (xx = 0; xx < width; xx++) - { - *bp++ = r; - *bp++ = g; - *bp++ = b; - } - - bp = color_area_rgb_buf; - -#ifdef DISPLAY_FILTERS - for (list = color_area_gdisp->cd_list; list; list = g_list_next (list)) - { - ColorDisplayNode *node = (ColorDisplayNode *) list->data; - - node->cd_convert (node->cd_ID, bp, width, 1, 3, rowstride); - } -#endif /* DISPLAY_FILTERS */ - - for (yy = 1; yy < height; yy++) - { - bp += rowstride; - memcpy (bp, color_area_rgb_buf, rowstride); - } - - gdk_draw_rgb_image (drawable, gc, x, y, width, height, - GDK_RGB_DITHER_MAX, - color_area_rgb_buf, - rowstride); -} - static void color_area_select_callback (ColorNotebook *color_notebook, const GimpRGB *color, @@ -320,7 +110,7 @@ color_area_select_callback (ColorNotebook *color_notebook, /* Fallthrough */ case COLOR_NOTEBOOK_UPDATE: - if (edit_color == FOREGROUND) + if (edit_color == GIMP_ACTIVE_COLOR_FOREGROUND) gimp_context_set_foreground (context, color); else gimp_context_set_background (context, color); @@ -337,8 +127,9 @@ color_area_select_callback (ColorNotebook *color_notebook, } static void -color_area_edit (GimpContext *context, - GtkWidget *widget) +color_area_color_clicked (GimpFgBgEditor *editor, + GimpActiveColor active_color, + GimpContext *context) { GimpRGB color; const gchar *title; @@ -349,18 +140,19 @@ color_area_edit (GimpContext *context, gimp_context_get_background (context, &revert_bg); } - if (active_color == FOREGROUND) - gimp_context_get_foreground (context, &color); + if (active_color == GIMP_ACTIVE_COLOR_FOREGROUND) + { + gimp_context_get_foreground (context, &color); + title = _("Change Foreground Color"); + } else - gimp_context_get_background (context, &color); + { + gimp_context_get_background (context, &color); + title = _("Change Background Color"); + } edit_color = active_color; - if (active_color == FOREGROUND) - title = _("Change Foreground Color"); - else - title = _("Change Background Color"); - if (! color_notebook) { GimpDialogFactory *toplevel_factory; @@ -368,7 +160,7 @@ color_area_edit (GimpContext *context, toplevel_factory = gimp_dialog_factory_from_name ("toplevel"); color_notebook = color_notebook_new (NULL, title, NULL, NULL, - widget, + GTK_WIDGET (editor), toplevel_factory, "gimp-toolbox-color-dialog", (const GimpRGB *) &color, @@ -385,123 +177,3 @@ color_area_edit (GimpContext *context, color_notebook_active = TRUE; } } - -static gint -color_area_events (GtkWidget *widget, - GdkEvent *event, - gpointer data) -{ - GimpContext *context; - GdkEventButton *bevent; - ColorAreaTarget target; - - static ColorAreaTarget press_target = INVALID_AREA; - - context = GIMP_CONTEXT (data); - - switch (event->type) - { - case GDK_BUTTON_PRESS: - bevent = (GdkEventButton *) event; - - if (bevent->button == 1) - { - target = color_area_target (bevent->x, bevent->y); - press_target = INVALID_AREA; - - switch (target) - { - case FORE_AREA: - case BACK_AREA: - if (target != active_color) - { - active_color = target; - gtk_widget_queue_draw (widget); - } - else - { - press_target = target; - } - break; - - case SWAP_AREA: - gimp_context_swap_colors (context); - break; - - case DEFAULT_AREA: - gimp_context_set_default_colors (context); - break; - - default: - break; - } - } - break; - - case GDK_BUTTON_RELEASE: - bevent = (GdkEventButton *) event; - - if (bevent->button == 1) - { - target = color_area_target (bevent->x, bevent->y); - - if (target == press_target) - { - switch (target) - { - case FORE_AREA: - case BACK_AREA: - color_area_edit (context, widget); - break; - - default: - break; - } - } - press_target = INVALID_AREA; - } - break; - - case GDK_LEAVE_NOTIFY: - press_target = INVALID_AREA; - break; - - default: - break; - } - - return FALSE; -} - -static void -color_area_drag_color (GtkWidget *widget, - GimpRGB *color, - gpointer data) -{ - GimpContext *context = GIMP_CONTEXT (data); - - if (active_color == FOREGROUND) - gimp_context_get_foreground (context, color); - else - gimp_context_get_background (context, color); -} - -static void -color_area_drop_color (GtkWidget *widget, - const GimpRGB *color, - gpointer data) -{ - GimpContext *context = GIMP_CONTEXT (data); - - if (color_notebook_active && active_color == edit_color) - { - color_notebook_set_color (color_notebook, color); - } - else - { - if (active_color == FOREGROUND) - gimp_context_set_foreground (context, color); - else - gimp_context_set_background (context, color); - } -} diff --git a/app/widgets/widgets-enums.c b/app/widgets/widgets-enums.c index 2487694e6c..5ca69ff8ec 100644 --- a/app/widgets/widgets-enums.c +++ b/app/widgets/widgets-enums.c @@ -8,6 +8,25 @@ /* enumerations from "./widgets-enums.h" */ +static const GEnumValue gimp_active_color_enum_values[] = +{ + { GIMP_ACTIVE_COLOR_FOREGROUND, N_("Foreground"), "foreground" }, + { GIMP_ACTIVE_COLOR_BACKGROUND, N_("Background"), "background" }, + { 0, NULL, NULL } +}; + +GType +gimp_active_color_get_type (void) +{ + static GType enum_type = 0; + + if (!enum_type) + enum_type = g_enum_register_static ("GimpActiveColor", gimp_active_color_enum_values); + + return enum_type; +} + + static const GEnumValue gimp_aspect_type_enum_values[] = { { GIMP_ASPECT_SQUARE, "GIMP_ASPECT_SQUARE", "square" }, diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h index 869dc11c20..e20f07ca6a 100644 --- a/app/widgets/widgets-enums.h +++ b/app/widgets/widgets-enums.h @@ -24,6 +24,17 @@ * these enums that are registered with the type system */ +#define GIMP_TYPE_ACTIVE_COLOR (gimp_active_color_get_type ()) + +GType gimp_active_color_get_type (void) G_GNUC_CONST; + +typedef enum +{ + GIMP_ACTIVE_COLOR_FOREGROUND, /*< desc="Foreground" >*/ + GIMP_ACTIVE_COLOR_BACKGROUND /*< desc="Background" >*/ +} GimpActiveColor; + + #define GIMP_TYPE_ASPECT_TYPE (gimp_aspect_type_get_type ()) GType gimp_aspect_type_get_type (void) G_GNUC_CONST; diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index efc8186ec9..2fbb53f06b 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -127,6 +127,7 @@ typedef struct _GimpColorDisplayEditor GimpColorDisplayEditor; typedef struct _GimpColorFrame GimpColorFrame; typedef struct _GimpColorPanel GimpColorPanel; typedef struct _GimpDashEditor GimpDashEditor; +typedef struct _GimpFgBgEditor GimpFgBgEditor; typedef struct _GimpGridEditor GimpGridEditor; typedef struct _GimpHistogramBox GimpHistogramBox; typedef struct _GimpHistogramView GimpHistogramView;