diff --git a/ChangeLog b/ChangeLog index de91405d88..2fe7df22da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,23 @@ +2005-05-21 Sven Neumann + + * app/core/gimpdashpattern.[ch]: added utility functions to copy + and to free a dash pattern. + + * app/widgets/Makefile.am + * app/widgets/widgets-types.h + * app/widgets/gimpcellrendererdashes.[ch]: added a simple cell + renderer to visualize a dash pattern. + + * app/widgets/gimpstrokeeditor.c: show previews of the dash + presets in the combo-box. + 2005-05-21 Michael Natterer * tools/test-clipboard.c (main): NULL terminate the options array. 2005-05-21 Sven Neumann - Allow to paste a new image using Ctrl-V (bug 169477): + Allow to paste a new image using Ctrl-V (bug #169477): * menus/toolbox-menu.xml.in: added an accelerator for "edit-paste". @@ -229,7 +242,6 @@ instruction count correct. This is partially complete as of this commit. - 2005-05-17 Sven Neumann * configure.in: bumped version number to 2.3.1. diff --git a/app/core/gimpdashpattern.c b/app/core/gimpdashpattern.c index 963095927a..1559cc8199 100644 --- a/app/core/gimpdashpattern.c +++ b/app/core/gimpdashpattern.c @@ -254,3 +254,29 @@ gimp_dash_pattern_value_set (GArray *pattern, g_value_set_boxed (value, val_array); } } + +GArray * +gimp_dash_pattern_copy (GArray *pattern) +{ + if (pattern) + { + GArray *copy; + gint i; + + copy = g_array_sized_new (FALSE, FALSE, sizeof (gdouble), pattern->len); + + for (i = 0; i < pattern->len; i++) + copy = g_array_append_val (copy, g_array_index (pattern, gdouble, i)); + + return copy; + } + + return NULL; +} + +void +gimp_dash_pattern_free (GArray *pattern) +{ + if (pattern) + g_array_free (pattern, TRUE); +} diff --git a/app/core/gimpdashpattern.h b/app/core/gimpdashpattern.h index 7d2db9db47..0410988b71 100644 --- a/app/core/gimpdashpattern.h +++ b/app/core/gimpdashpattern.h @@ -37,5 +37,8 @@ GArray * gimp_dash_pattern_from_value (const GValue *value); void gimp_dash_pattern_value_set (GArray *pattern, GValue *value); +GArray * gimp_dash_pattern_copy (GArray *pattern); +void gimp_dash_pattern_free (GArray *pattern); + #endif /* __GIMP_DASH_PATTERN_H__ */ diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am index 9ad8097afb..c22fa90f03 100644 --- a/app/widgets/Makefile.am +++ b/app/widgets/Makefile.am @@ -38,6 +38,8 @@ libappwidgets_a_sources = \ gimpbufferview.h \ gimpcellrendereraccel.c \ gimpcellrendereraccel.h \ + gimpcellrendererdashes.c \ + gimpcellrendererdashes.h \ gimpcellrendererviewable.c \ gimpcellrendererviewable.h \ gimpchanneltreeview.c \ diff --git a/app/widgets/gimpcellrendererdashes.c b/app/widgets/gimpcellrendererdashes.c new file mode 100644 index 0000000000..2f51101dec --- /dev/null +++ b/app/widgets/gimpcellrendererdashes.c @@ -0,0 +1,270 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcellrendererdashes.c + * Copyright (C) 2005 Sven Neumann + * + * 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 + +#include + +#include "widgets-types.h" + +#include "core/gimpdashpattern.h" + +#include "gimpcellrendererdashes.h" + + +#define DASHES_WIDTH 72 +#define DASHES_HEIGHT 6 + +#define N_SEGMENTS 24 +#define BLOCK_WIDTH (DASHES_WIDTH / N_SEGMENTS) + + +enum +{ + PROP_0, + PROP_PATTERN +}; + + +static void gimp_cell_renderer_dashes_class_init (GimpCellRendererDashesClass *klass); +static void gimp_cell_renderer_dashes_init (GimpCellRendererDashes *cell); + +static void gimp_cell_renderer_dashes_finalize (GObject *object); +static void gimp_cell_renderer_dashes_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void gimp_cell_renderer_dashes_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_cell_renderer_dashes_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *rectangle, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height); +static void gimp_cell_renderer_dashes_render (GtkCellRenderer *cell, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags); + + +static GtkCellRendererClass *parent_class = NULL; + + +GType +gimp_cell_renderer_dashes_get_type (void) +{ + static GType cell_type = 0; + + if (! cell_type) + { + static const GTypeInfo cell_info = + { + sizeof (GimpCellRendererDashesClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gimp_cell_renderer_dashes_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpCellRendererDashes), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_cell_renderer_dashes_init, + }; + + cell_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, + "GimpCellRendererDashes", + &cell_info, 0); + } + + return cell_type; +} + +static void +gimp_cell_renderer_dashes_class_init (GimpCellRendererDashesClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gimp_cell_renderer_dashes_finalize; + object_class->get_property = gimp_cell_renderer_dashes_get_property; + object_class->set_property = gimp_cell_renderer_dashes_set_property; + + cell_class->get_size = gimp_cell_renderer_dashes_get_size; + cell_class->render = gimp_cell_renderer_dashes_render; + + g_object_class_install_property (object_class, PROP_PATTERN, + g_param_spec_pointer ("pattern", NULL, NULL, + G_PARAM_READWRITE)); +} + +static void +gimp_cell_renderer_dashes_init (GimpCellRendererDashes *dashes) +{ + dashes->pattern = NULL; + dashes->segments = g_new0 (gboolean, N_SEGMENTS); +} + +static void +gimp_cell_renderer_dashes_finalize (GObject *object) +{ + GimpCellRendererDashes *dashes = GIMP_CELL_RENDERER_DASHES (object); + + g_free (dashes->segments); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_cell_renderer_dashes_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GimpCellRendererDashes *dashes = GIMP_CELL_RENDERER_DASHES (object); + + switch (param_id) + { + case PROP_PATTERN: + g_value_set_pointer (value, dashes->pattern); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gimp_cell_renderer_dashes_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpCellRendererDashes *dashes = GIMP_CELL_RENDERER_DASHES (object); + + switch (param_id) + { + case PROP_PATTERN: + dashes->pattern = g_value_get_pointer (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gimp_cell_renderer_dashes_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ + if (cell_area) + { + if (x_offset) + { + gdouble align; + + align = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? + 1.0 - cell->xalign : cell->xalign); + + *x_offset = align * (cell_area->width - DASHES_WIDTH); + *x_offset = MAX (*x_offset, 0) + cell->xpad; + } + + if (y_offset) + { + *y_offset = cell->yalign * (cell_area->height - DASHES_HEIGHT); + *y_offset = MAX (*y_offset, 0) + cell->ypad; + } + } + else + { + if (x_offset) + *x_offset = 0; + + if (y_offset) + *y_offset = 0; + } + + *width = DASHES_WIDTH + 2 * cell->xpad; + *height = DASHES_HEIGHT + 2 * cell->ypad; +} + +static void +gimp_cell_renderer_dashes_render (GtkCellRenderer *cell, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags) +{ + GimpCellRendererDashes *dashes = GIMP_CELL_RENDERER_DASHES (cell); + GdkRectangle rect; + gint x, y; + + gimp_dash_pattern_segments_set (dashes->pattern, + dashes->segments, N_SEGMENTS); + + gdk_rectangle_intersect (cell_area, expose_area, &rect); + gdk_draw_rectangle (window, + widget->style->base_gc[GTK_STATE_NORMAL], TRUE, + rect.x, rect.y, rect.width, rect.height); + + y = cell_area->y + (cell_area->height - DASHES_HEIGHT) / 2; + + for (x = 0; x < cell_area->width + BLOCK_WIDTH; x += BLOCK_WIDTH) + { + guint index = ((guint) x / BLOCK_WIDTH) % N_SEGMENTS; + + if (dashes->segments[index]) + { + rect.x = cell_area->x + x; + rect.y = y; + rect.width = BLOCK_WIDTH; + rect.height = DASHES_HEIGHT; + + gdk_rectangle_intersect (&rect, expose_area, &rect); + gdk_draw_rectangle (widget->window, + widget->style->text_gc[GTK_STATE_NORMAL], TRUE, + rect.x, rect.y, rect.width, rect.height); + } + } +} + +GtkCellRenderer * +gimp_cell_renderer_dashes_new (void) +{ + return g_object_new (GIMP_TYPE_CELL_RENDERER_DASHES, NULL); +} diff --git a/app/widgets/gimpcellrendererdashes.h b/app/widgets/gimpcellrendererdashes.h new file mode 100644 index 0000000000..b6754a0401 --- /dev/null +++ b/app/widgets/gimpcellrendererdashes.h @@ -0,0 +1,58 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcellrendererdashes.h + * Copyright (C) 2005 Sven Neumann + * + * 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_CELL_RENDERER_DASHES_H__ +#define __GIMP_CELL_RENDERER_DASHES_H__ + + +#include + + +#define GIMP_TYPE_CELL_RENDERER_DASHES (gimp_cell_renderer_dashes_get_type ()) +#define GIMP_CELL_RENDERER_DASHES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CELL_RENDERER_DASHES, GimpCellRendererDashes)) +#define GIMP_CELL_RENDERER_DASHES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CELL_RENDERER_DASHES, GimpCellRendererDashesClass)) +#define GIMP_IS_CELL_RENDERER_DASHES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CELL_RENDERER_DASHES)) +#define GIMP_IS_CELL_RENDERER_DASHES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CELL_RENDERER_DASHES)) +#define GIMP_CELL_RENDERER_DASHES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CELL_RENDERER_DASHES, GimpCellRendererDashesClass)) + + +typedef struct _GimpCellRendererDashesClass GimpCellRendererDashesClass; + +struct _GimpCellRendererDashes +{ + GtkCellRenderer parent_instance; + + GArray *pattern; + gboolean *segments; +}; + +struct _GimpCellRendererDashesClass +{ + GtkCellRendererClass parent_class; +}; + + +GType gimp_cell_renderer_dashes_get_type (void) G_GNUC_CONST; + +GtkCellRenderer * gimp_cell_renderer_dashes_new (void); + + +#endif /* __GIMP_CELL_RENDERER_DASHES_H__ */ diff --git a/app/widgets/gimpstrokeeditor.c b/app/widgets/gimpstrokeeditor.c index 8116c9e6e1..95b91f7ed9 100644 --- a/app/widgets/gimpstrokeeditor.c +++ b/app/widgets/gimpstrokeeditor.c @@ -25,8 +25,10 @@ #include "widgets-types.h" +#include "core/gimpdashpattern.h" #include "core/gimpstrokeoptions.h" +#include "gimpcellrendererdashes.h" #include "gimpdasheditor.h" #include "gimpstrokeeditor.h" @@ -59,6 +61,8 @@ static gboolean gimp_stroke_editor_paint_button (GtkWidget *widget, static void gimp_stroke_editor_dash_preset (GtkWidget *widget, GimpStrokeOptions *options); +static void gimp_stroke_editor_combo_fill (GimpStrokeOptions *options, + GtkComboBox *box); static GtkVBoxClass *parent_class = NULL; @@ -178,6 +182,7 @@ gimp_stroke_editor_constructor (GType type, GtkWidget *expander; GtkWidget *dash_editor; GtkWidget *button; + GtkCellRenderer *cell; GObject *object; gint row = 0; @@ -286,6 +291,13 @@ gimp_stroke_editor_constructor (GType type, _("Dash preset:"), 0.0, 0.5, box, 2, FALSE); + cell = gimp_cell_renderer_dashes_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, FALSE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (box), cell, + "pattern", GIMP_INT_STORE_USER_DATA); + + gimp_stroke_editor_combo_fill (editor->options, GTK_COMBO_BOX (box)); + g_signal_connect (box, "changed", G_CALLBACK (gimp_stroke_editor_dash_preset), editor->options); @@ -365,3 +377,70 @@ gimp_stroke_editor_dash_preset (GtkWidget *widget, gimp_stroke_options_set_dash_pattern (options, value, NULL); } } + +static void +gimp_stroke_editor_combo_update (GtkTreeModel *model, + GParamSpec *pspec, + GimpStrokeOptions *options) +{ + GtkTreeIter iter; + + if (gimp_int_store_lookup_by_value (model, GIMP_DASH_CUSTOM, &iter)) + { + GArray *pattern; + + gtk_tree_model_get (model, &iter, + GIMP_INT_STORE_USER_DATA, &pattern, + -1); + gimp_dash_pattern_free (pattern); + + pattern = gimp_dash_pattern_copy (options->dash_info); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + GIMP_INT_STORE_USER_DATA, pattern, + -1); + } +} + +static void +gimp_stroke_editor_combo_fill (GimpStrokeOptions *options, + GtkComboBox *box) +{ + GtkTreeModel *model = gtk_combo_box_get_model (box); + GtkTreeIter iter; + gboolean iter_valid; + + for (iter_valid = gtk_tree_model_get_iter_first (model, &iter); + iter_valid; + iter_valid = gtk_tree_model_iter_next (model, &iter)) + { + GArray *pattern; + gint value; + + gtk_tree_model_get (model, &iter, + GIMP_INT_STORE_VALUE, &value, + -1); + + if (value == GIMP_DASH_CUSTOM) + { + pattern = gimp_dash_pattern_copy (options->dash_info); + + g_signal_connect_object (options, "notify::dash-info", + G_CALLBACK (gimp_stroke_editor_combo_update), + model, G_CONNECT_SWAPPED); + } + else + { + pattern = gimp_dash_pattern_from_preset (value); + } + + if (pattern) + { + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + GIMP_INT_STORE_USER_DATA, pattern, + -1); + + g_object_weak_ref (G_OBJECT (box), + (GWeakNotify) gimp_dash_pattern_free, pattern); + } + } +} diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index 2043d1d46a..74c37f25e2 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -193,6 +193,7 @@ typedef struct _GimpViewRendererVectors GimpViewRendererVectors; /* cell renderers */ typedef struct _GimpCellRendererAccel GimpCellRendererAccel; +typedef struct _GimpCellRendererDashes GimpCellRendererDashes; typedef struct _GimpCellRendererViewable GimpCellRendererViewable;