1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <libpspp/tower.h>
22 #include <libpspp/pool.h>
23 #include "psppire-axis.h"
27 #define PSPPIRE_AXIS_GET_IFACE(obj) \
28 (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface))
31 psppire_axis_iface_get_type (void)
33 static GType psppire_axis_iface_type = 0;
35 if (! psppire_axis_iface_type)
37 static const GTypeInfo psppire_axis_iface_info =
39 sizeof (PsppireAxisIface), /* class_size */
41 NULL, /* base_finalize */
43 NULL, /* class_finalize */
44 NULL, /* class_data */
50 psppire_axis_iface_type =
51 g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface",
52 &psppire_axis_iface_info, 0);
55 return psppire_axis_iface_type;
58 G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT);
62 /* --- prototypes --- */
63 static void psppire_axis_class_init (PsppireAxisClass *class);
64 static void psppire_axis_init (PsppireAxis *axis);
65 static void psppire_axis_finalize (GObject *object);
68 /* --- variables --- */
69 static GObjectClass *parent_class = NULL;
82 psppire_axis_get_property (GObject *object,
87 PsppireAxis *axis = PSPPIRE_AXIS (object);
92 g_value_set_long (value, axis->min_extent);
94 case PROP_DEFAULT_SIZE:
95 g_value_set_int (value, axis->default_size);
98 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105 psppire_axis_set_property (GObject *object,
110 PsppireAxis *axis = PSPPIRE_AXIS (object);
114 case PROP_MIN_EXTENT:
115 axis->min_extent = g_value_get_long (value);
117 case PROP_DEFAULT_SIZE:
118 axis->default_size = g_value_get_int (value);
121 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127 psppire_axis_class_init (PsppireAxisClass *class)
129 GObjectClass *object_class = G_OBJECT_CLASS (class);
130 GParamSpec *min_extent_spec;
131 GParamSpec *default_size_spec;
133 object_class->set_property = psppire_axis_set_property;
134 object_class->get_property = psppire_axis_get_property;
137 g_param_spec_long ("minimum-extent",
139 "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget).",
142 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
144 g_object_class_install_property (object_class,
150 g_param_spec_int ("default-size",
152 "The size given to units which haven't been explicity inserted",
155 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
158 g_object_class_install_property (object_class,
162 parent_class = g_type_class_peek_parent (class);
164 object_class->finalize = psppire_axis_finalize;
169 psppire_axis_init (PsppireAxis *axis)
175 psppire_axis_finalize (GObject *object)
177 G_OBJECT_CLASS (parent_class)->finalize (object);
181 psppire_axis_unit_size (const PsppireAxis *a, gint unit)
183 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
185 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1);
188 if (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a))
189 return a->default_size;
191 return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit);
195 psppire_axis_unit_count (const PsppireAxis *a)
200 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
201 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_count, -1);
203 actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
205 if ( actual_size < a->min_extent )
206 padding = (a->min_extent - actual_size) / a->default_size;
208 return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding;
212 /* Return the starting pixel of UNIT */
214 psppire_axis_pixel_start (const PsppireAxis *a, gint unit)
216 gint the_count, total_size ;
217 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
219 the_count = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
220 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
222 if ( unit >= the_count)
224 return total_size + (unit - the_count) * a->default_size;
227 // g_print ("%s %d\n", __FUNCTION__, unit);
229 return PSPPIRE_AXIS_GET_IFACE (a)->pixel_start (a, unit);
233 /* Return the unit covered by PIXEL */
235 psppire_axis_get_unit_at_pixel (const PsppireAxis *a, glong pixel)
239 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
241 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1);
243 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel, -1);
245 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
247 if (pixel >= total_size)
249 gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
250 glong extra = pixel - total_size;
252 return n_items - 1 + extra / a->default_size;
255 return PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel (a, pixel);