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"
25 #include <ui/gui/psppire-marshal.h>
37 static guint signals[n_signals] ;
40 #define PSPPIRE_AXIS_GET_IFACE(obj) \
41 (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface))
44 psppire_axis_iface_get_type (void)
46 static GType psppire_axis_iface_type = 0;
48 if (! psppire_axis_iface_type)
50 static const GTypeInfo psppire_axis_iface_info =
52 sizeof (PsppireAxisIface), /* class_size */
54 NULL, /* base_finalize */
56 NULL, /* class_finalize */
57 NULL, /* class_data */
63 psppire_axis_iface_type =
64 g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface",
65 &psppire_axis_iface_info, 0);
68 return psppire_axis_iface_type;
71 G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT);
75 /* --- prototypes --- */
76 static void psppire_axis_class_init (PsppireAxisClass *class);
77 static void psppire_axis_init (PsppireAxis *axis);
78 static void psppire_axis_finalize (GObject *object);
81 /* --- variables --- */
82 static GObjectClass *parent_class = NULL;
95 psppire_axis_get_property (GObject *object,
100 PsppireAxis *axis = PSPPIRE_AXIS (object);
104 case PROP_MIN_EXTENT:
105 g_value_set_long (value, axis->min_extent);
107 case PROP_DEFAULT_SIZE:
108 g_value_set_int (value, axis->default_size);
111 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
118 psppire_axis_set_property (GObject *object,
123 PsppireAxis *axis = PSPPIRE_AXIS (object);
127 case PROP_MIN_EXTENT:
128 axis->min_extent = g_value_get_long (value);
130 case PROP_DEFAULT_SIZE:
131 axis->default_size = g_value_get_int (value);
134 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 psppire_axis_class_init (PsppireAxisClass *class)
142 GObjectClass *object_class = G_OBJECT_CLASS (class);
143 GParamSpec *min_extent_spec;
144 GParamSpec *default_size_spec;
146 object_class->set_property = psppire_axis_set_property;
147 object_class->get_property = psppire_axis_get_property;
150 g_param_spec_long ("minimum-extent",
152 "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget).",
155 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
157 g_object_class_install_property (object_class,
163 g_param_spec_int ("default-size",
165 "The size given to units which haven't been explicity inserted",
168 G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
171 g_object_class_install_property (object_class,
175 parent_class = g_type_class_peek_parent (class);
177 object_class->finalize = psppire_axis_finalize;
180 signals[RESIZE_UNIT] =
181 g_signal_new ("resize-unit",
182 G_TYPE_FROM_CLASS (object_class),
186 psppire_marshal_VOID__INT_LONG,
196 psppire_axis_init (PsppireAxis *axis)
202 psppire_axis_finalize (GObject *object)
204 G_OBJECT_CLASS (parent_class)->finalize (object);
208 psppire_axis_unit_size (const PsppireAxis *a, gint unit)
210 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
212 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1);
215 if (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a))
216 return a->default_size;
218 return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit);
222 psppire_axis_unit_count (const PsppireAxis *a)
227 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
228 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_count, -1);
230 actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
232 if ( actual_size < a->min_extent )
233 padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size);
235 return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding;
239 /* Return the starting pixel of UNIT */
241 psppire_axis_start_pixel (const PsppireAxis *a, gint unit)
243 gint the_count, total_size ;
244 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
246 the_count = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
247 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
249 if ( unit >= the_count)
251 return total_size + (unit - the_count) * a->default_size;
254 return PSPPIRE_AXIS_GET_IFACE (a)->start_pixel (a, unit);
258 /* Return the unit covered by PIXEL */
260 psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel)
264 g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
266 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1);
268 g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel, -1);
270 total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
272 if (pixel >= total_size)
274 gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
275 glong extra = pixel - total_size;
277 return n_items - 1 + DIV_RND_UP (extra, a->default_size);
280 return PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel (a, pixel);
284 /* Set UNIT to size SIZE */
286 psppire_axis_resize (PsppireAxis *a, gint unit, glong size)
288 g_return_if_fail (PSPPIRE_IS_AXIS (a));
290 g_return_if_fail (PSPPIRE_AXIS_GET_IFACE (a));
292 g_return_if_fail (size > 0);
294 if (PSPPIRE_AXIS_GET_IFACE (a)->resize)
295 PSPPIRE_AXIS_GET_IFACE (a)->resize (a, unit, size);
298 g_signal_emit (a, signals [RESIZE_UNIT], 0, unit, size);