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_pointer ("minimum-extent",
134 "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget)",
135 G_PARAM_WRITABLE | G_PARAM_READABLE );
137 g_object_class_install_property (object_class,
143 g_param_spec_pointer ("default-size",
145 "The size given to units which haven't been explicity inserted",
146 G_PARAM_WRITABLE | G_PARAM_READABLE );
149 g_object_class_install_property (object_class,
153 parent_class = g_type_class_peek_parent (class);
155 object_class->finalize = psppire_axis_finalize;
160 psppire_axis_init (PsppireAxis *axis)
162 axis->min_extent = 800;
163 axis->default_size = 75;
165 psppire_axis_clear (axis);
170 psppire_axis_finalize (GObject *object)
172 PsppireAxis *a = PSPPIRE_AXIS (object);
173 pool_destroy (a->pool);
174 G_OBJECT_CLASS (parent_class)->finalize (object);
179 * @returns: a new #PsppireAxis object
181 * Creates a new #PsppireAxis.
184 psppire_axis_new (void)
186 return g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
191 psppire_axis_unit_size (PsppireAxis *a, gint unit)
193 const struct tower_node *node;
194 if (unit >= tower_count (&a->tower))
195 return a->default_size;
197 node = tower_get (&a->tower, unit);
199 return tower_node_get_size (node);
203 psppire_axis_unit_count (PsppireAxis *a)
207 if ( tower_height (&a->tower) < a->min_extent )
208 padding = (a->min_extent - tower_height (&a->tower))
211 return tower_count (&a->tower) + padding;
215 /* Return the starting pixel of UNIT */
217 psppire_axis_pixel_start (PsppireAxis *a, gint unit)
219 const struct tower_node *node;
221 if ( unit >= tower_count (&a->tower))
223 return tower_height (&a->tower) +
224 (unit - tower_count (&a->tower)) * a->default_size;
227 node = tower_get (&a->tower, unit);
228 return tower_node_get_level (node);
232 /* Return the unit covered by PIXEL */
234 psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel)
236 const struct tower_node *node;
237 unsigned long int node_start;
239 if (pixel >= tower_height (&a->tower))
241 glong extra = pixel - tower_height (&a->tower);
242 return tower_count (&a->tower) + extra / a->default_size;
245 node = tower_lookup (&a->tower, pixel, &node_start);
247 return tower_node_get_index (node);
251 psppire_axis_append (PsppireAxis *a, gint size)
253 struct tower_node *new = pool_malloc (a->pool, sizeof *new);
255 tower_insert (&a->tower, size, new, NULL);
260 /* Insert a new unit of size SIZE before position POSN */
262 psppire_axis_insert (PsppireAxis *a, gint size, gint posn)
264 struct tower_node *new = pool_malloc (a->pool, sizeof *new);
266 struct tower_node *before = NULL;
268 if ( posn != tower_count (&a->tower))
269 before = tower_get (&a->tower, posn);
271 tower_insert (&a->tower, size, new, before);
276 psppire_axis_remove (PsppireAxis *a, gint posn)
278 struct tower_node *node = tower_get (&a->tower, posn);
280 tower_delete (&a->tower, node);
282 pool_free (a->pool, node);
287 psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn)
289 struct tower_node *node = tower_get (&a->tower, posn);
291 tower_resize (&a->tower, node, size);
296 psppire_axis_clear (PsppireAxis *a)
298 pool_destroy (a->pool);
299 a->pool = pool_create ();
300 tower_init (&a->tower);