/* gtkplot - 2d scientific plots widget for gtk+ * Copyright 1999-2001 Adrian E. Feiguin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "gtkplot.h" #include "gtkplotdata.h" #include "gtkpsfont.h" #include "gtkplotgdk.h" #include "gtkextra-marshal.h" #define DEFAULT_WIDTH 420 #define DEFAULT_HEIGHT 340 #define DEFAULT_FONT_HEIGHT 12 #define LABEL_MAX_LENGTH 100 #define P_(string) string static gchar DEFAULT_FONT[] = "Helvetica"; /* Signals */ extern void _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...); enum { ADD_DATA, CHANGED, UPDATE, MOVED, RESIZED, LAST_SIGNAL }; enum { TICK_LABEL, AXIS_CHANGED, LAST_AXIS_SIGNAL }; enum { ARG_PLOT_0, ARG_BOTTOM, ARG_TOP, ARG_LEFT, ARG_RIGHT, ARG_ALLOCATION_X, ARG_ALLOCATION_Y, ARG_ALLOCATION_WIDTH, ARG_ALLOCATION_HEIGHT, ARG_USE_PIXMAP, ARG_BG_PIXMAP, ARG_TRANSPARENT, ARG_MAGNIFICATION, ARG_CLIP_DATA, ARG_BG, ARG_GRIDS_ON_TOP, ARG_SHOW_X0, ARG_SHOW_Y0, ARG_X0_LINE, ARG_Y0_LINE, ARG_XMIN, ARG_XMAX, ARG_YMIN, ARG_YMAX, ARG_X, ARG_Y, ARG_WIDTH, ARG_HEIGHT, ARG_XSCALE, ARG_YSCALE, ARG_REFLECT_X, ARG_REFLECT_Y, ARG_BOTTOM_ALIGN, ARG_TOP_ALIGN, ARG_LEFT_ALIGN, ARG_RIGHT_ALIGN, ARG_LEGENDS_X, ARG_LEGENDS_Y, ARG_LEGENDS_WIDTH, ARG_LEGENDS_HEIGHT, ARG_LEGENDS_BORDER, ARG_LEGENDS_LINE_WIDTH, ARG_LEGENDS_BORDER_WIDTH, ARG_LEGENDS_SHADOW_WIDTH, ARG_LEGENDS_SHOW, ARG_LEGENDS_ATTR, ARG_LEGENDS_TRANSPARENT, }; enum { ARG_AXIS_0, ARG_VISIBLE, ARG_TITLE, ARG_TITLE_VISIBLE, ARG_ORIENTATION, ARG_LINE, ARG_MAJOR_GRID, ARG_MINOR_GRID, ARG_MAJOR_MASK, ARG_MINOR_MASK, ARG_TICKS_LENGTH, ARG_TICKS_WIDTH, ARG_CUSTOM_LABELS, ARG_LABELS_OFFSET, ARG_LABELS_PREFIX, ARG_LABELS_SUFFIX, ARG_SHOW_MAJOR_GRID, ARG_SHOW_MINOR_GRID, ARG_LABELS_ATTR, ARG_LABELS_PRECISION, ARG_LABELS_STYLE, ARG_LABELS_MASK, ARG_TICKS_MIN, ARG_TICKS_MAX, ARG_TICK_LABELS, ARG_SCALE, ARG_NMAJORTICKS, ARG_NMINORTICKS, ARG_NTICKS, ARG_STEP, ARG_NMINOR, ARG_APPLY_BREAK, ARG_BREAK_SCALE, ARG_BREAK_STEP, ARG_BREAK_NMINOR, ARG_BREAK_MIN, ARG_BREAK_MAX, ARG_BREAK_POSITION, ARG_SET_LIMITS, ARG_BEGIN, ARG_END }; /* Private methods for ticks */ void gtk_plot_ticks_recalc (GtkPlotAxis *ticks); void gtk_plot_ticks_autoscale (GtkPlotAxis *ticks, gdouble xmin, gdouble xmax, gint *precision); gdouble gtk_plot_ticks_transform (GtkPlotAxis *ticks, gdouble y); gdouble gtk_plot_ticks_inverse (GtkPlotAxis *ticks, gdouble x); void gtk_plot_parse_label (GtkPlotAxis *axis, gdouble val, gint precision, gint style, gchar *label); static void gtk_plot_class_init (GtkPlotClass *klass); static void gtk_plot_init (GtkPlot *plot); static void gtk_plot_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gtk_plot_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gtk_plot_axis_class_init (GtkPlotAxisClass *klass); static void gtk_plot_axis_init (GtkPlotAxis *axis); static void gtk_plot_axis_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gtk_plot_axis_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gtk_plot_destroy (GtkObject *object); static void gtk_plot_axis_destroy (GtkObject *object); static void gtk_plot_real_set_pc (GtkPlot *plot, GtkPlotPC *pc); static void gtk_plot_real_set_drawable (GtkPlot *plot, GdkDrawable *drawable); static void gtk_plot_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_plot_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static void gtk_plot_show_all (GtkWidget *widget); static void gtk_plot_draw_grids (GtkPlot *plot); static void gtk_plot_draw_axis (GtkPlot *plot, GtkPlotAxis *axis, GtkPlotVector tick_direction); static void gtk_plot_draw_labels (GtkPlot *plot, GtkPlotAxis *axis, GtkPlotVector tick_direction); static void gtk_plot_draw_legends (GtkWidget *widget); static void gtk_plot_real_paint (GtkWidget *widget); static void gtk_plot_paint_text (GtkPlot *plot, gint x, gint y, GtkPlotText text); static void gtk_plot_real_get_pixel (GtkWidget *widget, gdouble xx, gdouble yy , gdouble *x, gdouble *y); static void gtk_plot_real_get_point (GtkWidget *widget, gint x, gint y, gdouble *px, gdouble *py); void gtk_plot_remove_dimension (GtkPlot *plot, const gchar *dimension); inline gint roundint (gdouble x); static void update_datasets (GtkPlot *plot, gboolean new_range); static GtkWidgetClass *parent_class = NULL; static guint plot_signals[LAST_SIGNAL] = {0}; static guint axis_signals[LAST_AXIS_SIGNAL] = {0}; GtkType gtk_plot_get_type (void) { static GtkType plot_type = 0; if (!plot_type) { GtkTypeInfo plot_info = { "GtkPlot", sizeof (GtkPlot), sizeof (GtkPlotClass), (GtkClassInitFunc) gtk_plot_class_init, (GtkObjectInitFunc) gtk_plot_init, /* reserved 1*/ NULL, /* reserved 2 */ NULL, (GtkClassInitFunc) NULL, }; plot_type = gtk_type_unique (GTK_TYPE_MISC, &plot_info); } return plot_type; } static void gtk_plot_class_init (GtkPlotClass *klass) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkPlotClass *plot_class; GObjectClass *gobject_class = G_OBJECT_CLASS(klass); parent_class = gtk_type_class (gtk_widget_get_type ()); object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; plot_class = (GtkPlotClass *) klass; widget_class->show_all = gtk_plot_show_all; widget_class->size_request = gtk_plot_size_request; widget_class->size_allocate = gtk_plot_size_allocate; plot_signals[ADD_DATA] = gtk_signal_new("add_data", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotClass, add_data), gtkextra_BOOL__POINTER, GTK_TYPE_BOOL, 1, GTK_TYPE_PLOT_DATA); plot_signals[CHANGED] = gtk_signal_new("changed", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotClass, changed), gtkextra_VOID__VOID, GTK_TYPE_NONE, 0); plot_signals[UPDATE] = gtk_signal_new("update", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotClass, update), gtkextra_VOID__BOOL, GTK_TYPE_NONE, 1, GTK_TYPE_BOOL); plot_signals[MOVED] = gtk_signal_new("moved", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotClass, moved), gtkextra_BOOL__POINTER_POINTER, GTK_TYPE_BOOL, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); plot_signals[RESIZED] = gtk_signal_new("resized", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotClass, resized), gtkextra_BOOL__POINTER_POINTER, GTK_TYPE_BOOL, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); object_class->destroy = gtk_plot_destroy; gobject_class->set_property = gtk_plot_set_property; gobject_class->get_property = gtk_plot_get_property; klass->changed = NULL; klass->moved = NULL; klass->resized = NULL; plot_class->set_pc = gtk_plot_real_set_pc; plot_class->set_drawable = gtk_plot_real_set_drawable; plot_class->add_data = NULL; plot_class->update = update_datasets; plot_class->plot_paint = gtk_plot_real_paint; plot_class->draw_legends = gtk_plot_draw_legends; plot_class->get_point = gtk_plot_real_get_point; plot_class->get_pixel = gtk_plot_real_get_pixel; g_object_class_install_property(gobject_class, ARG_BOTTOM, g_param_spec_object ("bottom_axis", P_(""), P_(""), GTK_TYPE_PLOT_AXIS, G_PARAM_READABLE)); g_object_class_install_property(gobject_class, ARG_TOP, g_param_spec_object ("top_axis", P_(""), P_(""), GTK_TYPE_PLOT_AXIS, G_PARAM_READABLE)); g_object_class_install_property(gobject_class, ARG_LEFT, g_param_spec_object ("left_axis", P_(""), P_(""), GTK_TYPE_PLOT_AXIS, G_PARAM_READABLE)); g_object_class_install_property(gobject_class, ARG_RIGHT, g_param_spec_object ("right_axis", P_(""), P_(""), GTK_TYPE_PLOT_AXIS, G_PARAM_READABLE)); g_object_class_install_property(gobject_class, ARG_ALLOCATION_X, g_param_spec_int ("allocation_x", P_(""), P_(""), -G_MAXINT,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_ALLOCATION_Y, g_param_spec_int ("allocation_y", P_(""), P_(""), -G_MAXINT,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_ALLOCATION_WIDTH, g_param_spec_int ("allocation_width", P_(""), P_(""), -G_MAXINT,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_ALLOCATION_HEIGHT, g_param_spec_int ("allocation_height", P_(""), P_(""), -G_MAXINT,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_USE_PIXMAP, g_param_spec_boolean ("use_pixmap", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BG_PIXMAP, g_param_spec_pointer ("bg_pixmap", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TRANSPARENT, g_param_spec_boolean ("transparent", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_MAGNIFICATION, g_param_spec_double ("magnification", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_CLIP_DATA, g_param_spec_boolean ("clip_data", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BG, g_param_spec_pointer ("bg_color", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_GRIDS_ON_TOP, g_param_spec_boolean ("grids_on_top", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SHOW_X0, g_param_spec_boolean ("show_x0", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SHOW_Y0, g_param_spec_boolean ("show_y0", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_X0_LINE, g_param_spec_pointer ("x0_line", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_Y0_LINE, g_param_spec_pointer ("y0_line", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_XMIN, g_param_spec_double ("xmin", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_XMAX, g_param_spec_double ("xmax", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_YMIN, g_param_spec_double ("ymin", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_YMAX, g_param_spec_double ("ymax", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_X, g_param_spec_double ("x", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_Y, g_param_spec_double ("y", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_WIDTH, g_param_spec_double ("width", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_HEIGHT, g_param_spec_double ("height", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_XSCALE, g_param_spec_int ("xscale", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_YSCALE, g_param_spec_int ("yscale", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_REFLECT_X, g_param_spec_boolean ("reflect_x", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_REFLECT_Y, g_param_spec_boolean ("reflect_y", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BOTTOM_ALIGN, g_param_spec_double ("bottom_align", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TOP_ALIGN, g_param_spec_double ("top_align", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEFT_ALIGN, g_param_spec_double ("left_align", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_RIGHT_ALIGN, g_param_spec_double ("right_align", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_X, g_param_spec_double ("legends_x", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_Y, g_param_spec_double ("legends_y", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_WIDTH, g_param_spec_int ("legends_width", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_HEIGHT, g_param_spec_int ("legends_height", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_BORDER, g_param_spec_int ("legends_border", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_LINE_WIDTH, g_param_spec_int ("legends_line_width", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_BORDER_WIDTH, g_param_spec_int ("legends_border_width", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_SHADOW_WIDTH, g_param_spec_int ("legends_shadow_width", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_SHOW, g_param_spec_boolean ("legends_show", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_ATTR, g_param_spec_pointer ("legends_attr_text", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LEGENDS_TRANSPARENT, g_param_spec_boolean ("legends_transparent", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); } GtkType gtk_plot_axis_get_type (void) { static GtkType axis_type = 0; if (!axis_type) { GtkTypeInfo axis_info = { "GtkPlotAxis", sizeof (GtkPlotAxis), sizeof (GtkPlotAxisClass), (GtkClassInitFunc) gtk_plot_axis_class_init, (GtkObjectInitFunc) gtk_plot_axis_init, /* reserved 1*/ NULL, /* reserved 2 */ NULL, (GtkClassInitFunc) NULL, }; axis_type = gtk_type_unique (GTK_TYPE_OBJECT, &axis_info); } return axis_type; } static void gtk_plot_axis_class_init (GtkPlotAxisClass *klass) { GtkObjectClass *object_class; GtkPlotAxisClass *axis_class; GObjectClass *gobject_class = G_OBJECT_CLASS(klass); object_class = (GtkObjectClass *) klass; axis_class = (GtkPlotAxisClass *) klass; axis_signals[TICK_LABEL] = gtk_signal_new("tick_label", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotAxisClass, tick_label), gtkextra_BOOL__POINTER_POINTER, GTK_TYPE_BOOL, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); axis_signals[AXIS_CHANGED] = gtk_signal_new("changed", GTK_RUN_LAST, GTK_CLASS_TYPE(object_class), GTK_SIGNAL_OFFSET (GtkPlotAxisClass, changed), gtkextra_VOID__VOID, GTK_TYPE_NONE, 0); object_class->destroy = gtk_plot_axis_destroy; gobject_class->set_property = gtk_plot_axis_set_property; gobject_class->get_property = gtk_plot_axis_get_property; axis_class->tick_label = NULL; g_object_class_install_property(gobject_class, ARG_VISIBLE, g_param_spec_boolean ("visible", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TITLE, g_param_spec_pointer ("title_text", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TITLE_VISIBLE, g_param_spec_boolean ("title_visible", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_ORIENTATION, g_param_spec_enum ("orientation", P_(""), P_(""), GTK_TYPE_ORIENTATION,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LINE, g_param_spec_pointer ("line", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_MAJOR_GRID, g_param_spec_pointer ("major_grid_line", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_MINOR_GRID, g_param_spec_pointer ("minor_grid_line", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_MAJOR_MASK, g_param_spec_int ("major_mask", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_MINOR_MASK, g_param_spec_int ("minor_mask", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TICKS_LENGTH, g_param_spec_int ("ticks_length", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TICKS_WIDTH, g_param_spec_double ("ticks_width", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_CUSTOM_LABELS, g_param_spec_boolean ("custom_labels", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TICK_LABELS, g_param_spec_object ("labels_array", P_(""), P_(""), GTK_TYPE_PLOT_ARRAY, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_OFFSET, g_param_spec_int ("labels_offset", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_PREFIX, g_param_spec_string ("labels_prefix", P_(""), P_(""), NULL, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_SUFFIX, g_param_spec_string ("labels_suffix", P_(""), P_(""), NULL, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SHOW_MAJOR_GRID, g_param_spec_boolean ("show_major_grid", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SHOW_MINOR_GRID, g_param_spec_boolean ("show_minor_grid", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_ATTR, g_param_spec_pointer ("labels_text", P_(""), P_(""), G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_PRECISION, g_param_spec_int ("labels_precision", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_STYLE, g_param_spec_int ("labels_style", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_LABELS_MASK, g_param_spec_int ("labels_mask", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TICKS_MIN, g_param_spec_double ("min", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_TICKS_MAX, g_param_spec_double ("max", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SCALE, g_param_spec_int ("scale", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_NMAJORTICKS, g_param_spec_int ("nmajorticks", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_NMINORTICKS, g_param_spec_int ("nminorticks", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_NTICKS, g_param_spec_int ("nticks", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_STEP, g_param_spec_double ("step", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_NMINOR, g_param_spec_int ("nminor", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_APPLY_BREAK, g_param_spec_boolean ("apply_break", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_SCALE, g_param_spec_int ("break_scale", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_MIN, g_param_spec_double ("break_min", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_MAX, g_param_spec_double ("break_max", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_STEP, g_param_spec_double ("break_step", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_NMINOR, g_param_spec_int ("break_nminor", P_(""), P_(""), 0,G_MAXINT,0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BREAK_POSITION, g_param_spec_double ("break_position", P_(""), P_(""), 0,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_SET_LIMITS, g_param_spec_boolean ("set_limits", P_(""), P_(""), FALSE, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_BEGIN, g_param_spec_double ("begin", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); g_object_class_install_property(gobject_class, ARG_END, g_param_spec_double ("end", P_(""), P_(""), -G_MAXDOUBLE,G_MAXDOUBLE,0.0, G_PARAM_READABLE|G_PARAM_WRITABLE)); } static void axis_changed(GtkPlotAxis *axis, GtkPlot *plot) { gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } static void gtk_plot_init (GtkPlot *plot) { GtkWidget *widget; GTK_WIDGET_SET_FLAGS(plot, GTK_NO_WINDOW); widget = GTK_WIDGET(plot); gdk_color_black(gtk_widget_get_colormap(widget), &widget->style->black); gdk_color_white(gtk_widget_get_colormap(widget), &widget->style->white); plot->bg_pixmap = NULL; plot->transparent = FALSE; plot->clip_data = FALSE; plot->grids_on_top = FALSE; plot->reflect_x = FALSE; plot->reflect_y = FALSE; plot->magnification = 1.; plot->xmin = 0.; plot->xmax = 1.000000; plot->ymin = 0.; plot->ymax = 1.000000; plot->show_x0 = FALSE; plot->show_y0 = FALSE; plot->right = GTK_PLOT_AXIS(gtk_plot_axis_new(GTK_PLOT_AXIS_Y)); gtk_object_ref(GTK_OBJECT(plot->right)); gtk_object_sink(GTK_OBJECT(plot->right)); gtk_signal_connect(GTK_OBJECT(plot->right), "changed", GTK_SIGNAL_FUNC(axis_changed), plot); plot->left = GTK_PLOT_AXIS(gtk_plot_axis_new(GTK_PLOT_AXIS_Y)); gtk_object_ref(GTK_OBJECT(plot->left)); gtk_object_sink(GTK_OBJECT(plot->left)); gtk_signal_connect(GTK_OBJECT(plot->left), "changed", GTK_SIGNAL_FUNC(axis_changed), plot); plot->top = GTK_PLOT_AXIS(gtk_plot_axis_new(GTK_PLOT_AXIS_X)); gtk_object_ref(GTK_OBJECT(plot->top)); gtk_object_sink(GTK_OBJECT(plot->top)); gtk_signal_connect(GTK_OBJECT(plot->top), "changed", GTK_SIGNAL_FUNC(axis_changed), plot); plot->bottom = GTK_PLOT_AXIS(gtk_plot_axis_new(GTK_PLOT_AXIS_X)); gtk_object_ref(GTK_OBJECT(plot->bottom)); gtk_object_sink(GTK_OBJECT(plot->bottom)); gtk_signal_connect(GTK_OBJECT(plot->bottom), "changed", GTK_SIGNAL_FUNC(axis_changed), plot); plot->left->labels_attr.justification = GTK_JUSTIFY_RIGHT; plot->right->labels_attr.justification = GTK_JUSTIFY_LEFT; plot->right->title.angle = 270; gtk_plot_axis_ticks_recalc(plot->left); gtk_plot_axis_ticks_recalc(plot->right); gtk_plot_axis_ticks_recalc(plot->bottom); gtk_plot_axis_ticks_recalc(plot->top); plot->bottom_align = 0.; plot->top_align = 1.; plot->left_align = 0.; plot->right_align = 1.; plot->x0_line.line_style = GTK_PLOT_LINE_SOLID; plot->x0_line.cap_style = 0; plot->x0_line.join_style = 0; plot->x0_line.line_width = 0; plot->x0_line.color = widget->style->black; plot->y0_line.line_style = GTK_PLOT_LINE_SOLID; plot->y0_line.line_width = 0; plot->y0_line.cap_style = 0; plot->y0_line.join_style = 0; plot->y0_line.color = widget->style->black; plot->legends_x = .6; plot->legends_y = .1; plot->legends_width = 0; plot->legends_height = 0; plot->legends_line_width = 30; plot->legends_border_width = 1; plot->legends_shadow_width = 3; plot->legends_border = GTK_PLOT_BORDER_LINE; plot->show_legends = TRUE; plot->legends_attr.text = NULL; plot->legends_attr.font = g_strdup(DEFAULT_FONT); plot->legends_attr.height = DEFAULT_FONT_HEIGHT; plot->legends_attr.fg = widget->style->black; plot->legends_attr.bg = widget->style->white; plot->legends_attr.transparent = FALSE; plot->legends_attr.border = 0; plot->legends_attr.border_width = 0; plot->legends_attr.shadow_width = 0; plot->background = widget->style->white; plot->xscale = GTK_PLOT_SCALE_LINEAR; plot->yscale = GTK_PLOT_SCALE_LINEAR; plot->data_sets = NULL; plot->text = NULL; gtk_psfont_init(); plot->drawable = NULL; plot->pc = NULL; gtk_plot_set_pc(plot, NULL); } static void gtk_plot_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GtkPlot *plot; plot = GTK_PLOT (object); switch(prop_id){ case ARG_BOTTOM: g_value_set_object(value, GTK_OBJECT(plot->bottom)); break; case ARG_TOP: g_value_set_object(value, GTK_OBJECT(plot->top)); break; case ARG_LEFT: g_value_set_object(value, GTK_OBJECT(plot->left)); break; case ARG_RIGHT: g_value_set_object(value, GTK_OBJECT(plot->right)); break; case ARG_ALLOCATION_X: g_value_set_int(value, plot->internal_allocation.x); break; case ARG_ALLOCATION_Y: g_value_set_int(value, plot->internal_allocation.y); break; case ARG_ALLOCATION_WIDTH: g_value_set_int(value, plot->internal_allocation.width); break; case ARG_ALLOCATION_HEIGHT: g_value_set_int(value, plot->internal_allocation.height); break; case ARG_USE_PIXMAP: g_value_set_boolean(value, plot->use_pixmap); break; case ARG_BG_PIXMAP: g_value_set_pointer(value, plot->bg_pixmap); break; case ARG_TRANSPARENT: g_value_set_boolean(value, plot->transparent); break; case ARG_MAGNIFICATION: g_value_set_double(value, plot->magnification); break; case ARG_CLIP_DATA: g_value_set_boolean(value, plot->clip_data); break; case ARG_BG: g_value_set_pointer(value, &plot->background); break; case ARG_GRIDS_ON_TOP: g_value_set_boolean(value, plot->grids_on_top); break; case ARG_SHOW_X0: g_value_set_boolean(value, plot->show_x0); break; case ARG_SHOW_Y0: g_value_set_boolean(value, plot->show_y0); break; case ARG_X0_LINE: g_value_set_pointer(value, &plot->x0_line); break; case ARG_Y0_LINE: g_value_set_pointer(value, &plot->y0_line); break; case ARG_XMIN: g_value_set_double(value, plot->xmin); break; case ARG_XMAX: g_value_set_double(value, plot->xmax); break; case ARG_YMIN: g_value_set_double(value, plot->ymin); break; case ARG_YMAX: g_value_set_double(value, plot->ymax); break; case ARG_X: g_value_set_double(value, plot->x); break; case ARG_Y: g_value_set_double(value, plot->y); break; case ARG_WIDTH: g_value_set_double(value, plot->width); break; case ARG_HEIGHT: g_value_set_double(value, plot->height); break; case ARG_XSCALE: g_value_set_int(value, plot->xscale); break; case ARG_YSCALE: g_value_set_int(value, plot->yscale); break; case ARG_REFLECT_X: g_value_set_boolean(value, plot->reflect_x); break; case ARG_REFLECT_Y: g_value_set_boolean(value, plot->reflect_y); break; case ARG_BOTTOM_ALIGN: g_value_set_double(value, plot->bottom_align); break; case ARG_TOP_ALIGN: g_value_set_double(value, plot->top_align); break; case ARG_LEFT_ALIGN: g_value_set_double(value, plot->left_align); break; case ARG_RIGHT_ALIGN: g_value_set_double(value, plot->right_align); break; case ARG_LEGENDS_X: g_value_set_double(value, plot->legends_x); break; case ARG_LEGENDS_Y: g_value_set_double(value, plot->legends_y); break; case ARG_LEGENDS_WIDTH: g_value_set_int(value, plot->legends_width); break; case ARG_LEGENDS_HEIGHT: g_value_set_int(value, plot->legends_height); break; case ARG_LEGENDS_BORDER: g_value_set_int(value, plot->legends_border); break; case ARG_LEGENDS_LINE_WIDTH: g_value_set_int(value, plot->legends_line_width); break; case ARG_LEGENDS_BORDER_WIDTH: g_value_set_int(value, plot->legends_border_width); break; case ARG_LEGENDS_SHADOW_WIDTH: g_value_set_int(value, plot->legends_shadow_width); break; case ARG_LEGENDS_SHOW: g_value_set_boolean(value, plot->show_legends); break; case ARG_LEGENDS_ATTR: g_value_set_pointer(value, &plot->legends_attr); break; case ARG_LEGENDS_TRANSPARENT: g_value_set_boolean(value, plot->legends_attr.transparent); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gtk_plot_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GtkPlot *plot; GtkPlotText *text = NULL; plot = GTK_PLOT (object); switch(prop_id){ case ARG_ALLOCATION_X: plot->internal_allocation.x = g_value_get_int(value); break; case ARG_ALLOCATION_Y: plot->internal_allocation.y = g_value_get_int(value); break; case ARG_ALLOCATION_WIDTH: plot->internal_allocation.width = g_value_get_int(value); break; case ARG_ALLOCATION_HEIGHT: plot->internal_allocation.height = g_value_get_int(value); break; case ARG_USE_PIXMAP: plot->use_pixmap = g_value_get_boolean(value); break; case ARG_BG_PIXMAP: if(plot->bg_pixmap) gdk_pixmap_unref(plot->bg_pixmap); plot->bg_pixmap = (GdkPixmap *)g_value_get_pointer(value); if(plot->bg_pixmap) gdk_pixmap_ref(plot->bg_pixmap); break; case ARG_TRANSPARENT: plot->transparent = g_value_get_boolean(value); break; case ARG_MAGNIFICATION: plot->magnification = g_value_get_double(value); break; case ARG_CLIP_DATA: plot->clip_data = g_value_get_boolean(value); break; case ARG_BG: plot->background = *((GdkColor *)g_value_get_pointer(value)); break; case ARG_GRIDS_ON_TOP: plot->grids_on_top = g_value_get_boolean(value); break; case ARG_SHOW_X0: plot->show_x0 = g_value_get_boolean(value); break; case ARG_SHOW_Y0: plot->show_y0 = g_value_get_boolean(value); break; case ARG_X0_LINE: plot->x0_line = *((GtkPlotLine *)g_value_get_pointer(value)); break; case ARG_Y0_LINE: plot->y0_line = *((GtkPlotLine *)g_value_get_pointer(value)); break; case ARG_XMIN: plot->xmin = g_value_get_double(value); break; case ARG_XMAX: plot->xmax = g_value_get_double(value); break; case ARG_YMIN: plot->ymin = g_value_get_double(value); break; case ARG_YMAX: plot->ymax = g_value_get_double(value); break; case ARG_X: plot->x = g_value_get_double(value); break; case ARG_Y: plot->y = g_value_get_double(value); break; case ARG_WIDTH: plot->width = g_value_get_double(value); break; case ARG_HEIGHT: plot->height = g_value_get_double(value); break; case ARG_XSCALE: plot->xscale = g_value_get_int(value); break; case ARG_YSCALE: plot->yscale = g_value_get_int(value); break; case ARG_REFLECT_X: plot->reflect_x = g_value_get_boolean(value); break; case ARG_REFLECT_Y: plot->reflect_y = g_value_get_boolean(value); break; case ARG_BOTTOM_ALIGN: plot->bottom_align = g_value_get_double(value); break; case ARG_TOP_ALIGN: plot->top_align = g_value_get_double(value); break; case ARG_LEFT_ALIGN: plot->left_align = g_value_get_double(value); break; case ARG_RIGHT_ALIGN: plot->right_align = g_value_get_double(value); break; case ARG_LEGENDS_X: plot->legends_x = g_value_get_double(value); break; case ARG_LEGENDS_Y: plot->legends_y = g_value_get_double(value); break; case ARG_LEGENDS_WIDTH: plot->legends_width = g_value_get_int(value); break; case ARG_LEGENDS_HEIGHT: plot->legends_height = g_value_get_int(value); break; case ARG_LEGENDS_BORDER: plot->legends_border = g_value_get_int(value); break; case ARG_LEGENDS_LINE_WIDTH: plot->legends_line_width = g_value_get_int(value); break; case ARG_LEGENDS_BORDER_WIDTH: plot->legends_border_width = g_value_get_int(value); break; case ARG_LEGENDS_SHADOW_WIDTH: plot->legends_shadow_width = g_value_get_int(value); break; case ARG_LEGENDS_SHOW: plot->show_legends = g_value_get_boolean(value); break; case ARG_LEGENDS_ATTR: text = (GtkPlotText *)g_value_get_pointer(value); gtk_plot_legends_set_attributes(plot, text->font, text->height, &text->fg, &text->bg); break; case ARG_LEGENDS_TRANSPARENT: plot->legends_attr.transparent = g_value_get_boolean(value); break; } } void gtk_plot_set_pc(GtkPlot *plot, GtkPlotPC *pc) { GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->set_pc(plot, pc); } static void gtk_plot_real_set_pc(GtkPlot *plot, GtkPlotPC *pc) { if(plot->pc) gtk_object_unref(GTK_OBJECT(plot->pc)); if(!pc){ plot->pc = GTK_PLOT_PC(gtk_plot_gdk_new(GTK_WIDGET(plot))); gtk_object_ref(GTK_OBJECT(plot->pc)); gtk_object_sink(GTK_OBJECT(plot->pc)); } else { plot->pc = pc; gtk_object_ref(GTK_OBJECT(plot->pc)); gtk_object_sink(GTK_OBJECT(plot->pc)); } } static void gtk_plot_axis_init (GtkPlotAxis *axis) { GdkColor black, white; gdk_color_black(gdk_colormap_get_system(), &black); gdk_color_white(gdk_colormap_get_system(), &white); axis->ticks.nmajorticks = 0; axis->ticks.nminorticks = 0; axis->ticks.values = NULL; axis->ticks.set_limits = FALSE; axis->ticks.begin = 0; axis->ticks.end = 0; axis->ticks.step = .100000000; axis->ticks.nminor = 1; axis->ticks.scale = GTK_PLOT_SCALE_LINEAR; axis->ticks.apply_break = FALSE; axis->ticks.break_min = 0.; axis->ticks.break_max = 0.; axis->ticks.break_step = .1; axis->ticks.break_nminor = 1; axis->ticks.break_scale = GTK_PLOT_SCALE_LINEAR; axis->ticks.break_position = 0.5; axis->ticks.min = 0.0; axis->ticks.max = 1.0; axis->major_mask = GTK_PLOT_TICKS_IN; axis->minor_mask = GTK_PLOT_TICKS_IN; axis->ticks_length = 8; axis->ticks_width = 1; axis->labels_offset = 10; axis->orientation = GTK_PLOT_AXIS_X; axis->is_visible = TRUE; axis->custom_labels = FALSE; axis->line.line_style = GTK_PLOT_LINE_SOLID; axis->line.cap_style = 3; axis->line.join_style = 0; axis->line.line_width = 2; axis->line.color = black; axis->labels_attr.text = NULL; axis->labels_attr.font = g_strdup(DEFAULT_FONT); axis->labels_attr.height = DEFAULT_FONT_HEIGHT; axis->labels_attr.fg = black; axis->labels_attr.bg = white; axis->labels_attr.transparent = TRUE; axis->labels_attr.angle = 0; axis->labels_attr.border = 0; axis->labels_attr.border_width = 0; axis->labels_attr.shadow_width = 0; axis->label_mask = GTK_PLOT_LABEL_OUT; axis->label_style = GTK_PLOT_LABEL_FLOAT; axis->label_precision = 1; axis->labels_attr.justification = GTK_JUSTIFY_CENTER; axis->labels_prefix = NULL; axis->labels_suffix = NULL; axis->title.angle = 0; axis->title.justification = GTK_JUSTIFY_CENTER; axis->title.font = g_strdup(DEFAULT_FONT); axis->title.height = DEFAULT_FONT_HEIGHT; axis->title.fg = black; axis->title.bg = white; axis->title.transparent = TRUE; axis->title.text = g_strdup("Title"); axis->title.border = 0; axis->title.border_width = 0; axis->title.shadow_width = 0; axis->title_visible = TRUE; axis->direction.x = 1.; axis->direction.y = 0.; axis->direction.z = 0.; axis->show_major_grid = FALSE; axis->show_minor_grid = FALSE; axis->major_grid.line_style = GTK_PLOT_LINE_SOLID; axis->major_grid.cap_style = 0; axis->major_grid.join_style = 0; axis->major_grid.line_width = 0; axis->major_grid.color = black; axis->minor_grid.line_style = GTK_PLOT_LINE_DOTTED; axis->minor_grid.cap_style = 0; axis->minor_grid.join_style = 0; axis->minor_grid.line_width = 0; axis->minor_grid.color = black; axis->tick_labels = NULL; } static void gtk_plot_axis_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GtkPlotAxis *axis; GtkPlotText *text = NULL; axis = GTK_PLOT_AXIS (object); switch(prop_id){ case ARG_VISIBLE: axis->is_visible = g_value_get_boolean(value); break; case ARG_TITLE: text = (GtkPlotText *)g_value_get_pointer(value); if(axis->title.text) g_free(axis->title.text); if(axis->title.font) g_free(axis->title.font); axis->title = *text; axis->title.text = g_strdup(text->text); axis->title.font = g_strdup(text->font); break; case ARG_TITLE_VISIBLE: axis->title_visible = g_value_get_boolean(value); break; case ARG_ORIENTATION: axis->orientation = g_value_get_enum(value); break; case ARG_LINE: axis->line = *((GtkPlotLine *)g_value_get_pointer(value)); break; case ARG_MAJOR_GRID: axis->major_grid = *((GtkPlotLine *)g_value_get_pointer(value)); break; case ARG_MINOR_GRID: axis->minor_grid = *((GtkPlotLine *)g_value_get_pointer(value)); break; case ARG_MAJOR_MASK: axis->major_mask = g_value_get_int(value); break; case ARG_MINOR_MASK: axis->minor_mask = g_value_get_int(value); break; case ARG_TICKS_LENGTH: axis->ticks_length = g_value_get_int(value); break; case ARG_TICKS_WIDTH: axis->ticks_width = g_value_get_double(value); break; case ARG_CUSTOM_LABELS: axis->custom_labels = g_value_get_boolean(value); break; case ARG_LABELS_OFFSET: axis->labels_offset = g_value_get_int(value); break; case ARG_LABELS_PREFIX: if(axis->labels_prefix) g_free(axis->labels_prefix); axis->labels_prefix = g_strdup(g_value_get_string(value)); break; case ARG_LABELS_SUFFIX: if(axis->labels_suffix) g_free(axis->labels_suffix); axis->labels_suffix = g_strdup(g_value_get_string(value)); break; case ARG_SHOW_MAJOR_GRID: axis->show_major_grid = g_value_get_boolean(value); break; case ARG_SHOW_MINOR_GRID: axis->show_minor_grid = g_value_get_boolean(value); break; case ARG_LABELS_ATTR: text = (GtkPlotText *)g_value_get_pointer(value); if(axis->labels_attr.text) g_free(axis->labels_attr.text); if(axis->labels_attr.font) g_free(axis->labels_attr.font); axis->labels_attr = *text; axis->labels_attr.text = g_strdup(text->text); axis->labels_attr.font = g_strdup(text->font); break; case ARG_LABELS_PRECISION: axis->label_precision = g_value_get_int(value); break; case ARG_LABELS_STYLE: axis->label_style = g_value_get_int(value); break; case ARG_LABELS_MASK: axis->label_mask = g_value_get_int(value); break; case ARG_TICKS_MIN: axis->ticks.min = g_value_get_double(value); break; case ARG_TICKS_MAX: axis->ticks.max = g_value_get_double(value); break; case ARG_SCALE: axis->ticks.scale = g_value_get_int(value); break; case ARG_NMAJORTICKS: axis->ticks.nmajorticks = g_value_get_int(value); break; case ARG_NMINORTICKS: axis->ticks.nminorticks = g_value_get_int(value); break; case ARG_NTICKS: axis->ticks.nticks = g_value_get_int(value); break; case ARG_STEP: axis->ticks.step = g_value_get_double(value); break; case ARG_NMINOR: axis->ticks.nminor = g_value_get_int(value); break; case ARG_APPLY_BREAK: axis->ticks.apply_break = g_value_get_boolean(value); break; case ARG_BREAK_SCALE: axis->ticks.break_scale = g_value_get_int(value); break; case ARG_BREAK_STEP: axis->ticks.break_step = g_value_get_double(value); break; case ARG_BREAK_NMINOR: axis->ticks.break_nminor = g_value_get_int(value); break; case ARG_BREAK_MIN: axis->ticks.break_min = g_value_get_double(value); break; case ARG_BREAK_MAX: axis->ticks.break_max = g_value_get_double(value); break; case ARG_BREAK_POSITION: axis->ticks.break_position = g_value_get_double(value); break; case ARG_SET_LIMITS: axis->ticks.set_limits = g_value_get_boolean(value); break; case ARG_BEGIN: axis->ticks.begin = g_value_get_double(value); break; case ARG_END: axis->ticks.end = g_value_get_double(value); break; case ARG_TICK_LABELS: if(g_value_get_object(value)) gtk_plot_axis_set_tick_labels(axis, GTK_PLOT_ARRAY(g_value_get_object(value))); else gtk_plot_axis_set_tick_labels(axis, NULL); break; } } static void gtk_plot_axis_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GtkPlotAxis *axis; axis = GTK_PLOT_AXIS (object); switch(prop_id){ case ARG_VISIBLE: g_value_set_boolean(value, axis->is_visible); break; case ARG_TITLE: g_value_set_pointer(value, &axis->title); break; case ARG_TITLE_VISIBLE: g_value_set_boolean(value, axis->title_visible); break; case ARG_ORIENTATION: g_value_set_enum(value, axis->orientation); break; case ARG_LINE: g_value_set_pointer(value, &axis->line); break; case ARG_MAJOR_GRID: g_value_set_pointer(value, &axis->major_grid); break; case ARG_MINOR_GRID: g_value_set_pointer(value, &axis->minor_grid); break; case ARG_MAJOR_MASK: g_value_set_int(value, axis->major_mask); break; case ARG_MINOR_MASK: g_value_set_int(value, axis->minor_mask); break; case ARG_TICKS_LENGTH: g_value_set_int(value, axis->ticks_length); break; case ARG_TICKS_WIDTH: g_value_set_double(value, axis->ticks_width); break; case ARG_CUSTOM_LABELS: g_value_set_boolean(value, axis->custom_labels); break; case ARG_LABELS_OFFSET: g_value_set_int(value, axis->labels_offset); break; case ARG_LABELS_PREFIX: g_value_set_string(value, axis->labels_prefix); break; case ARG_LABELS_SUFFIX: g_value_set_string(value, axis->labels_suffix); break; case ARG_SHOW_MAJOR_GRID: g_value_set_boolean(value, axis->show_major_grid); break; case ARG_SHOW_MINOR_GRID: g_value_set_boolean(value, axis->show_minor_grid); break; case ARG_LABELS_ATTR: g_value_set_pointer(value, &axis->labels_attr); break; case ARG_LABELS_PRECISION: g_value_set_int(value, axis->label_precision); break; case ARG_LABELS_STYLE: g_value_set_int(value, axis->label_style); break; case ARG_LABELS_MASK: g_value_set_int(value, axis->label_mask); break; case ARG_TICKS_MIN: g_value_set_double(value, axis->ticks.min); break; case ARG_TICKS_MAX: g_value_set_double(value, axis->ticks.max); break; case ARG_SCALE: g_value_set_int(value, axis->ticks.scale); break; case ARG_NMAJORTICKS: g_value_set_int(value, axis->ticks.nmajorticks); break; case ARG_NMINORTICKS: g_value_set_int(value, axis->ticks.nminorticks); break; case ARG_NTICKS: g_value_set_int(value, axis->ticks.nticks); break; case ARG_STEP: g_value_set_double(value, axis->ticks.step); break; case ARG_NMINOR: g_value_set_int(value, axis->ticks.nminor); break; case ARG_APPLY_BREAK: g_value_set_boolean(value, axis->ticks.apply_break); break; case ARG_BREAK_SCALE: g_value_set_int(value, axis->ticks.break_scale); break; case ARG_BREAK_STEP: g_value_set_double(value, axis->ticks.break_step); break; case ARG_BREAK_NMINOR: g_value_set_int(value, axis->ticks.break_nminor); break; case ARG_BREAK_MIN: g_value_set_double(value, axis->ticks.break_min); break; case ARG_BREAK_MAX: g_value_set_double(value, axis->ticks.break_max); break; case ARG_BREAK_POSITION: g_value_set_double(value, axis->ticks.break_position); break; case ARG_SET_LIMITS: g_value_set_boolean(value, axis->ticks.set_limits); break; case ARG_BEGIN: g_value_set_double(value, axis->ticks.begin); break; case ARG_END: g_value_set_double(value, axis->ticks.end); break; case ARG_TICK_LABELS: if(axis->tick_labels) g_value_set_object(value, GTK_OBJECT(axis->tick_labels)); else g_value_set_object(value, NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gtk_plot_destroy (GtkObject *object) { GtkPlot *plot; GList *list; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_PLOT (object)); plot = GTK_PLOT (object); gtk_object_unref(GTK_OBJECT(plot->top)); gtk_object_unref(GTK_OBJECT(plot->bottom)); gtk_object_unref(GTK_OBJECT(plot->left)); gtk_object_unref(GTK_OBJECT(plot->right)); if(plot->legends_attr.font) g_free (plot->legends_attr.font); plot->legends_attr.font = NULL; list = plot->text; while(list){ GtkPlotText *text; text = (GtkPlotText *) list->data; if(text->text) g_free(text->text); if(text->font) g_free(text->font); g_free(text); plot->text = g_list_remove_link(plot->text, list); g_list_free_1(list); list = plot->text; } plot->text = NULL; list = plot->data_sets; while(list){ gtk_widget_unref(GTK_WIDGET(list->data)); plot->data_sets = g_list_remove_link(plot->data_sets, list); g_list_free_1(list); list = plot->data_sets; } plot->data_sets = NULL; if ( GTK_OBJECT_CLASS (parent_class)->destroy ) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); if(plot->pc) gtk_object_unref(GTK_OBJECT(plot->pc)); plot->pc = NULL; gtk_psfont_unref(); } static void gtk_plot_axis_destroy (GtkObject *object) { GtkPlotAxis *axis; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_PLOT_AXIS (object)); axis = GTK_PLOT_AXIS (object); if(axis->labels_attr.font) g_free (axis->labels_attr.font); if(axis->title.font) g_free (axis->title.font); if(axis->title.text) g_free (axis->title.text); axis->labels_attr.font = NULL; axis->title.font = NULL; axis->title.text = NULL; if(axis->labels_prefix) g_free(axis->labels_prefix); if(axis->labels_suffix) g_free(axis->labels_suffix); if(axis->ticks.values){ g_free (axis->ticks.values); axis->ticks.values = NULL; } if(axis->tick_labels) g_object_unref(G_OBJECT(axis->tick_labels)); axis->tick_labels = NULL; } static void gtk_plot_show_all (GtkWidget *widget) { GtkPlot *plot; GList *list; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_PLOT (widget)); plot = GTK_PLOT (widget); list = plot->data_sets; while(list) { if (GTK_IS_WIDGET (list->data)) gtk_widget_show_all (GTK_WIDGET (list->data)); list = list->next; } gtk_widget_show (widget); } void gtk_plot_paint (GtkPlot *plot) { if(!plot->drawable) return; gtk_plot_pc_init(plot->pc); GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->plot_paint(GTK_WIDGET(plot)); gtk_plot_pc_leave(plot->pc); } static void gtk_plot_real_paint (GtkWidget *widget) { GtkPlot *plot; GtkPlotText *child_text; GtkStyle *style; GdkPixmap *pixmap; GList *dataset; GList *text; gint width, height; gint xoffset, yoffset ; plot = GTK_PLOT(widget); xoffset = plot->internal_allocation.x; yoffset = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; style = gtk_widget_get_style(widget); pixmap = plot->drawable; gtk_plot_pc_gsave(plot->pc); gtk_plot_pc_set_color(plot->pc, &plot->background); if(!gtk_plot_is_transparent(plot) && !plot->bg_pixmap) gtk_plot_pc_draw_rectangle (plot->pc, TRUE, xoffset, yoffset, width , height); if(!gtk_plot_is_transparent(plot) && plot->bg_pixmap){ gint pwidth, pheight; gdouble scale_x, scale_y; gdk_window_get_size(plot->bg_pixmap, &pwidth, &pheight); scale_x = (gdouble)width / (gdouble)pwidth; scale_y = (gdouble)height / (gdouble)pheight; gtk_plot_pc_draw_pixmap (plot->pc, plot->bg_pixmap, NULL, 0, 0, xoffset, yoffset, pwidth , pheight, scale_x, scale_y); } /* draw frame to guide the eyes*/ /* gtk_plot_pc_draw_rectangle (plot->pc, FALSE, xoffset, yoffset, width , height); */ /* draw the ticks & grid lines */ gtk_plot_axis_ticks_recalc(plot->left); gtk_plot_axis_ticks_recalc(plot->right); gtk_plot_axis_ticks_recalc(plot->bottom); gtk_plot_axis_ticks_recalc(plot->top); if(!plot->grids_on_top) gtk_plot_draw_grids(plot); else { dataset = plot->data_sets; while(dataset) { if(GTK_IS_PLOT_DATA(dataset->data)) gtk_plot_data_paint(GTK_PLOT_DATA(dataset->data)); dataset = dataset->next; } } if(plot->bottom->is_visible) { GtkPlotVector tick; gboolean reflect; tick.x = 0.; tick.y = -1.; plot->bottom->origin.x = plot->xmin; plot->bottom->origin.y = plot->ymin*(1.0-plot->bottom_align) + plot->ymax*plot->bottom_align; reflect = plot->reflect_y; plot->reflect_y = FALSE; gtk_plot_draw_axis(plot, plot->bottom, tick); gtk_plot_draw_labels(plot, plot->bottom, tick); plot->reflect_y = reflect; } if(plot->top->is_visible) { GtkPlotVector tick; gboolean reflect; tick.x = 0.; tick.y = 1.; plot->top->origin.x = plot->xmin; plot->top->origin.y = plot->ymin*(1.0-plot->top_align) + plot->ymax*plot->top_align; reflect = plot->reflect_y; plot->reflect_y = FALSE; gtk_plot_draw_axis(plot, plot->top, tick); gtk_plot_draw_labels(plot, plot->top, tick); plot->reflect_y = reflect; } if(plot->left->is_visible) { GtkPlotVector tick; gboolean reflect; tick.x = 1.; tick.y = 0.; plot->left->origin.x = plot->xmin*(1.0-plot->left_align) + plot->xmax*plot->left_align; plot->left->origin.y = plot->ymin; reflect = plot->reflect_x; plot->reflect_x = FALSE; gtk_plot_draw_axis(plot, plot->left, tick); gtk_plot_draw_labels(plot, plot->left, tick); plot->reflect_x = reflect; } if(plot->right->is_visible) { GtkPlotVector tick; gboolean reflect; tick.x = -1.; tick.y = 0.; plot->right->origin.x = plot->xmin*(1.0-plot->right_align) + plot->xmax*plot->right_align; plot->right->origin.y = plot->ymin; reflect = plot->reflect_x; plot->reflect_x = FALSE; gtk_plot_draw_axis(plot, plot->right, tick); gtk_plot_draw_labels(plot, plot->right, tick); plot->reflect_x = reflect; } if(plot->grids_on_top) gtk_plot_draw_grids(plot); else { dataset = plot->data_sets; while(dataset) { if(GTK_IS_PLOT_DATA(dataset->data)) gtk_plot_data_paint(GTK_PLOT_DATA(dataset->data)); dataset = dataset->next; } } text = plot->text; while(text) { child_text = (GtkPlotText *) text->data; gtk_plot_draw_text(plot, *child_text); text = text->next; } GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->draw_legends(GTK_WIDGET(plot)); gtk_plot_pc_grestore(plot->pc); } void gtk_plot_refresh (GtkPlot *plot, GdkRectangle *drawing_area) { GtkWidget *widget; GdkPixmap *pixmap; GdkRectangle area; widget = GTK_WIDGET(plot); if(!GTK_WIDGET_VISIBLE(widget)) return; if(!plot->drawable) return; pixmap = plot->drawable; if(drawing_area == NULL){ area.x = widget->allocation.x; area.y = widget->allocation.y; area.width = widget->allocation.width; area.height = widget->allocation.height; } else { area = *drawing_area; } gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], pixmap, area.x, area.y, widget->allocation.x, widget->allocation.y, widget->allocation.width, widget->allocation.height); } static void gtk_plot_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkPlot *plot; plot = GTK_PLOT(widget); requisition->width = DEFAULT_WIDTH; requisition->height = DEFAULT_HEIGHT; } static void gtk_plot_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkPlot *plot; plot = GTK_PLOT(widget); widget->allocation = *allocation; plot->internal_allocation.x = GTK_WIDGET(plot)->allocation.x + roundint(plot->x * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.y = GTK_WIDGET(plot)->allocation.y + roundint(plot->y * GTK_WIDGET(plot)->allocation.height); plot->internal_allocation.width = roundint(plot->width * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.height = roundint(plot->height * GTK_WIDGET(plot)->allocation.height); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], FALSE); } GtkObject* gtk_plot_axis_new (GtkPlotOrientation orientation) { GtkObject *axis; axis = gtk_type_new (gtk_plot_axis_get_type ()); gtk_plot_axis_construct(GTK_PLOT_AXIS(axis), orientation); return GTK_OBJECT (axis); } void gtk_plot_axis_construct(GtkPlotAxis *axis, GtkPlotOrientation orientation) { axis->orientation = orientation; axis->title.border = GTK_PLOT_BORDER_NONE; axis->title.border_width = 0; axis->title.border_space = 2; axis->title.shadow_width = 3; axis->ticks.values = NULL; axis->ticks_transform = gtk_plot_ticks_transform; axis->ticks_inverse = gtk_plot_ticks_inverse; axis->ticks_recalc = gtk_plot_ticks_recalc; axis->ticks_autoscale = gtk_plot_ticks_autoscale; axis->parse_label = gtk_plot_parse_label; switch(orientation){ case GTK_PLOT_AXIS_X: axis->direction.x = 1.0; axis->direction.y = 0.0; axis->direction.z = 0.0; g_free(axis->title.text); axis->title.text = g_strdup("X Title"); axis->title.angle = 0; break; case GTK_PLOT_AXIS_Y: axis->direction.x = 0.0; axis->direction.y = -1.0; axis->direction.z = 0.0; g_free(axis->title.text); axis->title.text = g_strdup("Y Title"); axis->title.angle = 90; break; case GTK_PLOT_AXIS_Z: axis->direction.x = 0.0; axis->direction.y = 0.0; axis->direction.z = 1.0; g_free(axis->title.text); axis->title.text = g_strdup("Z Title"); axis->title.angle = 0; break; } } GtkWidget* gtk_plot_new (GdkDrawable *drawable) { GtkPlot *plot; plot = gtk_type_new (gtk_plot_get_type ()); gtk_plot_construct(GTK_PLOT(plot), drawable); return GTK_WIDGET (plot); } void gtk_plot_construct(GtkPlot *plot, GdkDrawable *drawable) { gtk_plot_set_drawable(plot, drawable); plot->x = .15; plot->y = .1; plot->width = .6; plot->height = .6; plot->internal_allocation.x = GTK_WIDGET(plot)->allocation.x + roundint(plot->x * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.y = GTK_WIDGET(plot)->allocation.y + roundint(plot->y * GTK_WIDGET(plot)->allocation.height); plot->internal_allocation.width = roundint(plot->width * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.height = roundint(plot->height * GTK_WIDGET(plot)->allocation.height); plot->left->title.x = plot->x; plot->left->title.y = plot->y + plot->height / 2.; plot->right->title.x = plot->x + plot->width; plot->right->title.y = plot->y + plot->height / 2.; plot->top->title.x = plot->x + plot->width / 2.; plot->top->title.y = plot->y; plot->bottom->title.x = plot->x + plot->width / 2.; plot->bottom->title.y = plot->y + plot->height; plot->left->title.x -= 45. / (gdouble)DEFAULT_WIDTH; plot->right->title.x += 45. / (gdouble)DEFAULT_WIDTH; plot->top->title.y -= 35. / (gdouble)DEFAULT_HEIGHT; plot->bottom->title.y += 35. / (gdouble)DEFAULT_HEIGHT; } GtkWidget* gtk_plot_new_with_size (GdkDrawable *drawable, gdouble width, gdouble height) { GtkWidget *plot; plot = gtk_type_new (gtk_plot_get_type ()); gtk_plot_construct_with_size(GTK_PLOT(plot), drawable, width, height); return(plot); } void gtk_plot_construct_with_size (GtkPlot *plot, GdkDrawable *drawable, gdouble width, gdouble height) { gtk_plot_construct(plot, drawable); gtk_plot_resize (GTK_PLOT(plot), width, height); } void gtk_plot_set_drawable (GtkPlot *plot, GdkDrawable *drawable) { GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->set_drawable(plot, drawable); } static void gtk_plot_real_set_drawable (GtkPlot *plot, GdkDrawable *drawable) { plot->drawable = drawable; if(GTK_IS_PLOT_GDK(plot->pc)) gtk_plot_gdk_set_drawable(GTK_PLOT_GDK(plot->pc), drawable); } GdkDrawable * gtk_plot_get_drawable (GtkPlot *plot) { return(plot->drawable); } void gtk_plot_set_background_pixmap (GtkPlot *plot, GdkPixmap *pixmap) { if(plot->bg_pixmap) gdk_pixmap_unref(plot->bg_pixmap); plot->bg_pixmap = pixmap; if(pixmap) gdk_pixmap_ref(pixmap); } void gtk_plot_set_transparent (GtkPlot *plot, gboolean transparent) { plot->transparent = transparent; } gboolean gtk_plot_is_transparent (GtkPlot *plot) { return(plot->transparent); } static void gtk_plot_draw_grids(GtkPlot *plot) { GtkWidget *widget; GdkRectangle clip_area; gdouble width, height; gdouble xp, yp; gdouble x1, y1, x2, y2; gdouble xx, yy; gdouble x_tick; gint ntick; widget = GTK_WIDGET(plot); xp = plot->internal_allocation.x; yp = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; clip_area.x = xp; clip_area.y = yp; clip_area.width = width; clip_area.height = height; gtk_plot_pc_clip(plot->pc, &clip_area); if(plot->show_x0) { if(plot->xmin <= 0. && plot->xmax >= 0.) { gtk_plot_get_pixel(plot, 0., plot->ymin, &x1, &y1); gtk_plot_get_pixel(plot, 0., plot->ymax, &x2, &y2); gtk_plot_draw_line(plot, plot->x0_line, x1, y1, x2, y2); } } if(plot->show_y0) { if(plot->ymin <= 0. && plot->ymax >= 0.) { gtk_plot_get_pixel(plot, plot->xmin, 0., &x1, &y1); gtk_plot_get_pixel(plot, plot->xmax, 0., &x2, &y2); gtk_plot_draw_line(plot, plot->y0_line, x1, y1, x2, y2); } } if(plot->bottom->show_minor_grid) { for(ntick = 0; ntick < plot->bottom->ticks.nticks; ntick++){ if(!plot->bottom->ticks.values[ntick].minor) continue; if(plot->bottom->ticks.values[ntick].value >= plot->bottom->ticks.min){ x_tick = plot->bottom->ticks.values[ntick].value; xx = x_tick; yy = plot->ymin; gtk_plot_get_pixel(plot, xx, yy, &x1, &y1); xx = x_tick; yy = plot->ymax; gtk_plot_get_pixel(plot, xx, yy, &x2, &y2); gtk_plot_draw_line(plot, plot->bottom->minor_grid, x1, y1, x2, y2); } } } if(plot->bottom->show_major_grid) { for(ntick = 0; ntick < plot->bottom->ticks.nticks; ntick++){ if(plot->bottom->ticks.values[ntick].minor) continue; if(plot->bottom->ticks.values[ntick].value >= plot->bottom->ticks.min){ x_tick = plot->bottom->ticks.values[ntick].value; xx = x_tick; yy = plot->ymin; gtk_plot_get_pixel(plot, xx, yy, &x1, &y1); xx = x_tick; yy = plot->ymax; gtk_plot_get_pixel(plot, xx, yy, &x2, &y2); gtk_plot_draw_line(plot, plot->bottom->major_grid, x1, y1, x2, y2); } } } if(plot->left->show_minor_grid) { for(ntick = 0; ntick < plot->left->ticks.nticks; ntick++){ if(!plot->left->ticks.values[ntick].minor) continue; if(plot->left->ticks.values[ntick].value >= plot->left->ticks.min){ x_tick = plot->left->ticks.values[ntick].value; xx = plot->xmin; yy = x_tick; gtk_plot_get_pixel(plot, xx, yy, &x1, &y1); xx = plot->xmax; yy = x_tick; gtk_plot_get_pixel(plot, xx, yy, &x2, &y2); gtk_plot_draw_line(plot, plot->left->minor_grid, x1, y1, x2, y2); } } } if(plot->left->show_major_grid) { for(ntick = 0; ntick < plot->left->ticks.nticks; ntick++){ if(plot->left->ticks.values[ntick].minor) continue; if(plot->left->ticks.values[ntick].value >= plot->left->ticks.min){ x_tick = plot->left->ticks.values[ntick].value; xx = plot->xmin; yy = x_tick; gtk_plot_get_pixel(plot, xx, yy, &x1, &y1); xx = plot->xmax; yy = x_tick; gtk_plot_get_pixel(plot, xx, yy, &x2, &y2); gtk_plot_draw_line(plot, plot->left->major_grid, x1, y1, x2, y2); } } } gtk_plot_pc_clip(plot->pc, NULL); } static void gtk_plot_draw_axis(GtkPlot *plot, GtkPlotAxis *axis, GtkPlotVector tick_direction) { GtkWidget *widget; gdouble x_tick; gdouble xp, yp, width, height; gint ntick; gdouble m = plot->magnification; gdouble x1, y1, x2, y2; gdouble px, py; gdouble xx, yy; widget = GTK_WIDGET(plot); xp = plot->internal_allocation.x; yp = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; gtk_plot_get_pixel(plot, axis->origin.x, axis->origin.y, &x1, &y1); if(axis->ticks.apply_break){ gdouble l = m * axis->ticks_length; gtk_plot_get_pixel(plot, axis->origin.x+axis->direction.x*(axis->ticks.break_min-axis->ticks.min), axis->origin.y-axis->direction.y*(axis->ticks.break_min-axis->ticks.min), &x2, &y2); gtk_plot_draw_line(plot, axis->line, x1, y1, x2, y2); x1 = x2 + axis->direction.x * 6 * m; y1 = y2 + axis->direction.y * 6 * m; gtk_plot_draw_line(plot, axis->line, x1 - axis->direction.y * l + axis->direction.x * l/2, y1 - axis->direction.x * l + axis->direction.y * l/2, x1 + axis->direction.y * l - axis->direction.x * l/2, y1 + axis->direction.x * l - axis->direction.y * l/2); gtk_plot_draw_line(plot, axis->line, x2 - axis->direction.y * l + axis->direction.x * l/2, y2 - axis->direction.x * l + axis->direction.y * l/2, x2 + axis->direction.y * l - axis->direction.x * l/2, y2 + axis->direction.x * l - axis->direction.y * l/2); gtk_plot_get_pixel(plot, axis->origin.x+axis->direction.x*(axis->ticks.max-axis->ticks.min), axis->origin.y-axis->direction.y*(axis->ticks.max-axis->ticks.min), &x2, &y2); gtk_plot_draw_line(plot, axis->line, x1, y1, x2, y2); } else { gtk_plot_get_pixel(plot, axis->origin.x+axis->direction.x*(axis->ticks.max-axis->ticks.min), axis->origin.y-axis->direction.y*(axis->ticks.max-axis->ticks.min), &x2, &y2); gtk_plot_draw_line(plot, axis->line, x1, y1, x2, y2); } gtk_plot_pc_set_lineattr(plot->pc, axis->ticks_width, 0, 1, 0); for(ntick = 0; ntick < axis->ticks.nticks; ntick++){ GtkPlotTick tick = axis->ticks.values[ntick]; x_tick = tick.value; xx = -axis->direction.y * axis->origin.x + x_tick * axis->direction.x; yy = axis->direction.x * axis->origin.y - x_tick * axis->direction.y; gtk_plot_get_pixel(plot, xx, yy, &px, &py); if(!tick.minor && x_tick >= axis->ticks.min){ if(axis->major_mask & GTK_PLOT_TICKS_IN) gtk_plot_pc_draw_line(plot->pc, px, py, px + tick_direction.x * m * axis->ticks_length, py + tick_direction.y * m * axis->ticks_length); if(axis->major_mask & GTK_PLOT_TICKS_OUT) gtk_plot_pc_draw_line(plot->pc, px, py, px - tick_direction.x * m * axis->ticks_length, py - tick_direction.y * m * axis->ticks_length); } if(tick.minor && x_tick >= axis->ticks.min){ if(axis->minor_mask & GTK_PLOT_TICKS_IN) gtk_plot_pc_draw_line(plot->pc, px, py, px + tick_direction.x * m * axis->ticks_length/2., py + tick_direction.y * m * axis->ticks_length/2.); if(axis->minor_mask & GTK_PLOT_TICKS_OUT) gtk_plot_pc_draw_line(plot->pc, px, py, px - tick_direction.x * m * axis->ticks_length/2., py - tick_direction.y * m * axis->ticks_length/2.); } } } static void gtk_plot_draw_labels(GtkPlot *plot, GtkPlotAxis *axis, GtkPlotVector tick_direction) { GtkWidget *widget; GtkPlotText title, tick; gchar label[LABEL_MAX_LENGTH], new_label[LABEL_MAX_LENGTH]; gdouble x_tick; gdouble xx, yy; gint text_height; gdouble xp, yp, width, height; gint ntick; gdouble m = plot->magnification; gboolean veto = FALSE; gdouble px, py; gdouble y; gint n = 0; widget = GTK_WIDGET(plot); xp = plot->internal_allocation.x; yp = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; gtk_plot_pc_set_color (plot->pc, &axis->labels_attr.fg); text_height = roundint(axis->labels_attr.height*m); y = 0.0; switch(axis->labels_attr.angle){ case 0: y += text_height / 2.; break; case 90: break; case 180: y -= text_height / 2.; break; case 270: break; } tick = axis->labels_attr; for(ntick = 0; ntick < axis->ticks.nticks; ntick++){ if(axis->ticks.values[ntick].minor) continue; x_tick = axis->ticks.values[ntick].value; xx = -axis->direction.y * axis->origin.x + x_tick * axis->direction.x; yy = axis->direction.x * axis->origin.y - x_tick * axis->direction.y; gtk_plot_get_pixel(plot, xx, yy, &px, &py); if(x_tick >= axis->ticks.min-1.e-9){ if(!axis->custom_labels){ gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label); } else { veto = FALSE; _gtkextra_signal_emit(GTK_OBJECT(axis), axis_signals[TICK_LABEL], &x_tick, label, &veto); if(!veto) { if(axis->tick_labels){ gchar **array; array = gtk_plot_array_get_string(axis->tick_labels); if(array && n < gtk_plot_array_get_size(axis->tick_labels) && array[n]) { g_snprintf(label, 100, "%s", array[n++]); } else { g_snprintf(label, 100, " "); } } else { gtk_plot_axis_parse_label(axis, x_tick, axis->label_precision, axis->label_style, label); } } } if(axis->labels_prefix){ g_snprintf(new_label, 100, "%s%s", axis->labels_prefix, label); g_snprintf(label, 100, "%s", new_label); } if(axis->labels_suffix){ g_snprintf(new_label, 100, "%s%s", label, axis->labels_suffix); g_snprintf(label, 100, "%s", new_label); } tick.text = label; tick.x = px; tick.y = py + y; if(axis->label_mask & GTK_PLOT_LABEL_IN){ tick.x = tick.x + tick_direction.x*roundint(axis->labels_offset * m); tick.y = tick.y + tick_direction.y*roundint(axis->labels_offset * m); tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width; tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height; gtk_plot_draw_text(plot, tick); } if(axis->label_mask & GTK_PLOT_LABEL_OUT){ tick.x = tick.x - tick_direction.x*roundint(axis->labels_offset * m); tick.y = tick.y - tick_direction.y*roundint(axis->labels_offset * m); tick.x = (gdouble)tick.x / (gdouble)widget->allocation.width; tick.y = (gdouble)tick.y / (gdouble)widget->allocation.height; gtk_plot_draw_text(plot, tick); } } } if(axis->title_visible && axis->title.text) { title = axis->title; gtk_plot_draw_text(plot, title); } } void gtk_plot_draw_line(GtkPlot *plot, GtkPlotLine line, gdouble x1, gdouble y1, gdouble x2, gdouble y2) { if(line.line_style == GTK_PLOT_LINE_NONE) return; gtk_plot_set_line_attributes(plot, line); gtk_plot_pc_draw_line(plot->pc, x1, y1, x2, y2); } void gtk_plot_set_line_attributes(GtkPlot *plot, GtkPlotLine line) { gdouble dot[] = {2., 3.}; gdouble dash[] = {6., 4.}; gdouble dot_dash[] = {6., 4., 2., 4.}; gdouble dot_dot_dash[] = {6., 4., 2., 4., 2., 4.}; gdouble dot_dash_dash[] = {6., 4., 6., 4., 2., 4.}; gtk_plot_pc_set_color (plot->pc, &line.color); switch(line.line_style){ case GTK_PLOT_LINE_SOLID: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, 0, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, 0, 0); break; case GTK_PLOT_LINE_DOTTED: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, GDK_LINE_ON_OFF_DASH, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, dot, 2); break; case GTK_PLOT_LINE_DASHED: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, GDK_LINE_ON_OFF_DASH, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, dash, 2); break; case GTK_PLOT_LINE_DOT_DASH: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, GDK_LINE_ON_OFF_DASH, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, dot_dash, 4); break; case GTK_PLOT_LINE_DOT_DOT_DASH: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, GDK_LINE_ON_OFF_DASH, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, dot_dot_dash, 6); break; case GTK_PLOT_LINE_DOT_DASH_DASH: gtk_plot_pc_set_lineattr(plot->pc, line.line_width, GDK_LINE_ON_OFF_DASH, line.cap_style, line.join_style); gtk_plot_pc_set_dash(plot->pc, 0, dot_dash_dash, 6); break; case GTK_PLOT_LINE_NONE: default: break; } } static void gtk_plot_draw_legends (GtkWidget *widget) { GtkPlot *plot; GList *datasets; GtkPlotData *dataset; GtkAllocation legend_area; gint x, y; gint height; gint lwidth, lheight; gdouble m; plot = GTK_PLOT(widget); if(!plot->show_legends) return; m = plot->magnification; gtk_plot_pc_gsave(plot->pc); /* first draw the white rectangle for the background */ legend_area = gtk_plot_legends_get_allocation(plot); if(!plot->legends_attr.transparent){ gtk_plot_pc_set_color(plot->pc, &plot->legends_attr.bg); gtk_plot_pc_draw_rectangle(plot->pc, TRUE, legend_area.x, legend_area.y, legend_area.width, legend_area.height); } plot->legends_width = legend_area.width; plot->legends_height = legend_area.height; /* now draw the legends */ height = roundint(4 * m); y = legend_area.y + height; x = legend_area.x + roundint(4 * m); datasets = plot->data_sets; while(datasets) { dataset = GTK_PLOT_DATA(datasets->data); if(GTK_WIDGET_VISIBLE(GTK_WIDGET(dataset)) && dataset->show_legend) { GTK_PLOT_DATA_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(dataset)))->get_legend_size(dataset, &lwidth, &lheight); GTK_PLOT_DATA_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(dataset)))->draw_legend(dataset, x, y); y += lheight; height += lheight; } datasets=datasets->next; } gtk_plot_pc_set_lineattr(plot->pc, plot->legends_border_width, 0, 0, 0); gtk_plot_pc_set_color(plot->pc, &plot->legends_attr.fg); gtk_plot_pc_set_dash(plot->pc, 0, 0, 0); if(plot->legends_border != GTK_PLOT_BORDER_NONE) { gtk_plot_pc_draw_rectangle(plot->pc, FALSE, legend_area.x, legend_area.y, legend_area.width, legend_area.height); } gtk_plot_pc_set_lineattr(plot->pc, 0, 0, 0, 0); if(plot->legends_border == GTK_PLOT_BORDER_SHADOW) { gtk_plot_pc_draw_rectangle(plot->pc, TRUE, legend_area.x + roundint(plot->legends_shadow_width * m), legend_area.y + legend_area.height, legend_area.width, roundint(plot->legends_shadow_width * m)); gtk_plot_pc_draw_rectangle(plot->pc, TRUE, legend_area.x + legend_area.width, legend_area.y + roundint(plot->legends_shadow_width * m), roundint(plot->legends_shadow_width * m), legend_area.height); } datasets = plot->data_sets; while(datasets) { dataset = GTK_PLOT_DATA(datasets->data); if(GTK_WIDGET_VISIBLE(GTK_WIDGET(dataset)) && dataset->show_gradient) { GTK_PLOT_DATA_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(dataset)))->draw_gradient(dataset); } datasets=datasets->next; } gtk_plot_pc_grestore(plot->pc); } void gtk_plot_axis_ticks_recalc (GtkPlotAxis *axis) { axis->ticks_recalc(axis); } void gtk_plot_axis_ticks_autoscale (GtkPlotAxis *axis, gdouble xmin, gdouble xmax, gint *precision) { axis->ticks_autoscale(axis, xmin, xmax, precision); } gdouble gtk_plot_axis_ticks_transform (GtkPlotAxis *axis, gdouble y) { return (axis->ticks_transform(axis, y)); } gdouble gtk_plot_axis_ticks_inverse (GtkPlotAxis *axis, gdouble x) { return (axis->ticks_inverse(axis, x)); } void gtk_plot_axis_parse_label (GtkPlotAxis *axis, gdouble val, gint precision, gint style, gchar *label) { axis->parse_label(axis, val, precision, style, label); } gdouble gtk_plot_ticks_transform(GtkPlotAxis *axis, gdouble x) { gdouble position = 0; GtkPlotTicks *_ticks = &axis->ticks; GtkPlotTicks ticks = *_ticks; switch( ticks.scale ){ case GTK_PLOT_SCALE_LOG10: if( x <= 0.0 || ticks.min <= 0.0 || ticks.max <= 0.0 ) return 0; if(ticks.apply_break){ if(x <= ticks.break_min) { position = log(x/ticks.min) / log(ticks.break_min / ticks.min); position *= ticks.break_position; } else { if(x <= ticks.break_max) return ticks.break_position; if(ticks.break_scale == GTK_PLOT_SCALE_LOG10) position = log(x/ticks.break_max) / log(ticks.max/ticks.break_max); else position = (x - ticks.break_max) / (ticks.max - ticks.break_max); position = ticks.break_position + (1 - ticks.break_position) * position; } } else { position = log(x/ticks.min) / log(ticks.max/ticks.min); } break; case GTK_PLOT_SCALE_LINEAR: default: if(ticks.apply_break){ if(x <= ticks.break_min) { position = (x - ticks.min) / (ticks.break_min - ticks.min); position *= ticks.break_position; } else { if(x <= ticks.break_max) return ticks.break_position; if(ticks.break_scale == GTK_PLOT_SCALE_LOG10) position = log(x/ticks.break_max) / log(ticks.max/ticks.break_max); else position = (x - ticks.break_max) / (ticks.max - ticks.break_max); position = ticks.break_position + (1 - ticks.break_position) * position; } } else { position = (x - ticks.min) / (ticks.max - ticks.min); } break; } return(position); } gdouble gtk_plot_ticks_inverse(GtkPlotAxis *axis, gdouble x) { gdouble point = 0; GtkPlotTicks *_ticks = &axis->ticks; GtkPlotTicks ticks = *_ticks; switch(ticks.scale){ case GTK_PLOT_SCALE_LINEAR: if(ticks.apply_break){ if(x <= ticks.break_position){ point = ticks.min + x*(ticks.break_min-ticks.min)/ticks.break_position; } else { point = ticks.break_max + (x - ticks.break_position)*(ticks.max-ticks.break_max)/(1-ticks.break_position); } } else { point = ticks.min + x*(ticks.max-ticks.min); } break; case GTK_PLOT_SCALE_LOG10: /* FIXME */ if(ticks.apply_break){ if(x <= ticks.break_position){ point = ticks.min + x*(ticks.break_min-ticks.min)/ticks.break_position; } else { point = ticks.break_max + (x - ticks.break_position)*(ticks.max-ticks.break_max)/(1-ticks.break_position); } } else { point = ticks.min + x*(ticks.max-ticks.min); } break; } return point; } inline gint roundint (gdouble x) { return (x+.50999999471); } void gtk_plot_parse_label(GtkPlotAxis *axis, gdouble val, gint precision, gint style, gchar *label) { gdouble auxval; gint intspace = 0; gint power; gfloat v; GtkPlotScale scale = axis->ticks.scale; auxval = fabs(val); power = 0.0; if(auxval != 0.0) power = (gint)log10(auxval); v = val / pow(10.0, power); if(fabs(v) < 1.0 && v != 0.0){ v *= 10.0; power -= 1; } if(fabs(v) >= 10.0){ v /= 10.0; power += 1; } /* if(power < -12){ power = 0; v = 0.0f; } */ if(auxval > 1) intspace = (gint)log10(auxval); switch(style){ case GTK_PLOT_LABEL_EXP: sprintf (label, "%*.*E", 1, precision, val); break; case GTK_PLOT_LABEL_POW: if(scale == GTK_PLOT_SCALE_LOG10) sprintf (label, "10\\S%i", power); else sprintf (label, "%*.*f\\4x\\N10\\S%i", 1, precision, v, power); break; case GTK_PLOT_LABEL_FLOAT: default: if(fabs(val) < pow(10,-precision)) val = 0.0f; sprintf (label, "%*.*f", intspace, precision, val); } } void gtk_plot_draw_text(GtkPlot *plot, GtkPlotText text) { gint x, y; if(!text.text) return; if(strlen(text.text) == 0) return; if(plot->drawable == NULL) return; x = text.x * GTK_WIDGET(plot)->allocation.width; y = text.y * GTK_WIDGET(plot)->allocation.height; gtk_plot_paint_text(plot, x, y, text); } static void gtk_plot_paint_text(GtkPlot *plot, gint x, gint y, GtkPlotText text) { gdouble m = plot->magnification; if(!text.text) return; if(strlen(text.text) == 0) return; if(plot->drawable == NULL) return; gtk_plot_pc_draw_string(plot->pc, x, y, text.angle, &text.fg, &text.bg, text.transparent, text.border, roundint(m * text.border_space), roundint(m * text.border_width), roundint(m * text.shadow_width), text.font, roundint(m * text.height), text.justification, text.text); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_text_get_size(const gchar *text, gint angle, const gchar* text_font, gint text_height, gint *width, gint *height, gint *ascent, gint *descent) { PangoFontDescription *font, *latin_font; GtkPSFont *psfont, *base_psfont, *latin_psfont; gint old_width, old_height; gboolean italic, bold; gint fontsize; gint x, y, y0; GList *family; gint numf; gchar insert_char; gchar num[4]; const gchar *aux = text; const gchar *lastchar = text; const gchar *wtext = text; const gchar *xaux = text; PangoFontMetrics *metrics = NULL; PangoLayout *layout = NULL; PangoRectangle rect; PangoContext *context; gint i = 0; if(!text || strlen(text) == 0) return; layout = pango_layout_new(context = gdk_pango_context_get_for_screen(gdk_screen_get_default())); g_object_unref(G_OBJECT(context)); pango_layout_set_text(layout, text, -1); gtk_psfont_get_families(&family, &numf); base_psfont = psfont = gtk_psfont_get_by_name(text_font); font = gtk_psfont_get_font_description(psfont, text_height); pango_layout_get_extents(layout, NULL, &rect); old_width = PANGO_PIXELS(rect.width); old_height = PANGO_PIXELS(rect.height); italic = psfont->italic; bold = psfont->bold; fontsize = text_height; if (psfont->i18n_latinfamily) { latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold); latin_font = gtk_psfont_get_font_description(latin_psfont, text_height); } else { latin_font = NULL; latin_psfont = NULL; } metrics = pango_context_get_metrics(pango_layout_get_context(layout), font, gtk_get_default_language()); y0 = y = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); y0 = y = 0; x = 0; old_width = 0; *ascent = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); *descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); aux = wtext = text; while(aux && *aux != '\0' && *aux != '\n'){ if(*aux == '\\'){ aux = g_utf8_next_char(aux); switch(*aux){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '9': psfont = gtk_psfont_get_by_family((gchar *)g_list_nth_data(family, *aux-'0'), italic, bold); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); /* The 0th-9th data of family is supposed to be a built-in Latin font defined in font_data[], so this code is not needed unless the font_data[] is modified. if (psfont->i18n_latinfamily) { latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold); gdk_font_unref(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } */ aux = g_utf8_next_char(aux); break; case '8': case 'g': psfont = gtk_psfont_get_by_family("Symbol", italic, bold); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); /* The code commented out above might be needed here if the font_data[] is modified. */ aux = g_utf8_next_char(aux); break; case 'B': bold = TRUE; psfont = gtk_psfont_get_by_family(psfont->family, italic, bold); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); if (psfont->i18n_latinfamily) { latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold); if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case 'i': italic = TRUE; psfont = gtk_psfont_get_by_family(psfont->family, italic, bold); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); if (psfont->i18n_latinfamily) { latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold); if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case 'S': case '^': fontsize = (int)((gdouble)fontsize * 0.6 + 0.5); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); pango_font_metrics_unref(metrics); metrics = pango_context_get_metrics(pango_layout_get_context(layout), font, gtk_get_default_language()); y += PANGO_PIXELS(pango_font_metrics_get_ascent(metrics)); if (psfont->i18n_latinfamily) { if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case 's': case '_': fontsize = (int)((gdouble)fontsize * 0.6 + 0.5); pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); pango_font_metrics_unref(metrics); metrics = pango_context_get_metrics(pango_layout_get_context(layout), font, gtk_get_default_language()); y -= PANGO_PIXELS(pango_font_metrics_get_descent(metrics)); if (psfont->i18n_latinfamily) { if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case '+': fontsize += 3; pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); if (psfont->i18n_latinfamily){ if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case '-': fontsize -= 3; pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, fontsize); if (psfont->i18n_latinfamily){ if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case 'N': psfont = base_psfont; pango_font_description_free(font); font = gtk_psfont_get_font_description(psfont, text_height); y = y0; italic = psfont->italic; bold = psfont->bold; fontsize = text_height; if (psfont->i18n_latinfamily) { latin_psfont = gtk_psfont_get_by_family(psfont->i18n_latinfamily, italic, bold); if(latin_font) pango_font_description_free(latin_font); latin_font = gtk_psfont_get_font_description(latin_psfont, fontsize); } aux = g_utf8_next_char(aux); break; case 'b': if(lastchar){ const gchar *aux2 = lastchar; gint i = g_utf8_next_char(lastchar) != ++aux2 ? 2 : 1; pango_layout_set_text(layout, lastchar, i); pango_layout_get_extents(layout, NULL, &rect); x -= PANGO_PIXELS(rect.width); if (lastchar == wtext) lastchar = NULL; else lastchar--; } else { pango_layout_set_text(layout, "X", 1); pango_layout_get_extents(layout, NULL, &rect); x -= PANGO_PIXELS(rect.width); } aux = g_utf8_next_char(aux); break; case 'x': xaux = aux + 1; for (i=0; i<3; i++){ if (xaux[i] >= '0' && xaux[i] <= '9') num[i] = xaux[i]; else break; } if (i < 3){ aux++; break; } num[3] = '\0'; insert_char = (gchar)atoi(num); /* \xNNN is always outputted with latin fonts. */ pango_layout_set_font_description(layout, font); pango_layout_set_text(layout, aux, 1); pango_layout_get_extents(layout, NULL, &rect); x += PANGO_PIXELS(rect.width); aux += 4; lastchar = aux - 1; break; default: if(aux && *aux != '\0' && *aux !='\n'){ const gchar *aux2 = aux; gint i = g_utf8_next_char(aux) != ++aux2 ? 2 : 1; pango_layout_set_font_description(layout, font); pango_layout_set_text(layout, aux, i); pango_layout_get_extents(layout, NULL, &rect); x += PANGO_PIXELS(rect.width); lastchar = aux; aux = g_utf8_next_char(aux); } break; } } else { if(aux && *aux != '\0' && *aux != '\n'){ const gchar *aux2 = aux; gint i = g_utf8_next_char(aux) != ++aux2 ? 2 : 1; pango_layout_set_font_description(layout, font); pango_layout_set_text(layout, aux, i); pango_layout_get_extents(layout, NULL, &rect); x += PANGO_PIXELS(rect.width); lastchar = aux; aux = g_utf8_next_char(aux); if(x > old_width) old_width = x; } } } pango_font_description_free(font); if(latin_font) pango_font_description_free(latin_font); pango_font_metrics_unref(metrics); g_object_unref(G_OBJECT(layout)); old_height = *ascent + *descent; *width = old_width; *height = old_height; if(angle == 90 || angle == 270) { *width = old_height; *height = old_width; } } void gtk_plot_text_get_area(const gchar *text, gint angle, GtkJustification just, const gchar *font, gint font_height, gint *x, gint *y, gint *width, gint *height) { gint ascent, descent; if(text == NULL) return; gtk_plot_text_get_size(text, angle, font, font_height, width, height, &ascent, &descent); *x = 0; *y = 0; switch(just){ case GTK_JUSTIFY_LEFT: switch(angle){ case 0: *y -= ascent; break; case 90: *y -= *height; *x -= ascent; break; case 180: *x -= *width; *y -= descent; break; case 270: *x -= descent; break; } break; case GTK_JUSTIFY_RIGHT: switch(angle){ case 0: *x -= *width; *y -= ascent; break; case 90: *x -= ascent; break; case 180: *y -= descent; break; case 270: *y -= *height; *x -= descent; break; } break; case GTK_JUSTIFY_CENTER: default: switch(angle){ case 0: *x -= *width / 2.; *y -= ascent; break; case 90: *x -= ascent; *y -= *height / 2.; break; case 180: *x -= *width / 2.; *y -= descent; break; case 270: *x -= descent; *y -= *height / 2.; break; } } } /****************************************** * gtk_plot_clip_data * gtk_plot_get_position * gtk_plot_get_size * gtk_plot_get_internal_allocation * gtk_plot_set_background * gtk_plot_move * gtk_plot_resize * gtk_plot_move_resize * gtk_plot_get_pixel * gtk_plot_get_point * gtk_plot_real_get_pixel * gtk_plot_set_xscale * gtk_plot_set_yscale * gtk_plot_draw_text ******************************************/ void gtk_plot_clip_data (GtkPlot *plot, gboolean clip) { plot->clip_data = clip; } void gtk_plot_get_position (GtkPlot *plot, gdouble *x, gdouble *y) { *x = plot->x; *y = plot->y; } void gtk_plot_get_size (GtkPlot *plot, gdouble *width, gdouble *height) { *width = plot->width; *height = plot->height; } GtkAllocation gtk_plot_get_internal_allocation (GtkPlot *plot) { return(plot->internal_allocation); } void gtk_plot_set_background(GtkPlot *plot, const GdkColor *color) { plot->background = *color; gtk_plot_paint(plot); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_move (GtkPlot *plot, gdouble x, gdouble y) { gboolean veto = TRUE; _gtkextra_signal_emit (GTK_OBJECT(plot), plot_signals[MOVED], &x, &y, &veto); if(!veto) return; plot->left->title.x += (x - plot->x); plot->left->title.y += (y - plot->y); plot->right->title.x += (x - plot->x); plot->right->title.y += (y - plot->y); plot->top->title.x += (x - plot->x); plot->top->title.y += (y - plot->y); plot->bottom->title.x += (x - plot->x); plot->bottom->title.y += (y - plot->y); plot->x = x; plot->y = y; plot->internal_allocation.x = GTK_WIDGET(plot)->allocation.x + roundint(plot->x * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.y = GTK_WIDGET(plot)->allocation.y + roundint(plot->y * GTK_WIDGET(plot)->allocation.height); plot->internal_allocation.width = roundint(plot->width * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.height = roundint(plot->height * GTK_WIDGET(plot)->allocation.height); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_resize (GtkPlot *plot, gdouble width, gdouble height) { gboolean veto = TRUE; _gtkextra_signal_emit (GTK_OBJECT(plot), plot_signals[RESIZED], &width, &height, &veto); if(!veto) return; plot->left->title.y += (height - plot->height) / 2.; plot->right->title.x += (width - plot->width); plot->right->title.y += (height - plot->height) / 2.; plot->top->title.x += (width - plot->width) / 2.; plot->bottom->title.x += (width - plot->width) / 2.; plot->bottom->title.y += (height - plot->height); plot->width = width; plot->height = height; plot->internal_allocation.x = GTK_WIDGET(plot)->allocation.x + roundint(plot->x * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.y = GTK_WIDGET(plot)->allocation.y + roundint(plot->y * GTK_WIDGET(plot)->allocation.height); plot->internal_allocation.width = roundint(plot->width * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.height = roundint(plot->height * GTK_WIDGET(plot)->allocation.height); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], FALSE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_set_magnification (GtkPlot *plot, gdouble magnification) { GtkWidget *widget; widget = GTK_WIDGET(plot); plot->magnification = magnification; plot->internal_allocation.x = GTK_WIDGET(plot)->allocation.x + roundint(plot->x * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.y = GTK_WIDGET(plot)->allocation.y + roundint(plot->y * GTK_WIDGET(plot)->allocation.height); plot->internal_allocation.width = roundint(plot->width * GTK_WIDGET(plot)->allocation.width); plot->internal_allocation.height = roundint(plot->height * GTK_WIDGET(plot)->allocation.height); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], FALSE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_move_resize (GtkPlot *plot, gdouble x, gdouble y, gdouble width, gdouble height) { gtk_plot_move(plot, x, y); gtk_plot_resize(plot, width, height); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_get_pixel(GtkPlot *plot, gdouble xx, gdouble yy, gdouble *x, gdouble *y) { GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->get_pixel (GTK_WIDGET(plot), xx, yy, x, y); } void gtk_plot_get_point(GtkPlot *plot, gint x, gint y, gdouble *xx, gdouble *yy) { GTK_PLOT_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(plot)))->get_point (GTK_WIDGET(plot), x, y, xx, yy); } static void gtk_plot_real_get_pixel(GtkWidget *widget, gdouble xx, gdouble yy , gdouble *x, gdouble *y) { GtkPlot *plot; gint xp, yp, width, height; plot = GTK_PLOT(widget); xp = plot->internal_allocation.x; yp = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; *y = gtk_plot_ticks_transform(plot->left, yy)*height; *x = gtk_plot_ticks_transform(plot->bottom, xx)*width; if(!plot->reflect_x) *x = widget->allocation.x + xp + *x; else *x = widget->allocation.x + xp + width - *x; if(!plot->reflect_y) *y = widget->allocation.y + yp + height - *y; else *y = widget->allocation.y + yp + *y; } static void gtk_plot_real_get_point(GtkWidget *widget, gint x, gint y, gdouble *px, gdouble *py) { GtkPlot *plot; gdouble xx, yy; gdouble xp, yp, width, height; gdouble rx, ry; plot = GTK_PLOT(widget); xp = plot->internal_allocation.x; yp = plot->internal_allocation.y; width = plot->internal_allocation.width; height = plot->internal_allocation.height; if(!plot->reflect_x) xx = x - widget->allocation.x - xp; else xx = width - (x - widget->allocation.x - xp); if(!plot->reflect_y) yy = widget->allocation.y + yp + height - y; else yy = y - widget->allocation.y - yp; rx = plot->bottom->ticks.max - plot->bottom->ticks.min; ry = plot->left->ticks.max - plot->left->ticks.min; *px = gtk_plot_axis_ticks_inverse(plot->bottom, xx / width); *py = gtk_plot_axis_ticks_inverse(plot->left, yy / height); } void gtk_plot_set_xrange (GtkPlot *plot, gdouble xmin, gdouble xmax) { if(xmin > xmax) return; plot->xmin = xmin; plot->xmax = xmax; plot->bottom->ticks.min = xmin; plot->bottom->ticks.max = xmax; plot->top->ticks.min = xmin; plot->top->ticks.max = xmax; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], TRUE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_set_yrange (GtkPlot *plot, gdouble ymin, gdouble ymax) { if(ymin > ymax) return; plot->ymin = ymin; plot->ymax = ymax; plot->left->ticks.min = ymin; plot->left->ticks.max = ymax; plot->right->ticks.min = ymin; plot->right->ticks.max = ymax; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], TRUE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_set_range (GtkPlot *plot, gdouble xmin, gdouble xmax, gdouble ymin, gdouble ymax) { if(xmin > xmax || ymin > ymax) return; plot->xmin = xmin; plot->xmax = xmax; plot->ymin = ymin; plot->ymax = ymax; plot->bottom->ticks.min = xmin; plot->bottom->ticks.max = xmax; plot->top->ticks.min = xmin; plot->top->ticks.max = xmax; plot->left->ticks.min = ymin; plot->left->ticks.max = ymax; plot->right->ticks.min = ymin; plot->right->ticks.max = ymax; gtk_plot_axis_ticks_recalc(plot->bottom); gtk_plot_axis_ticks_recalc(plot->top); gtk_plot_axis_ticks_recalc(plot->left); gtk_plot_axis_ticks_recalc(plot->right); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], TRUE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_ticks_autoscale(GtkPlotAxis *axis, gdouble xmin, gdouble xmax, gint *precision) { GtkPlotTicks *ticks = &axis->ticks; if(xmin > xmax) return; if(ticks->scale == GTK_PLOT_SCALE_LOG10) { ticks->step = 1; ticks->nminor = 8; xmin = floor(log10(fabs(xmin))) - 1.; *precision = MAX(xmin + 1, 1); xmin = pow(10., xmin); xmax = ceil(log10(fabs(xmax))); xmax = pow(10., xmax); if(xmin == 0.0) xmin = xmax/1000.; } else { gdouble amin, amax; gdouble pmin, pmax; gdouble dx; gdouble pstep; amin = xmin; amax = xmax; if(xmin == xmax){ if(xmin == 0.0){ amax = xmax = 0.1; }else{ pstep = floor(log10(fabs(xmin))); dx = xmin/pow(10., pstep) * pow(10., pstep); amax = xmax = xmin + 2 * dx; amin = xmin = xmin - 2 * dx; } } dx = (xmax - xmin)/8.; xmin -= dx; xmax += dx; if(xmin == 0.0) xmin -= dx; if(xmax == 0.0) xmax += dx; pmin = floor(log10(fabs(xmin))) - 1.; pmax = floor(log10(fabs(xmax))) - 1.; xmin = floor(xmin/pow(10., pmin)) * pow(10., pmin); xmax = floor(xmax/pow(10., pmax)) * pow(10., pmax); pstep = floor(log10(fabs(dx))); dx = ticks->step = floor(dx/pow(10., pstep)) * pow(10., pstep); while(xmin >= amin) xmin -= dx; while(xmax <= amax) xmax += dx; dx = floor((xmax - xmin)/ticks->step); while(dx > 10.){ ticks->step *= 2; dx = floor((xmax - xmin)/ticks->step); } xmin = floor(xmin/ticks->step) * ticks->step; xmax = ceil(xmax/ticks->step) * ticks->step; ticks->step = ticks->step; *precision = MAX(floor(fabs(pstep)), 0); } ticks->min = xmin; ticks->max = xmax; gtk_plot_axis_ticks_recalc(axis); axis->label_precision = *precision; } void gtk_plot_autoscale(GtkPlot *plot) { GtkPlotData *dataset; GList *list; gdouble xmin, xmax; gdouble ymin, ymax; gint n; gboolean change = FALSE; gint labels_precision; if(!plot->data_sets) return; xmin = plot->xmax; xmax = plot->xmin; ymin = plot->ymax; ymax = plot->ymin; list = plot->data_sets; while(list){ dataset = GTK_PLOT_DATA(list->data); if(!dataset->is_function){ for(n = 0; n < dataset->num_points; n++){ gdouble fx, fy, fz, fa; gdouble fdx, fdy, fdz, fda; gchar *label; gboolean error; gtk_plot_data_get_point(dataset, n, &fx, &fy, &fz, &fa, &fdx, &fdy, &fdz, &fda, &label, &error); if(fx < xmin) xmin = fx; if(fy < ymin) ymin = fy; if(fx > xmax) xmax = fx; if(fy > ymax) ymax = fy; change = TRUE; } } list = list->next; } if(!change) return; gtk_plot_axis_ticks_autoscale(plot->bottom, xmin, xmax, &labels_precision); gtk_plot_axis_ticks_autoscale(plot->left, ymin, ymax, &labels_precision); gtk_plot_axis_ticks_autoscale(plot->top, xmin, xmax, &labels_precision); gtk_plot_axis_ticks_autoscale(plot->right, ymin, ymax, &labels_precision); plot->xmin = plot->bottom->ticks.min; plot->xmax = plot->bottom->ticks.max; plot->ymin = plot->left->ticks.min; plot->ymax = plot->left->ticks.max; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], TRUE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_get_xrange (GtkPlot *plot, gdouble *xmin, gdouble *xmax) { *xmax = plot->xmax; *xmin = plot->xmin; } void gtk_plot_get_yrange (GtkPlot *plot, gdouble *ymin, gdouble *ymax) { *ymax = plot->ymax; *ymin = plot->ymin; } void gtk_plot_set_xscale (GtkPlot *plot, GtkPlotScale scale_type) { plot->xscale = scale_type; plot->bottom->ticks.scale = scale_type; plot->top->ticks.scale = scale_type; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], FALSE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_set_yscale (GtkPlot *plot, GtkPlotScale scale_type) { plot->yscale = scale_type; plot->left->ticks.scale = scale_type; plot->right->ticks.scale = scale_type; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[UPDATE], FALSE); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } GtkPlotScale gtk_plot_get_xscale (GtkPlot *plot) { return plot->bottom->ticks.scale; } GtkPlotScale gtk_plot_get_yscale (GtkPlot *plot) { return plot->left->ticks.scale; } void gtk_plot_reflect_x (GtkPlot *plot, gboolean reflect) { plot->reflect_x = reflect; } void gtk_plot_reflect_y (GtkPlot *plot, gboolean reflect) { plot->reflect_y = reflect; } gboolean gtk_plot_is_x_reflected (GtkPlot *plot) { return plot->reflect_x; } gboolean gtk_plot_is_y_reflected (GtkPlot *plot) { return plot->reflect_y; } GtkPlotText * gtk_plot_put_text (GtkPlot *plot, gdouble x, gdouble y, const gchar *font, gint height, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, GtkJustification justification, const gchar *text) { GtkWidget *widget; GtkPlotText *text_attr; GdkRectangle area; widget = GTK_WIDGET(plot); text_attr = g_new0(GtkPlotText, 1); area.x = widget->allocation.x; area.y = widget->allocation.y; text_attr->x = x; text_attr->y = y; text_attr->angle = angle; text_attr->justification = justification; text_attr->fg = widget->style->black; text_attr->bg = widget->style->white; text_attr->transparent = transparent; text_attr->border = 0; text_attr->border_space = 2; text_attr->border_width = 0; text_attr->shadow_width = 3; if(!font) { text_attr->font = g_strdup(DEFAULT_FONT); text_attr->height = DEFAULT_FONT_HEIGHT; } else { text_attr->font = g_strdup(font); text_attr->height = height; } text_attr->text = NULL; if(text) text_attr->text = g_strdup(text); if(fg != NULL) text_attr->fg = *fg; if(bg != NULL) text_attr->bg = *bg; plot->text = g_list_append(plot->text, text_attr); gtk_plot_draw_text(plot, *text_attr); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); return text_attr; } void gtk_plot_text_set_attributes (GtkPlotText *text_attr, const gchar *font, gint height, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, GtkJustification justification, const gchar *text) { text_attr->angle = angle; gdk_color_black(gdk_colormap_get_system(), &text_attr->fg); gdk_color_white(gdk_colormap_get_system(), &text_attr->bg); text_attr->justification = justification; text_attr->transparent = transparent; if(!font) { text_attr->font = g_strdup(DEFAULT_FONT); text_attr->height = DEFAULT_FONT_HEIGHT; } else { text_attr->font = g_strdup(font); text_attr->height = height; } if(text_attr->text) g_free(text_attr->text); text_attr->text = NULL; if(text) text_attr->text = g_strdup(text); if(bg != NULL) text_attr->bg = *bg; if(fg != NULL) text_attr->fg = *fg; } void gtk_plot_text_set_border (GtkPlotText *text, GtkPlotBorderStyle border, gint border_space, gint border_width, gint shadow_width) { if(!text) return; text->border = border; text->border_width = border_width; text->border_space = border_space; text->shadow_width = shadow_width; } /******************************************/ void gtk_plot_set_ticks (GtkPlot *plot, GtkPlotOrientation orientation, gdouble major_step, gint nminor) { if(orientation == GTK_PLOT_AXIS_X){ gtk_plot_axis_set_ticks(plot->top, major_step, nminor); gtk_plot_axis_set_ticks(plot->bottom, major_step, nminor); } else { gtk_plot_axis_set_ticks(plot->left, major_step, nminor); gtk_plot_axis_set_ticks(plot->right, major_step, nminor); } } void gtk_plot_set_major_ticks (GtkPlot *plot, GtkPlotOrientation orientation, gdouble major_step) { if(orientation == GTK_PLOT_AXIS_X){ gtk_plot_axis_set_major_ticks(plot->top, major_step); gtk_plot_axis_set_major_ticks(plot->bottom, major_step); } else { gtk_plot_axis_set_major_ticks(plot->left, major_step); gtk_plot_axis_set_major_ticks(plot->right, major_step); } } void gtk_plot_set_minor_ticks (GtkPlot *plot, GtkPlotOrientation orientation, gint nminor) { if(orientation == GTK_PLOT_AXIS_X){ gtk_plot_axis_set_minor_ticks(plot->top, nminor); gtk_plot_axis_set_minor_ticks(plot->bottom, nminor); } else { gtk_plot_axis_set_minor_ticks(plot->left, nminor); gtk_plot_axis_set_minor_ticks(plot->right, nminor); } } void gtk_plot_set_ticks_limits (GtkPlot *plot, GtkPlotOrientation orientation, gdouble begin, gdouble end) { if(orientation == GTK_PLOT_AXIS_X){ gtk_plot_axis_set_ticks_limits(plot->top, begin, end); gtk_plot_axis_set_ticks_limits(plot->bottom, begin, end); } else { gtk_plot_axis_set_ticks_limits(plot->left, begin, end); gtk_plot_axis_set_ticks_limits(plot->right, begin, end); } } void gtk_plot_unset_ticks_limits (GtkPlot *plot, GtkPlotOrientation orientation) { if(orientation == GTK_PLOT_AXIS_X){ gtk_plot_axis_unset_ticks_limits(plot->top); gtk_plot_axis_unset_ticks_limits(plot->bottom); } else { gtk_plot_axis_unset_ticks_limits(plot->left); gtk_plot_axis_unset_ticks_limits(plot->right); } } void gtk_plot_set_break (GtkPlot *plot, GtkPlotOrientation orient, gdouble min, gdouble max, gdouble step_after, gint nminor_after, GtkPlotScale scale_after, gdouble pos) { if(orient == GTK_PLOT_AXIS_X){ gtk_plot_axis_set_break(plot->top, min, max, step_after, nminor_after, scale_after, pos); gtk_plot_axis_set_break(plot->bottom, min, max, step_after, nminor_after, scale_after, pos); } else { gtk_plot_axis_set_break(plot->left, min, max, step_after, nminor_after, scale_after, pos); gtk_plot_axis_set_break(plot->right, min, max, step_after, nminor_after, scale_after, pos); } } void gtk_plot_remove_break (GtkPlot *plot, GtkPlotOrientation orient) { if(orient == GTK_PLOT_AXIS_X){ gtk_plot_axis_remove_break(plot->top); gtk_plot_axis_remove_break(plot->bottom); } else { gtk_plot_axis_remove_break(plot->left); gtk_plot_axis_remove_break(plot->right); } } /****************************************** * gtk_plot_get_axis * gtk_plot_axis_set_visible * gtk_plot_axis_visible * gtk_plot_axis_set_title * gtk_plot_axis_show_title * gtk_plot_axis_hide_title * gtk_plot_axis_move_title * gtk_plot_axis_justify_title * gtk_plot_axis_show_labels * gtk_plot_axis_set_attributes * gtk_plot_axis_get_attributes * gtk_plot_axis_set_ticks * gtk_plot_axis_set_major_ticks * gtk_plot_axis_set_minor_ticks * gtk_plot_axis_set_ticks_length * gtk_plot_axis_show_ticks * gtk_plot_axis_set_ticks_limits * gtk_plot_axis_unset_ticks_limits * gtk_plot_axis_labels_set_attributes * gtk_plot_axis_labels_set_numbers ******************************************/ GtkPlotAxis * gtk_plot_get_axis (GtkPlot *plot, GtkPlotAxisPos axis) { GtkPlotAxis *aux = NULL; switch(axis){ case GTK_PLOT_AXIS_LEFT: aux = plot->left; break; case GTK_PLOT_AXIS_RIGHT: aux = plot->right; break; case GTK_PLOT_AXIS_TOP: aux = plot->top; break; case GTK_PLOT_AXIS_BOTTOM: aux = plot->bottom; break; } return aux; } void gtk_plot_axis_set_visible (GtkPlotAxis *axis, gboolean visible) { GtkPlotAxis *aux = axis; aux->is_visible = visible; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } gboolean gtk_plot_axis_visible (GtkPlotAxis *axis) { GtkPlotAxis *aux = axis; return aux->is_visible; } void gtk_plot_axis_set_title (GtkPlotAxis *axis, const gchar *title) { GtkPlotAxis *aux = axis; if(aux->title.text) g_free(aux->title.text); aux->title.text = g_strdup(title); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_show_title (GtkPlotAxis *axis) { GtkPlotAxis *aux = axis; aux->title_visible = TRUE; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_hide_title (GtkPlotAxis *axis) { GtkPlotAxis *aux = axis; aux->title_visible = FALSE; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_move_title (GtkPlotAxis *axis, gint angle, gdouble x, gdouble y) { GtkPlotAxis *aux = axis; aux->title.angle = angle; aux->title.x = x; aux->title.y = y; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_justify_title (GtkPlotAxis *axis, GtkJustification justification) { GtkPlotAxis *aux = axis; aux->title.justification = justification; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_attributes (GtkPlotAxis *axis, gfloat width, const GdkColor *color) { GtkPlotAxis *aux = axis; aux->line.line_width = width; aux->line.color = *color; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_get_attributes (GtkPlotAxis *axis, gfloat *width, GdkColor *color) { GtkPlotAxis *aux = axis; *width = aux->line.line_width; *color = aux->line.color; } void gtk_plot_axis_set_ticks (GtkPlotAxis *axis, gdouble major_step, gint nminor) { axis->ticks.step = major_step; axis->ticks.nminor = nminor; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_major_ticks (GtkPlotAxis *axis, gdouble major_step) { axis->ticks.step = major_step; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_minor_ticks (GtkPlotAxis *axis, gint nminor) { axis->ticks.nminor = nminor; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_ticks_length (GtkPlotAxis *axis, gint length) { GtkPlotAxis *aux = axis; aux->ticks_length = length; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_ticks_width (GtkPlotAxis *axis, gfloat width) { GtkPlotAxis *aux = axis; aux->ticks_width = width; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_show_ticks (GtkPlotAxis *axis, gint major_mask, gint minor_mask) { GtkPlotAxis *aux = axis; aux->major_mask = major_mask; aux->minor_mask = minor_mask; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_ticks_limits (GtkPlotAxis *axis, gdouble begin, gdouble end) { if(end < begin) return; axis->ticks.begin = begin; axis->ticks.end = end; axis->ticks.set_limits = TRUE; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_unset_ticks_limits (GtkPlotAxis *axis) { axis->ticks.set_limits = FALSE; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_tick_labels (GtkPlotAxis *axis, GtkPlotArray *labels) { if(axis->tick_labels) g_object_unref(G_OBJECT(axis->tick_labels)); axis->tick_labels = labels; if(labels){ if(labels->name) g_free(labels->name); labels->name = g_strdup("tick_labels"); g_object_ref(G_OBJECT(labels)); } } void gtk_plot_axis_set_break (GtkPlotAxis *axis, gdouble min, gdouble max, gdouble step_after, gint nminor_after, GtkPlotScale scale_after, gdouble pos) { axis->ticks.break_min = min; axis->ticks.break_max = max; axis->ticks.apply_break = TRUE; axis->ticks.break_step = step_after; axis->ticks.break_nminor = nminor_after; axis->ticks.break_position = pos; axis->ticks.break_scale = scale_after; gtk_plot_axis_ticks_recalc(axis); gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_remove_break (GtkPlotAxis *axis) { axis->ticks.apply_break = FALSE; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_show_labels (GtkPlotAxis *axis, gint mask) { GtkPlotAxis *aux = axis; aux->label_mask = mask; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_title_set_attributes (GtkPlotAxis *axis, const gchar *font, gint height, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, GtkJustification justification) { GtkPlotAxis *aux = axis; if(!font){ /* Use previous font */ /* aux->title.font = g_strdup(DEFAULT_FONT); aux->title.height = DEFAULT_FONT_HEIGHT; */ } else { if(aux->title.font) g_free(aux->title.font); aux->title.font = g_strdup(font); aux->title.height = height; } gdk_color_black(gdk_colormap_get_system(), &axis->title.fg); gdk_color_white(gdk_colormap_get_system(), &axis->title.bg); if(fg) aux->title.fg = *fg; if(bg) aux->title.bg = *bg; aux->title.angle = angle; aux->title.transparent = transparent; aux->title.justification = justification; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_labels_offset (GtkPlotAxis *axis, gint offset) { GtkPlotAxis *aux = axis; aux->labels_offset = offset; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } gint gtk_plot_axis_get_labels_offset (GtkPlotAxis *axis) { GtkPlotAxis *aux = axis; return(aux->labels_offset); } void gtk_plot_axis_set_labels_attributes (GtkPlotAxis *axis, const gchar *font, gint height, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, GtkJustification justification) { GtkPlotAxis *aux = axis; if(!font){ /* Use previous font */ /* aux->labels_attr.font = g_strdup(DEFAULT_FONT); aux->labels_attr.height = DEFAULT_FONT_HEIGHT; */ } else { if(aux->labels_attr.font) g_free(aux->labels_attr.font); aux->labels_attr.font = g_strdup(font); aux->labels_attr.height = height; } aux->labels_attr.angle = angle; gdk_color_black(gdk_colormap_get_system(), &axis->labels_attr.fg); gdk_color_white(gdk_colormap_get_system(), &axis->labels_attr.bg); if(fg) aux->labels_attr.fg = *fg; if(bg) aux->labels_attr.bg = *bg; aux->labels_attr.transparent = transparent; aux->labels_attr.justification = justification; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_labels_style (GtkPlotAxis *axis, GtkPlotLabelStyle style, gint precision) { GtkPlotAxis *aux = axis; aux->label_style = style; aux->label_precision = precision; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_use_custom_tick_labels (GtkPlotAxis *axis, gboolean use) { axis->custom_labels = use; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_labels_prefix (GtkPlotAxis *axis, const gchar *text) { if(axis->labels_prefix) g_free(axis->labels_prefix); if(text) axis->labels_prefix = g_strdup(text); else axis->labels_prefix = NULL; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } void gtk_plot_axis_set_labels_suffix (GtkPlotAxis *axis, const gchar *text) { if(axis->labels_suffix) g_free(axis->labels_suffix); if(text) axis->labels_suffix = g_strdup(text); else axis->labels_suffix = NULL; gtk_signal_emit (GTK_OBJECT(axis), axis_signals[AXIS_CHANGED]); } gchar * gtk_plot_axis_get_labels_prefix (GtkPlotAxis *axis) { return (axis->labels_prefix); } gchar * gtk_plot_axis_get_labels_suffix (GtkPlotAxis *axis) { return (axis->labels_suffix); } /****************************************** * gtk_plot_x0line_set_attributes * gtk_plot_y0line_set_attributes * gtk_plot_major_vgrid_set_attributes * gtk_plot_minor_vgrid_set_attributes * gtk_plot_major_hgrid_set_attributes * gtk_plot_minor_hgrid_set_attributes ******************************************/ void gtk_plot_x0_set_visible(GtkPlot *plot, gboolean visible) { plot->show_x0 = visible; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } gboolean gtk_plot_x0_visible(GtkPlot *plot) { return plot->show_x0; } void gtk_plot_y0_set_visible(GtkPlot *plot, gboolean visible) { plot->show_y0 = visible; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } gboolean gtk_plot_y0_visible(GtkPlot *plot) { return plot->show_y0; } void gtk_plot_grids_set_on_top(GtkPlot *plot, gboolean on_top) { plot->grids_on_top = on_top; } gboolean gtk_plot_grids_on_top(GtkPlot *plot) { return(plot->grids_on_top); } void gtk_plot_grids_set_visible(GtkPlot *plot, gboolean vmajor, gboolean vminor, gboolean hmajor, gboolean hminor) { plot->bottom->show_major_grid = vmajor; plot->bottom->show_minor_grid = vminor; plot->left->show_major_grid = hmajor; plot->left->show_minor_grid = hminor; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_grids_visible(GtkPlot *plot, gboolean *vmajor, gboolean *vminor, gboolean *hmajor, gboolean *hminor) { *vmajor = plot->bottom->show_major_grid; *vminor = plot->bottom->show_minor_grid; *hmajor = plot->left->show_major_grid; *hminor = plot->left->show_minor_grid; } void gtk_plot_x0line_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->x0_line.line_style = line_style; plot->x0_line.line_width = width; if(color) plot->x0_line.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_y0line_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->y0_line.line_style = line_style; plot->y0_line.line_width = width; if(color) plot->y0_line.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_major_vgrid_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->bottom->major_grid.line_style = line_style; plot->bottom->major_grid.line_width = width; if(color) plot->bottom->major_grid.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_minor_vgrid_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->bottom->minor_grid.line_style = line_style; plot->bottom->minor_grid.line_width = width; if(color) plot->bottom->minor_grid.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_major_hgrid_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->left->major_grid.line_style = line_style; plot->left->major_grid.line_width = width; if(color) plot->left->major_grid.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_minor_hgrid_set_attributes(GtkPlot *plot, GtkPlotLineStyle line_style, gfloat width, const GdkColor *color) { plot->left->minor_grid.line_style = line_style; plot->left->minor_grid.line_width = width; if(color) plot->left->minor_grid.color = *color; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } /****************************************** * gtk_plot_show_legends * gtk_plot_hide_legends * gtk_plot_show_legends_border * gtk_plot_hide_legends_border * gtk_plot_legends_move * gtk_plot_legends_get_position * gtk_plot_legends_get_allocation * gtk_plot_set_legends_attributes ******************************************/ void gtk_plot_show_legends(GtkPlot *plot) { plot->show_legends = TRUE; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_hide_legends(GtkPlot *plot) { plot->show_legends = FALSE; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_set_legends_border(GtkPlot *plot, GtkPlotBorderStyle legends_border, gint shadow_width) { plot->legends_border = legends_border; plot->legends_shadow_width = shadow_width; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_legends_move(GtkPlot *plot, gdouble x, gdouble y) { plot->legends_x = x; plot->legends_y = y; gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_legends_get_position(GtkPlot *plot, gdouble *x, gdouble *y) { *x = plot->legends_x; *y = plot->legends_y; } GtkAllocation gtk_plot_legends_get_allocation(GtkPlot *plot) { GtkAllocation allocation; GtkWidget *widget; GList *datasets; gdouble x, y, width, height; gdouble m; widget = GTK_WIDGET(plot); m = plot->magnification; x = widget->allocation.x + plot->x * widget->allocation.width + plot->legends_x * plot->width * widget->allocation.width; y = widget->allocation.y + plot->y * widget->allocation.height + plot->legends_y * plot->height * widget->allocation.height; width = 24 * m; height = 8 * m; datasets = g_list_first(plot->data_sets); while(datasets) { GtkPlotData *dataset; gint lwidth, lheight; dataset = GTK_PLOT_DATA(datasets->data); if(GTK_WIDGET_VISIBLE(GTK_WIDGET(dataset)) && dataset->show_legend) { GTK_PLOT_DATA_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(dataset)))->get_legend_size(dataset, &lwidth, &lheight); width = MAX(width, lwidth); height += lheight; } datasets = datasets->next; } allocation.x = roundint(x); allocation.y = roundint(y); allocation.width = roundint(width); allocation.height = roundint(height); return(allocation); } void gtk_plot_legends_set_attributes(GtkPlot *plot, const gchar *font, gint height, const GdkColor *foreground, const GdkColor *background) { g_free(plot->legends_attr.font); if(!font) { plot->legends_attr.font = g_strdup(DEFAULT_FONT); plot->legends_attr.height = DEFAULT_FONT_HEIGHT; } else { plot->legends_attr.font = g_strdup(font); plot->legends_attr.height = height; } plot->legends_attr.fg = GTK_WIDGET(plot)->style->black; plot->legends_attr.bg = GTK_WIDGET(plot)->style->white; if(foreground != NULL) plot->legends_attr.fg = *foreground; plot->legends_attr.transparent = TRUE; if(background != NULL){ plot->legends_attr.bg = *background; plot->legends_attr.transparent = FALSE; } gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } void gtk_plot_add_data(GtkPlot *plot, GtkPlotData *dataset) { gboolean veto = TRUE; _gtkextra_signal_emit (GTK_OBJECT(plot), plot_signals[ADD_DATA], dataset, &veto); plot->data_sets = g_list_append(plot->data_sets, dataset); gtk_widget_ref(GTK_WIDGET(dataset)); gtk_object_sink(GTK_OBJECT(dataset)); dataset->plot = plot; gtk_signal_emit_by_name (GTK_OBJECT(dataset), "add_to_plot", plot, &veto); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); } GtkPlotData * gtk_plot_add_function(GtkPlot *plot, GtkPlotFunc function) { GtkPlotData *dataset; dataset = GTK_PLOT_DATA(gtk_plot_data_new_function(function)); gtk_plot_add_data(plot, dataset); return (dataset); } gint gtk_plot_remove_data(GtkPlot *plot, GtkPlotData *dataset) { GList *datasets; gpointer data; datasets = plot->data_sets; while(datasets) { data = datasets->data; if(GTK_PLOT_DATA(data) == dataset){ gtk_widget_unref(GTK_WIDGET(dataset)); plot->data_sets = g_list_remove_link(plot->data_sets, datasets); g_list_free_1(datasets); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); return TRUE; } datasets = datasets->next; } return FALSE; } gint gtk_plot_remove_text(GtkPlot *plot, GtkPlotText *text) { GList *list; gpointer data; list = plot->text; while(list) { data = list->data; if((GtkPlotText *)data == text){ plot->text = g_list_remove_link(plot->text, list); g_list_free_1(list); gtk_signal_emit (GTK_OBJECT(plot), plot_signals[CHANGED]); return TRUE; } list = list->next; } return FALSE; } static void gtk_plot_real_ticks_recalc(GtkPlotTicks *ticks) { GtkPlotScale scale; gdouble min = 0., max = 0.; gdouble tick = 0.0; gdouble tick_step = 0.0; gdouble major_step; gdouble minor_step; gint nmajor = 0; gint n = 0; gdouble absmin, absmax; GtkPlotTick *major = NULL; gboolean changed = TRUE; scale = ticks->scale; max = ticks->max; min = ticks->min; absmin = min; absmax = max; if(ticks->set_limits){ max = MIN(max, ticks->end); min = MAX(min, ticks->begin); absmin = min; absmax = max; } else { /* printf("%f\n",ticks->step); printf("%f %f\n",min/ticks->step,floor(min/ticks->step)); printf("%f %f\n",max/ticks->step,ceil(max/ticks->step)); */ max = ceil(max/ticks->step) * ticks->step; min = floor(min/ticks->step) * ticks->step; } if(scale == GTK_PLOT_SCALE_LOG10){ min = ticks->min; max = ticks->max; if(max <= 0.0f) ticks->max = max = 1.E-11; if(max <= 0) ticks->max = max = fabs(max); if(min <= 0) ticks->min = min = max / 100.; min = floor(log10(min)); min = pow(10., min); absmin = ticks->min; absmax = ticks->max; } if(ticks->values){ g_free(ticks->values); ticks->values = NULL; } ticks->nmajorticks = 0; ticks->nminorticks = 0; major_step = ticks->step; minor_step = major_step / ((gdouble)ticks->nminor + 1.0); if(scale == GTK_PLOT_SCALE_LOG10){ if(major_step != 0.) major_step = floor(major_step); if(major_step == 0.) major_step = 1.0; ticks->nminor = 8; } if(ticks->step > 0.){ major = g_new0(GtkPlotTick,1); tick_step = min; tick = min; n = 0; while(tick <= max + 2*fabs(major_step)){ if(tick >= absmin-major_step*1.E-10 && tick <= absmax+major_step*1.E-10){ nmajor ++; major = g_realloc(major, nmajor*sizeof(GtkPlotTick)); major[nmajor-1].value = tick; major[nmajor-1].minor = FALSE; } switch(scale){ case GTK_PLOT_SCALE_LINEAR: tick += major_step; break; case GTK_PLOT_SCALE_LOG10: n++; tick = tick_step * pow(10., n*major_step); break; } } } if(nmajor == 0) return; ticks->nticks = 0; ticks->nmajorticks = nmajor; ticks->values = g_new0(GtkPlotTick, 1); if(ticks->step >0.){ gint i; n = 0; for(nmajor = 0; nmajor <= ticks->nmajorticks; nmajor++){ if(nmajor < ticks->nmajorticks){ n++; ticks->values = g_realloc(ticks->values, n*sizeof(GtkPlotTick)); ticks->values[n-1] = major[nmajor]; } switch(scale){ case GTK_PLOT_SCALE_LINEAR: if(nmajor < ticks->nmajorticks) tick_step = major[nmajor].value - major_step; else tick_step = major[nmajor-1].value; tick = tick_step; break; case GTK_PLOT_SCALE_LOG10: if(nmajor < ticks->nmajorticks) tick_step = major[nmajor].value/10.0; else tick_step = major[nmajor-1].value; tick = tick_step; break; } for(i = 0; i < ticks->nminor; i++){ switch(scale){ case GTK_PLOT_SCALE_LINEAR: tick += minor_step; break; case GTK_PLOT_SCALE_LOG10: tick += tick_step; break; } if(tick >= absmin-major_step*1.E-10 && tick <= absmax+major_step*1.E-10){ n++; ticks->values = g_realloc(ticks->values, n*sizeof(GtkPlotTick)); ticks->values[n-1].value = tick; ticks->values[n-1].minor = TRUE; ticks->nminorticks++; } } } } ticks->nticks = n; if(major) g_free(major); /* sorting ticks */ while(changed){ gint i; changed = FALSE; for(i = 0; i < ticks->nticks - 1; i++){ if(ticks->values[i].value > ticks->values[i+1].value) { GtkPlotTick aux = ticks->values[i]; ticks->values[i] = ticks->values[i+1]; ticks->values[i+1] = aux; changed = TRUE; } } } /* ticks->values[0].value = absmin; ticks->values[n-1].value = absmax; */ } void gtk_plot_ticks_recalc(GtkPlotAxis *axis) { GtkPlotTicks *ticks = &axis->ticks; if(ticks->apply_break){ GtkPlotTicks a1, a2; gint i; a1.scale = ticks->scale; a1.step = ticks->step; a1.begin = ticks->begin; a1.end = ticks->end; a1.nminor = ticks->nminor; a1.set_limits = ticks->set_limits; a1.min = ticks->min; a1.max = ticks->break_min; a1.values = NULL; gtk_plot_real_ticks_recalc(&a1); a2.scale = ticks->break_scale; a2.step = ticks->break_step; a2.begin = ticks->begin; a2.end = ticks->end; a2.nminor = ticks->break_nminor; a2.set_limits = ticks->set_limits; a2.min = ticks->break_max; a2.max = ticks->max; a2.values = NULL; gtk_plot_real_ticks_recalc(&a2); if(ticks->values){ g_free(ticks->values); ticks->values = NULL; } ticks->nmajorticks = a1.nmajorticks+a2.nmajorticks; ticks->nminorticks = a1.nminorticks+a2.nminorticks; ticks->nticks = a1.nticks+a2.nticks; ticks->values = g_new0(GtkPlotTick, ticks->nticks); for(i = 0; i < a1.nticks; i++) ticks->values[i] = a1.values[i]; for(i = 0; i < a2.nticks; i++) ticks->values[a1.nticks+i] = a2.values[i]; if(a1.values) g_free(a1.values); if(a2.values) g_free(a2.values); } else { gtk_plot_real_ticks_recalc(ticks); } } static void update_datasets(GtkPlot *plot, gboolean new_range) { GList *list = NULL; list = plot->data_sets; while(list) { gtk_signal_emit_by_name(GTK_OBJECT(list->data), "update", new_range); list = list->next; } }