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 <libpspp/misc.h>
24 #include "psppire-axis.h"
28 #define PSPPIRE_AXIS_GET_IFACE(obj) \
29 (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface))
32 psppire_axis_iface_get_type (void)
34 static GType psppire_axis_iface_type = 0;
36 if (! psppire_axis_iface_type)
38 static const GTypeInfo psppire_axis_iface_info =
40 sizeof (PsppireAxisIface), /* class_size */
42 NULL, /* base_finalize */
44 NULL, /* class_finalize */
45 NULL, /* class_data */
51 psppire_axis_iface_type =
52 g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface",
53 &psppire_axis_iface_info, 0);
56 return psppire_axis_iface_type;
59 G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT);
63 /* --- prototypes --- */
64 static void psppire_axis_class_init (PsppireAxisClass *class);
65 static void psppire_axis_init (PsppireAxis *axis);
66 static void psppire_axis_finalize (GObject *object);
69 /* --- variables --- */
70 static GObjectClass *parent_class = NULL;
83 psppire_axis_get_property (GObject *object,
88 PsppireAxis *axis = PSPPIRE_AXIS (object);
93 g_value_set_long (value, axis->min_extent);
95 case PROP_DEFAULT_SIZE:
96 g_value_set_int (value, axis->default_size);
99 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
106 psppire_axis_set_property (GObject *object,
111 PsppireAxis *axis = PSPPIRE_AXIS (object);
115 case PROP_MIN_EXTENT:
116 axis->min_extent = g_value_get_long (value);
118 case PROP_DEFAULT_SIZE:
119 axis->default_size = g_value_get_int (value);
122 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
128 psppire_axis_class_init (PsppireAxisClass *class)
130 GObjectClass *object_class = G_OBJECT_CLASS (class);
131 GParamSpec *min_extent_spec;
132 GParamSpec *default_size_spec;
134 object_class->set_property = psppire_axis_set_property;
135 object_class->get_property = psppire_axis_get_property;
138 g_param_spec_long ("minimum-extent",
140 "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget).",
143 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
145 g_object_class_install_property (object_class,
151 g_param_spec_int ("default-size",
153 "The size given to units which haven't been explicity inserted",
156 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
159 g_object_class_install_property (object_class,
163 parent_class = g_type_class_peek_parent (class);
165 object_class->finalize = psppire_axis_finalize;
170 psppire_axis_init (PsppireAxis *axis)
176 psppire_axis_finalize (GObject *object)
178 G_OBJECT_CLASS (parent_class)->finalize (object);
182 psppire_axis_unit_size (const PsppireAxis *a, gint unit)
184 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
186 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1);
189 if (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a))
190 return a->default_size;
192 return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit);
196 psppire_axis_unit_count (const PsppireAxis *a)
201 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
202 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_count, -1);
204 actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
206 if ( actual_size < a->min_extent )
207 padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size);
209 return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding;
213 /* Return the starting pixel of UNIT */
215 psppire_axis_pixel_start (const PsppireAxis *a, gint unit)
217 gint the_count, total_size ;
218 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
220 the_count = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
221 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
223 if ( unit >= the_count)
225 return total_size + (unit - the_count) * a->default_size;
228 return PSPPIRE_AXIS_GET_IFACE (a)->pixel_start (a, unit);
232 /* Return the unit covered by PIXEL */
234 psppire_axis_get_unit_at_pixel (const PsppireAxis *a, glong pixel)
238 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
240 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1);
242 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel, -1);
244 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
246 if (pixel >= total_size)
248 gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
249 glong extra = pixel - total_size;
251 return n_items - 1 + DIV_RND_UP (extra, a->default_size);
254 return PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel (a, pixel);