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 /* --- prototypes --- */
28 static void psppire_axis_class_init (PsppireAxisClass *class);
29 static void psppire_axis_init (PsppireAxis *axis);
30 static void psppire_axis_finalize (GObject *object);
33 /* --- variables --- */
34 static GObjectClass *parent_class = NULL;
36 /* --- functions --- */
38 * psppire_axis_get_type:
39 * @returns: the type ID for accelerator groups.
42 psppire_axis_get_type (void)
44 static GType object_type = 0;
48 static const GTypeInfo object_info = {
49 sizeof (PsppireAxisClass),
51 (GBaseFinalizeFunc) NULL,
52 (GClassInitFunc) psppire_axis_class_init,
53 NULL, /* class_finalize */
54 NULL, /* class_data */
57 (GInstanceInitFunc) psppire_axis_init,
60 object_type = g_type_register_static (G_TYPE_OBJECT,
77 psppire_axis_get_property (GObject *object,
82 PsppireAxis *axis = PSPPIRE_AXIS (object);
87 g_value_set_long (value, axis->min_extent);
89 case PROP_DEFAULT_SIZE:
90 g_value_set_int (value, axis->default_size);
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100 psppire_axis_set_property (GObject *object,
105 PsppireAxis *axis = PSPPIRE_AXIS (object);
109 case PROP_MIN_EXTENT:
110 axis->min_extent = g_value_get_long (value);
112 case PROP_DEFAULT_SIZE:
113 axis->default_size = g_value_get_int (value);
116 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122 psppire_axis_class_init (PsppireAxisClass *class)
124 GObjectClass *object_class = G_OBJECT_CLASS (class);
125 GParamSpec *min_extent_spec;
126 GParamSpec *default_size_spec;
128 object_class->set_property = psppire_axis_set_property;
129 object_class->get_property = psppire_axis_get_property;
132 g_param_spec_long ("minimum-extent",
134 "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget)",
137 G_PARAM_WRITABLE | G_PARAM_READABLE );
139 g_object_class_install_property (object_class,
145 g_param_spec_pointer ("default-size",
147 "The size given to units which haven't been explicity inserted",
148 G_PARAM_WRITABLE | G_PARAM_READABLE );
151 g_object_class_install_property (object_class,
155 parent_class = g_type_class_peek_parent (class);
157 object_class->finalize = psppire_axis_finalize;
162 psppire_axis_init (PsppireAxis *axis)
164 axis->min_extent = 800;
165 axis->default_size = 75;
167 psppire_axis_clear (axis);
172 psppire_axis_finalize (GObject *object)
174 PsppireAxis *a = PSPPIRE_AXIS (object);
175 pool_destroy (a->pool);
176 G_OBJECT_CLASS (parent_class)->finalize (object);
181 * @returns: a new #PsppireAxis object
183 * Creates a new #PsppireAxis.
186 psppire_axis_new (void)
188 return g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
193 psppire_axis_unit_size (PsppireAxis *a, gint unit)
195 const struct tower_node *node;
196 if (unit >= tower_count (&a->tower))
197 return a->default_size;
199 node = tower_get (&a->tower, unit);
201 return tower_node_get_size (node);
205 psppire_axis_unit_count (PsppireAxis *a)
209 if ( tower_height (&a->tower) < a->min_extent )
210 padding = (a->min_extent - tower_height (&a->tower))
213 return tower_count (&a->tower) + padding;
217 /* Return the starting pixel of UNIT */
219 psppire_axis_pixel_start (PsppireAxis *a, gint unit)
221 const struct tower_node *node;
223 if ( unit >= tower_count (&a->tower))
225 return tower_height (&a->tower) +
226 (unit - tower_count (&a->tower)) * a->default_size;
229 node = tower_get (&a->tower, unit);
230 return tower_node_get_level (node);
234 /* Return the unit covered by PIXEL */
236 psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel)
238 const struct tower_node *node;
239 unsigned long int node_start;
241 if (pixel >= tower_height (&a->tower))
243 glong extra = pixel - tower_height (&a->tower);
245 if ( extra > a->min_extent - tower_height (&a->tower))
246 extra = a->min_extent - tower_height (&a->tower);
248 return tower_count (&a->tower) - 1 + extra / a->default_size;
251 node = tower_lookup (&a->tower, pixel, &node_start);
253 return tower_node_get_index (node);
257 psppire_axis_append (PsppireAxis *a, gint size)
259 struct tower_node *new = pool_malloc (a->pool, sizeof *new);
261 tower_insert (&a->tower, size, new, NULL);
266 /* Insert a new unit of size SIZE before position POSN */
268 psppire_axis_insert (PsppireAxis *a, gint size, gint posn)
270 struct tower_node *new = pool_malloc (a->pool, sizeof *new);
272 struct tower_node *before = NULL;
274 if ( posn != tower_count (&a->tower))
275 before = tower_get (&a->tower, posn);
277 tower_insert (&a->tower, size, new, before);
282 psppire_axis_remove (PsppireAxis *a, gint posn)
284 struct tower_node *node = tower_get (&a->tower, posn);
286 tower_delete (&a->tower, node);
288 pool_free (a->pool, node);
293 psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn)
295 struct tower_node *node = tower_get (&a->tower, posn);
297 tower_resize (&a->tower, node, size);
302 psppire_axis_clear (PsppireAxis *a)
304 pool_destroy (a->pool);
305 a->pool = pool_create ();
306 tower_init (&a->tower);