From ebdd4fb7381fd8a7032344eae7787334e21c2717 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Fri, 7 May 2004 22:16:15 +0000 Subject: [PATCH] app/widgets/Makefile.am app/widgets/widgets-types.h 2004-05-08 Sven Neumann * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpunitcombobox.[ch] * app/widgets/gimpunitstore.[ch]: added a prototype of a unit menu based on GtkComboBox. Will move this to libgimpwidgets later... * app/display/gimpstatusbar.[ch]: use the new GimpUnitComboBox and GimpUnitStore. * themes/Default/gtkrc * themes/Small/gtkrc: hardcode the appearance of the GimpUnitComboBox. It uses a hack that doesn't work in list mode. --- ChangeLog | 15 + app/display/gimpstatusbar.c | 138 ++++++--- app/display/gimpstatusbar.h | 1 + app/widgets/Makefile.am | 4 + app/widgets/gimpunitcombobox.c | 120 +++++++ app/widgets/gimpunitcombobox.h | 55 ++++ app/widgets/gimpunitstore.c | 550 +++++++++++++++++++++++++++++++++ app/widgets/gimpunitstore.h | 91 ++++++ app/widgets/widgets-types.h | 2 + themes/Default/gtkrc | 37 +-- themes/Small/gtkrc | 39 +-- 11 files changed, 965 insertions(+), 87 deletions(-) create mode 100644 app/widgets/gimpunitcombobox.c create mode 100644 app/widgets/gimpunitcombobox.h create mode 100644 app/widgets/gimpunitstore.c create mode 100644 app/widgets/gimpunitstore.h diff --git a/ChangeLog b/ChangeLog index a460bbad23..996055038c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2004-05-08 Sven Neumann + + * app/widgets/Makefile.am + * app/widgets/widgets-types.h + * app/widgets/gimpunitcombobox.[ch] + * app/widgets/gimpunitstore.[ch]: added a prototype of a unit menu + based on GtkComboBox. Will move this to libgimpwidgets later... + + * app/display/gimpstatusbar.[ch]: use the new GimpUnitComboBox and + GimpUnitStore. + + * themes/Default/gtkrc + * themes/Small/gtkrc: hardcode the appearance of the + GimpUnitComboBox. It uses a hack that doesn't work in list mode. + 2004-05-07 Sven Neumann * app/core/gimpimage-colormap.[ch]: added a const qualifier. diff --git a/app/display/gimpstatusbar.c b/app/display/gimpstatusbar.c index 5cb3e11bcc..2b1dd83c48 100644 --- a/app/display/gimpstatusbar.c +++ b/app/display/gimpstatusbar.c @@ -25,6 +25,9 @@ #include "core/gimpimage.h" #include "core/gimpimage-unit.h" +#include "widgets/gimpunitstore.h" +#include "widgets/gimpunitcombobox.h" + #include "gimpdisplay.h" #include "gimpdisplayshell.h" #include "gimpstatusbar.h" @@ -38,12 +41,17 @@ #define CURSOR_STR_LENGTH 256 -static void gimp_statusbar_class_init (GimpStatusbarClass *klass); -static void gimp_statusbar_init (GimpStatusbar *statusbar); +static void gimp_statusbar_class_init (GimpStatusbarClass *klass); +static void gimp_statusbar_init (GimpStatusbar *statusbar); -static void gimp_statusbar_update (GtkStatusbar *gtk_statusbar, - guint context_id, - const gchar *text); +static void gimp_statusbar_update (GtkStatusbar *gtk_statusbar, + guint context_id, + const gchar *text); +static void gimp_statusbar_set_cursor (GimpStatusbar *statusbar, + gdouble x, + gdouble y); +static void gimp_statusbar_unit_changed (GtkWidget *combo, + GimpStatusbar *statusbar); static GtkStatusbarClass *parent_class = NULL; @@ -95,6 +103,7 @@ gimp_statusbar_init (GimpStatusbar *statusbar) { GtkStatusbar *gtk_statusbar; GtkBox *box; + GimpUnitStore *store; GtkShadowType shadow_type; gtk_statusbar = GTK_STATUSBAR (statusbar); @@ -122,6 +131,17 @@ gimp_statusbar_init (GimpStatusbar *statusbar) statusbar->cursor_label); gtk_widget_show (statusbar->cursor_label); + store = gimp_unit_store_new (2); + statusbar->combo = gimp_unit_combo_box_new_with_model (store); + g_object_unref (store); + + gtk_box_pack_start (box, statusbar->combo, FALSE, FALSE, 0); + gtk_widget_show (statusbar->combo); + + g_signal_connect (statusbar->combo, "changed", + G_CALLBACK (gimp_statusbar_unit_changed), + statusbar); + statusbar->progressbar = gtk_progress_bar_new (); gtk_box_pack_start (box, statusbar->progressbar, TRUE, TRUE, 0); gtk_widget_show (statusbar->progressbar); @@ -264,31 +284,7 @@ gimp_statusbar_update_cursor (GimpStatusbar *statusbar, } else { - GimpImage *gimage; - gchar buffer[CURSOR_STR_LENGTH]; - - gimage = statusbar->shell->gdisp->gimage; - - if (gimage->unit == GIMP_UNIT_PIXEL) - { - g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, - "", - ROUND (x), - ", ", - ROUND (y)); - } - else /* show real world units */ - { - gdouble unit_factor = gimp_image_unit_get_factor (gimage); - - g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, - "", - x * unit_factor / gimage->xresolution, - ", ", - y * unit_factor / gimage->yresolution); - } - - gtk_label_set_text (GTK_LABEL (statusbar->cursor_label), buffer); + gimp_statusbar_set_cursor (statusbar, x, y); } } @@ -299,48 +295,50 @@ gimp_statusbar_resize_cursor (GimpStatusbar *statusbar) GimpDisplayShell *shell; GimpImage *gimage; - gchar buffer[CURSOR_STR_LENGTH]; + GtkTreeModel *model; + const gchar *text; gint cursor_label_width; gint label_frame_size_difference; g_return_if_fail (GIMP_IS_STATUSBAR (statusbar)); - shell = statusbar->shell; + shell = statusbar->shell; gimage = shell->gdisp->gimage; + model = gtk_combo_box_get_model (GTK_COMBO_BOX (statusbar->combo)); + gimp_unit_store_set_resolutions (GIMP_UNIT_STORE (model), + gimage->xresolution, gimage->yresolution); + + g_signal_handlers_block_by_func (statusbar->combo, + gimp_statusbar_unit_changed, statusbar); + gtk_combo_box_set_active (GTK_COMBO_BOX (statusbar->combo), gimage->unit); + g_signal_handlers_unblock_by_func (statusbar->combo, + gimp_statusbar_unit_changed, statusbar); + if (gimage->unit == GIMP_UNIT_PIXEL) { g_snprintf (statusbar->cursor_format_str, sizeof (statusbar->cursor_format_str), "%%s%%d%%s%%d"); - - g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, - "", shell->gdisp->gimage->width, - ", ", shell->gdisp->gimage->height); } else /* show real world units */ { - gdouble unit_factor = gimp_image_unit_get_factor (gimage); - g_snprintf (statusbar->cursor_format_str, sizeof (statusbar->cursor_format_str), - "%%s%%.%df%%s%%.%df %s", - gimp_image_unit_get_digits (gimage), - gimp_image_unit_get_digits (gimage), - gimp_image_unit_get_symbol (gimage)); - - g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, - "", - (gdouble) gimage->width * unit_factor / gimage->xresolution, - ", ", - (gdouble) gimage->height * unit_factor / gimage->yresolution); + "%%s%%.%df%%s%%.%df", + gimp_image_unit_get_digits (gimage), + gimp_image_unit_get_digits (gimage)); } + gimp_statusbar_set_cursor (statusbar, gimage->width, gimage->height); + + text = gtk_label_get_text (GTK_LABEL (statusbar->cursor_label)); + /* one static layout for all displays should be fine */ if (! layout) - layout = gtk_widget_create_pango_layout (statusbar->cursor_label, buffer); + layout = gtk_widget_create_pango_layout (statusbar->cursor_label, text); else - pango_layout_set_text (layout, buffer, -1); + pango_layout_set_text (layout, text, -1); pango_layout_get_pixel_size (layout, &cursor_label_width, NULL); @@ -359,3 +357,43 @@ gimp_statusbar_resize_cursor (GimpStatusbar *statusbar) label_frame_size_difference, -1); } + +static void +gimp_statusbar_set_cursor (GimpStatusbar *statusbar, + gdouble x, + gdouble y) +{ + GimpImage *image = statusbar->shell->gdisp->gimage; + GtkTreeModel *model; + GimpUnitStore *store; + gchar buffer[CURSOR_STR_LENGTH]; + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (statusbar->combo)); + store = GIMP_UNIT_STORE (model); + + gimp_unit_store_set_pixel_values (store, x, y); + + if (image->unit == GIMP_UNIT_PIXEL) + { + g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, + "", ROUND (x), ", ", ROUND (y)); + } + else /* show real world units */ + { + gimp_unit_store_get_values (store, image->unit, &x, &y); + + g_snprintf (buffer, sizeof (buffer), statusbar->cursor_format_str, + "", x, ", ", y); + } + + gtk_label_set_text (GTK_LABEL (statusbar->cursor_label), buffer); +} + +static void +gimp_statusbar_unit_changed (GtkWidget *combo, + GimpStatusbar *statusbar) +{ + gimp_image_set_unit (statusbar->shell->gdisp->gimage, + gtk_combo_box_get_active (GTK_COMBO_BOX (combo))); +} + diff --git a/app/display/gimpstatusbar.h b/app/display/gimpstatusbar.h index a96cd00179..016e76d884 100644 --- a/app/display/gimpstatusbar.h +++ b/app/display/gimpstatusbar.h @@ -47,6 +47,7 @@ struct _GimpStatusbar GtkWidget *cursor_frame; GtkWidget *cursor_label; gchar cursor_format_str[CURSOR_FORMAT_LENGTH]; + GtkWidget *combo; GtkWidget *progressbar; guint progressid; diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am index 40869b6d21..7789416a2c 100644 --- a/app/widgets/Makefile.am +++ b/app/widgets/Makefile.am @@ -206,6 +206,10 @@ libappwidgets_a_sources = \ gimpuimanager.h \ gimpundoeditor.c \ gimpundoeditor.h \ + gimpunitcombobox.c \ + gimpunitcombobox.h \ + gimpunitstore.c \ + gimpunitstore.h \ gimpvectorstreeview.c \ gimpvectorstreeview.h \ gimpviewablebutton.c \ diff --git a/app/widgets/gimpunitcombobox.c b/app/widgets/gimpunitcombobox.c new file mode 100644 index 0000000000..51928bb237 --- /dev/null +++ b/app/widgets/gimpunitcombobox.c @@ -0,0 +1,120 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpunitcombobox.c + * Copyright (C) 2004 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 "config.h" + +#include + +#include "widgets-types.h" + +#include "gimpunitcombobox.h" +#include "gimpunitstore.h" + + +static void gimp_unit_combo_box_init (GimpUnitComboBox *combo); + + +GType +gimp_unit_combo_box_get_type (void) +{ + static GType combo_box_type = 0; + + if (!combo_box_type) + { + static const GTypeInfo combo_box_info = + { + sizeof (GimpUnitComboBoxClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpUnitComboBox), + 0, /* n_preallocs */ + (GInstanceInitFunc) gimp_unit_combo_box_init + }; + + combo_box_type = g_type_register_static (GTK_TYPE_COMBO_BOX, + "GimpUnitComboBox", + &combo_box_info, 0); + } + + return combo_box_type; +} + +static void +gimp_unit_combo_box_init (GimpUnitComboBox *combo) +{ + GtkCellLayout *layout = GTK_CELL_LAYOUT (combo); + GtkCellRenderer *cell; + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (layout, cell, TRUE); + gtk_cell_layout_set_attributes (layout, cell, + "text", GIMP_UNIT_STORE_UNIT_PLURAL, + NULL); + + /* hackedehack ... */ + layout = GTK_CELL_LAYOUT (GTK_BIN (combo)->child); + gtk_cell_layout_clear (layout); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (layout, cell, TRUE); + gtk_cell_layout_set_attributes (layout, cell, + "text", GIMP_UNIT_STORE_UNIT_ABBREVIATION, + NULL); +} + +/** + * gimp_unit_combo_box_new: + * + * Return value: a new #GimpUnitComboBox. + **/ +GtkWidget * +gimp_unit_combo_box_new (void) +{ + GtkWidget *combo_box; + GimpUnitStore *store; + + store = gimp_unit_store_new (0); + + combo_box = g_object_new (GIMP_TYPE_UNIT_COMBO_BOX, + "model", store, + NULL); + + g_object_unref (store); + + return combo_box; +} + +/** + * gimp_unit_combo_box_new_with_model: + * @model: a GimpUnitStore + * + * Return value: a new #GimpUnitComboBox. + **/ +GtkWidget * +gimp_unit_combo_box_new_with_model (GimpUnitStore *model) +{ + return g_object_new (GIMP_TYPE_UNIT_COMBO_BOX, + "model", model, + NULL); +} diff --git a/app/widgets/gimpunitcombobox.h b/app/widgets/gimpunitcombobox.h new file mode 100644 index 0000000000..0683225c86 --- /dev/null +++ b/app/widgets/gimpunitcombobox.h @@ -0,0 +1,55 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpunitcombobox.h + * Copyright (C) 2004 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_UNIT_COMBO_BOX_H__ +#define __GIMP_UNIT_COMBO_BOX_H__ + +#include + + +#define GIMP_TYPE_UNIT_COMBO_BOX (gimp_unit_combo_box_get_type ()) +#define GIMP_UNIT_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_UNIT_COMBO_BOX, GimpUnitComboBox)) +#define GIMP_UNIT_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_UNIT_COMBO_BOX, GimpUnitComboBoxClass)) +#define GIMP_IS_UNIT_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_UNIT_COMBO_BOX)) +#define GIMP_IS_UNIT_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_UNIT_COMBO_BOX)) +#define GIMP_UNIT_COMBO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_UNIT_COMBO_BOX, GimpUnitComboBoxClass)) + + +typedef struct _GimpUnitComboBoxClass GimpUnitComboBoxClass; + +struct _GimpUnitComboBoxClass +{ + GtkComboBoxClass parent_instance; +}; + +struct _GimpUnitComboBox +{ + GtkComboBox parent_instance; +}; + + +GType gimp_unit_combo_box_get_type (void) G_GNUC_CONST; + +GtkWidget * gimp_unit_combo_box_new (void); +GtkWidget * gimp_unit_combo_box_new_with_model (GimpUnitStore *model); + + +#endif /* __GIMP_UNIT_COMBO_BOX_H__ */ diff --git a/app/widgets/gimpunitstore.c b/app/widgets/gimpunitstore.c new file mode 100644 index 0000000000..ccbe3ef1b7 --- /dev/null +++ b/app/widgets/gimpunitstore.c @@ -0,0 +1,550 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpunitstore.c + * Copyright (C) 2004 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 "config.h" + +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "widgets-types.h" + +#include "config/gimpconfig-types.h" + +#include "gimpunitstore.h" + + +enum +{ + PROP_0, + PROP_NUM_VALUES +}; + +static GType column_types[GIMP_UNIT_STORE_UNIT_COLUMNS] = +{ + G_TYPE_INVALID, + G_TYPE_DOUBLE, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING +}; + +static void gimp_unit_store_class_init (GimpUnitStoreClass *klass); +static void gimp_unit_store_tree_model_init (GtkTreeModelIface *iface); + +static void gimp_unit_store_finalize (GObject *object); +static void gimp_unit_store_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_unit_store_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static GtkTreeModelFlags gimp_unit_store_get_flags (GtkTreeModel *tree_model); +static gint gimp_unit_store_get_n_columns (GtkTreeModel *tree_model); +static GType gimp_unit_store_get_column_type (GtkTreeModel *tree_model, + gint index); +static gboolean gimp_unit_store_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path); +static GtkTreePath *gimp_unit_store_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static void gimp_unit_store_tree_model_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value); +static gboolean gimp_unit_store_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean gimp_unit_store_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent); +static gboolean gimp_unit_store_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gint gimp_unit_store_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean gimp_unit_store_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n); +static gboolean gimp_unit_store_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child); + + +static GObjectClass *parent_class = NULL; + + +GType +gimp_unit_store_get_type (void) +{ + static GType store_type = 0; + + if (!store_type) + { + static const GTypeInfo store_info = + { + sizeof (GimpUnitStoreClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gimp_unit_store_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GimpUnitStore), + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + + static const GInterfaceInfo tree_model_info = + { + (GInterfaceInitFunc) gimp_unit_store_tree_model_init, + NULL, + NULL + }; + + store_type = g_type_register_static (G_TYPE_OBJECT, + "GimpUnitStore", + &store_info, 0); + + g_type_add_interface_static (store_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + + return store_type; +} + +static void +gimp_unit_store_class_init (GimpUnitStoreClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + column_types[GIMP_UNIT_STORE_UNIT] = GIMP_TYPE_UNIT; + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gimp_unit_store_finalize; + object_class->set_property = gimp_unit_store_set_property; + object_class->get_property = gimp_unit_store_get_property; + + g_object_class_install_property (object_class, PROP_NUM_VALUES, + g_param_spec_int ("num-values", + NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +}; + +static void +gimp_unit_store_tree_model_init (GtkTreeModelIface *iface) +{ + iface->get_flags = gimp_unit_store_get_flags; + iface->get_n_columns = gimp_unit_store_get_n_columns; + iface->get_column_type = gimp_unit_store_get_column_type; + iface->get_iter = gimp_unit_store_get_iter; + iface->get_path = gimp_unit_store_get_path; + iface->get_value = gimp_unit_store_tree_model_get_value; + iface->iter_next = gimp_unit_store_iter_next; + iface->iter_children = gimp_unit_store_iter_children; + iface->iter_has_child = gimp_unit_store_iter_has_child; + iface->iter_n_children = gimp_unit_store_iter_n_children; + iface->iter_nth_child = gimp_unit_store_iter_nth_child; + iface->iter_parent = gimp_unit_store_iter_parent; +} + +static void +gimp_unit_store_finalize (GObject *object) +{ + GimpUnitStore *store = GIMP_UNIT_STORE (object); + + if (store->num_values > 0) + { + g_free (store->values); + g_free (store->resolutions); + store->num_values = 0; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_unit_store_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpUnitStore *store = GIMP_UNIT_STORE (object); + + switch (property_id) + { + case PROP_NUM_VALUES: + g_return_if_fail (store->num_values == 0); + store->num_values = g_value_get_int (value); + if (store->num_values) + { + store->values = g_new0 (gdouble, store->num_values); + store->resolutions = g_new0 (gdouble, store->num_values); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_unit_store_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpUnitStore *store = GIMP_UNIT_STORE (object); + + switch (property_id) + { + case PROP_NUM_VALUES: + g_value_set_int (value, store->num_values); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static GtkTreeModelFlags +gimp_unit_store_get_flags (GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY; +} + +static gint +gimp_unit_store_get_n_columns (GtkTreeModel *tree_model) +{ + GimpUnitStore *store = GIMP_UNIT_STORE (tree_model); + + return GIMP_UNIT_STORE_UNIT_COLUMNS + store->num_values; +} + +static GType +gimp_unit_store_get_column_type (GtkTreeModel *tree_model, + gint index) +{ + g_return_val_if_fail (index >= 0, G_TYPE_INVALID); + + if (index < GIMP_UNIT_STORE_UNIT_COLUMNS) + return column_types[index]; + + return G_TYPE_DOUBLE; +} + +static gboolean +gimp_unit_store_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path) +{ + gint unit; + + g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); + + unit = gtk_tree_path_get_indices (path)[0]; + + if (unit >= 0 && unit < gimp_unit_get_number_of_units ()) + { + iter->user_data = GINT_TO_POINTER (unit); + return TRUE; + } + + return FALSE; +} + +static GtkTreePath * +gimp_unit_store_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreePath *path = gtk_tree_path_new (); + + gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data)); + + return path; +} + +static void +gimp_unit_store_tree_model_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value) +{ + GimpUnitStore *store = GIMP_UNIT_STORE (tree_model); + GimpUnit unit; + + g_return_if_fail (column >= 0 && + column < GIMP_UNIT_STORE_UNIT_COLUMNS + store->num_values); + + g_value_init (value, + column < GIMP_UNIT_STORE_UNIT_COLUMNS ? + column_types[column] : + G_TYPE_DOUBLE); + + unit = GPOINTER_TO_INT (iter->user_data); + + if (unit >= 0 && unit < gimp_unit_get_number_of_units ()) + { + switch (column) + { + case GIMP_UNIT_STORE_UNIT: + g_value_set_int (value, unit); + break; + case GIMP_UNIT_STORE_UNIT_FACTOR: + g_value_set_double (value, gimp_unit_get_factor (unit)); + break; + case GIMP_UNIT_STORE_UNIT_DIGITS: + g_value_set_int (value, gimp_unit_get_digits (unit)); + break; + case GIMP_UNIT_STORE_UNIT_IDENTIFIER: + g_value_set_static_string (value, gimp_unit_get_identifier (unit)); + break; + case GIMP_UNIT_STORE_UNIT_SYMBOL: + g_value_set_static_string (value, gimp_unit_get_symbol (unit)); + break; + case GIMP_UNIT_STORE_UNIT_ABBREVIATION: + g_value_set_static_string (value, gimp_unit_get_abbreviation (unit)); + break; + case GIMP_UNIT_STORE_UNIT_SINGULAR: + g_value_set_static_string (value, gimp_unit_get_singular (unit)); + break; + case GIMP_UNIT_STORE_UNIT_PLURAL: + g_value_set_static_string (value, gimp_unit_get_plural (unit)); + break; + + default: + column -= GIMP_UNIT_STORE_UNIT_COLUMNS; + if (column < store->num_values && store->resolutions[column]) + g_value_set_double (value, + store->values[column] * + gimp_unit_get_factor (unit) / + store->resolutions[column]); + break; + } + } +} + +static gboolean +gimp_unit_store_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + gint unit = GPOINTER_TO_INT (iter->user_data); + + unit++; + if (unit > 0 && unit < gimp_unit_get_number_of_units ()) + { + iter->user_data = GINT_TO_POINTER (unit); + return TRUE; + } + + return FALSE; +} + +static gboolean +gimp_unit_store_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + + iter->user_data = GINT_TO_POINTER (0); + + return TRUE; +} + +static gboolean +gimp_unit_store_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + return FALSE; +} + +static gint +gimp_unit_store_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + if (iter) + return 0; + + return gimp_unit_get_number_of_units (); +} + +static gboolean +gimp_unit_store_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n) +{ + GimpUnitStore *store; + + if (parent) + return FALSE; + + store = GIMP_UNIT_STORE (tree_model); + + if (n >= 0 && n < gimp_unit_get_number_of_units ()) + { + iter->user_data = GINT_TO_POINTER (n); + return TRUE; + } + + return FALSE; +} + +static gboolean +gimp_unit_store_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child) +{ + return FALSE; +} + + +GimpUnitStore * +gimp_unit_store_new (gint num_values) +{ + return g_object_new (GIMP_TYPE_UNIT_STORE, + "num-values", num_values, + NULL); +} + +void +gimp_unit_store_set_pixel_value (GimpUnitStore *store, + gint index, + gdouble value) +{ + g_return_if_fail (GIMP_IS_UNIT_STORE (store)); + g_return_if_fail (index > 0 && index < store->num_values); + + store->values[index] = value; +} + +void +gimp_unit_store_set_pixel_values (GimpUnitStore *store, + gdouble first_value, + ...) +{ + va_list args; + gint i; + + g_return_if_fail (GIMP_IS_UNIT_STORE (store)); + + va_start (args, first_value); + + for (i = 0; i < store->num_values; i++) + { + store->values[i] = first_value; + + first_value = va_arg (args, gdouble); + } + + va_end (args); +} + +void +gimp_unit_store_set_resolution (GimpUnitStore *store, + gint index, + gdouble resolution) +{ + g_return_if_fail (GIMP_IS_UNIT_STORE (store)); + g_return_if_fail (index > 0 && index < store->num_values); + + store->resolutions[index] = resolution; +} + +void +gimp_unit_store_set_resolutions (GimpUnitStore *store, + gdouble first_resolution, + ...) +{ + va_list args; + gint i; + + g_return_if_fail (GIMP_IS_UNIT_STORE (store)); + + va_start (args, first_resolution); + + for (i = 0; i < store->num_values; i++) + { + store->resolutions[i] = first_resolution; + + first_resolution = va_arg (args, gdouble); + } + + va_end (args); +} + +gdouble +gimp_unit_store_get_value (GimpUnitStore *store, + GimpUnit unit, + gint index) +{ + GtkTreeIter iter; + GValue value = { 0, }; + + g_return_val_if_fail (GIMP_IS_UNIT_STORE (store), 0.0); + g_return_val_if_fail (index >= 0 && index < store->num_values, 0.0); + + iter.user_data = GINT_TO_POINTER (unit); + + gimp_unit_store_tree_model_get_value (GTK_TREE_MODEL (store), + &iter, + GIMP_UNIT_STORE_FIRST_VALUE + index, + &value); + + return g_value_get_double (&value); +} + +void +gimp_unit_store_get_values (GimpUnitStore *store, + GimpUnit unit, + gdouble *first_value, + ...) +{ + va_list args; + gint i; + + g_return_if_fail (GIMP_IS_UNIT_STORE (store)); + + va_start (args, first_value); + + for (i = 0; i < store->num_values; i++) + { + if (first_value) + *first_value = gimp_unit_store_get_value (store, unit, i); + + first_value = va_arg (args, gdouble *); + } + + va_end (args); +} diff --git a/app/widgets/gimpunitstore.h b/app/widgets/gimpunitstore.h new file mode 100644 index 0000000000..a7c780992a --- /dev/null +++ b/app/widgets/gimpunitstore.h @@ -0,0 +1,91 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpunitstore.h + * Copyright (C) 2004 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_UNIT_STORE_H__ +#define __GIMP_UNIT_STORE_H__ + + +enum +{ + GIMP_UNIT_STORE_UNIT, + GIMP_UNIT_STORE_UNIT_FACTOR, + GIMP_UNIT_STORE_UNIT_DIGITS, + GIMP_UNIT_STORE_UNIT_IDENTIFIER, + GIMP_UNIT_STORE_UNIT_SYMBOL, + GIMP_UNIT_STORE_UNIT_ABBREVIATION, + GIMP_UNIT_STORE_UNIT_SINGULAR, + GIMP_UNIT_STORE_UNIT_PLURAL, + GIMP_UNIT_STORE_UNIT_COLUMNS, + GIMP_UNIT_STORE_FIRST_VALUE = GIMP_UNIT_STORE_UNIT_COLUMNS +}; + + +#define GIMP_TYPE_UNIT_STORE (gimp_unit_store_get_type ()) +#define GIMP_UNIT_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_UNIT_STORE, GimpUnitStore)) +#define GIMP_UNIT_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_UNIT_STORE, GimpUnitStoreClass)) +#define GIMP_IS_UNIT_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_UNIT_STORE)) +#define GIMP_IS_UNIT_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_UNIT_STORE)) +#define GIMP_UNIT_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_UNIT_STORE, GimpUnitStoreClass)) + + +typedef struct _GimpUnitStoreClass GimpUnitStoreClass; + +struct _GimpUnitStoreClass +{ + GObjectClass parent_class; +}; + +struct _GimpUnitStore +{ + GObject parent_instance; + + gint num_values; + gdouble *values; + gdouble *resolutions; +}; + + +GType gimp_unit_store_get_type (void) G_GNUC_CONST; + +GimpUnitStore * gimp_unit_store_new (gint num_values); + +void gimp_unit_store_set_pixel_value (GimpUnitStore *store, + gint index, + gdouble value); +void gimp_unit_store_set_pixel_values (GimpUnitStore *store, + gdouble first_value, + ...); +void gimp_unit_store_set_resolution (GimpUnitStore *store, + gint index, + gdouble resolution); +void gimp_unit_store_set_resolutions (GimpUnitStore *store, + gdouble first_resolution, + ...); +gdouble gimp_unit_store_get_value (GimpUnitStore *store, + GimpUnit unit, + gint index); +void gimp_unit_store_get_values (GimpUnitStore *store, + GimpUnit unit, + gdouble *first_value, + ...); + + +#endif /* __GIMP_UNIT_STORE_H__ */ diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index 84f9fa49af..ba27b51d27 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -41,6 +41,7 @@ typedef struct _GimpStringAction GimpStringAction; typedef struct _GimpUIManager GimpUIManager; typedef struct _GimpEnumStore GimpEnumStore; +typedef struct _GimpUnitStore GimpUnitStore; typedef struct _GimpCellRendererToggle GimpCellRendererToggle; typedef struct _GimpCellRendererViewable GimpCellRendererViewable; @@ -66,6 +67,7 @@ typedef struct _GimpContainerMenuImpl GimpContainerMenuImpl; typedef struct _GimpMenuItem GimpMenuItem; typedef struct _GimpEnumComboBox GimpEnumComboBox; +typedef struct _GimpUnitComboBox GimpUnitComboBox; typedef struct _GimpEditor GimpEditor; typedef struct _GimpDeviceStatus GimpDeviceStatus; diff --git a/themes/Default/gtkrc b/themes/Default/gtkrc index af071c19fc..ab3af13d94 100644 --- a/themes/Default/gtkrc +++ b/themes/Default/gtkrc @@ -36,24 +36,25 @@ style "gimp-default-style" { "images/stock-warning-64.png", *, *, "gtk-dialog" } } - GtkPaned::handle_size = 6 - GimpDock::separator_height = 6 - GimpDock::default_height = 300 - GimpImageDock::minimal_width = 250 - GimpImageDock::menu_preview_size = button - GimpToolbox::tool_icon_size = button - GimpToolbox::button_relief = none - GimpDockbook::tab_border = 0 - GimpDockbook::tab_icon_size = button - GimpColorNotebook::tab_border = 0 - GimpColorNotebook::tab_icon_size = button - GimpDockable::content_border = 2 - GimpEditor::content_spacing = 2 - GimpEditor::button_spacing = 2 - GimpEditor::button_icon_size = menu - GtkDialog::content_area_border = 0 - GtkDialog::button_spacing = 6 - GtkDialog::action_area_border = 12 + GtkPaned::handle_size = 6 + GimpDock::separator_height = 6 + GimpDock::default_height = 300 + GimpImageDock::minimal_width = 250 + GimpImageDock::menu_preview_size = button + GimpToolbox::tool_icon_size = button + GimpToolbox::button_relief = none + GimpDockbook::tab_border = 0 + GimpDockbook::tab_icon_size = button + GimpColorNotebook::tab_border = 0 + GimpColorNotebook::tab_icon_size = button + GimpDockable::content_border = 2 + GimpEditor::content_spacing = 2 + GimpEditor::button_spacing = 2 + GimpEditor::button_icon_size = menu + GtkDialog::content_area_border = 0 + GtkDialog::button_spacing = 6 + GtkDialog::action_area_border = 12 + GimpUnitComboBox::appears_as_list = 0 } class "GtkWidget" style "gimp-default-style" diff --git a/themes/Small/gtkrc b/themes/Small/gtkrc index ee0f1f3ebc..88871624b7 100644 --- a/themes/Small/gtkrc +++ b/themes/Small/gtkrc @@ -41,25 +41,26 @@ style "gimp-default-style" GtkOptionMenu::indicator_size = { 5, 11 } GtkOptionMenu::indicator_spacing = { 4, 3, 1, 1 } - GtkPaned::handle_size = 5 - GimpDock::separator_height = 5 - GimpDock::default_height = 240 - GimpImageDock::minimal_width = 200 - GimpImageDock::menu_preview_size = small-toolbar - GimpToolbox::tool_icon_size = menu - GimpToolbox::button_relief = none - GimpDockbook::tab_border = 0 - GimpDockbook::tab_icon_size = menu - GimpColorNotebook::tab_border = 0 - GimpColorNotebook::tab_icon_size = menu - GimpDockable::content_border = 1 - GimpEditor::content_spacing = 1 - GimpEditor::button_spacing = 1 - GimpEditor::button_icon_size = menu - GimpFrame::label_spacing = 2 - GtkDialog::content_area_border = 0 - GtkDialog::button_spacing = 4 - GtkDialog::action_area_border = 6 + GtkPaned::handle_size = 5 + GimpDock::separator_height = 5 + GimpDock::default_height = 240 + GimpImageDock::minimal_width = 200 + GimpImageDock::menu_preview_size = small-toolbar + GimpToolbox::tool_icon_size = menu + GimpToolbox::button_relief = none + GimpDockbook::tab_border = 0 + GimpDockbook::tab_icon_size = menu + GimpColorNotebook::tab_border = 0 + GimpColorNotebook::tab_icon_size = menu + GimpDockable::content_border = 1 + GimpEditor::content_spacing = 1 + GimpEditor::button_spacing = 1 + GimpEditor::button_icon_size = menu + GimpFrame::label_spacing = 2 + GtkDialog::content_area_border = 0 + GtkDialog::button_spacing = 4 + GtkDialog::action_area_border = 6 + GimpUnitComboBox::appears_as_list = 0 } class "GtkWidget" style "gimp-default-style"