Canonicalise identifier names
[pspp-builds.git] / lib / gtksheet / psppire-axis.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2008  Free Software Foundation
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18 #include <string.h>
19 #include <stdlib.h>
20
21 #include <libpspp/tower.h>
22 #include <libpspp/pool.h>
23 #include <libpspp/misc.h>
24 #include "psppire-axis.h"
25 #include <gtk/gtk.h>
26
27
28 #define PSPPIRE_AXIS_GET_IFACE(obj) \
29   (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface))
30
31 GType
32 psppire_axis_iface_get_type (void)
33 {
34   static GType psppire_axis_iface_type = 0;
35
36   if (! psppire_axis_iface_type)
37     {
38       static const GTypeInfo psppire_axis_iface_info =
39       {
40         sizeof (PsppireAxisIface), /* class_size */
41         NULL,           /* base init */
42         NULL,           /* base_finalize */
43         NULL,
44         NULL,           /* class_finalize */
45         NULL,           /* class_data */
46         0,
47         0,              /* n_preallocs */
48         NULL
49       };
50
51       psppire_axis_iface_type =
52         g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface",
53                                 &psppire_axis_iface_info, 0);
54     }
55
56   return psppire_axis_iface_type;
57 }
58
59 G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT);
60
61
62
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);
67
68
69 /* --- variables --- */
70 static GObjectClass     *parent_class = NULL;
71
72
73
74 enum
75   {
76     PROP_0,
77     PROP_MIN_EXTENT,
78     PROP_DEFAULT_SIZE
79   };
80
81
82 static void
83 psppire_axis_get_property (GObject         *object,
84                            guint            prop_id,
85                            GValue          *value,
86                            GParamSpec      *pspec)
87 {
88   PsppireAxis *axis = PSPPIRE_AXIS (object);
89
90   switch (prop_id)
91     {
92     case PROP_MIN_EXTENT:
93       g_value_set_long (value, axis->min_extent);
94       break;
95     case PROP_DEFAULT_SIZE:
96       g_value_set_int (value, axis->default_size);
97       break;
98     default:
99       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100       break;
101     };
102 }
103
104
105 static void
106 psppire_axis_set_property (GObject         *object,
107                            guint            prop_id,
108                            const GValue    *value,
109                            GParamSpec      *pspec)
110 {
111   PsppireAxis *axis = PSPPIRE_AXIS (object);
112
113   switch (prop_id)
114     {
115     case PROP_MIN_EXTENT:
116       axis->min_extent = g_value_get_long (value);
117       break;
118     case PROP_DEFAULT_SIZE:
119       axis->default_size = g_value_get_int (value);
120       break;
121     default:
122       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
123       break;
124     };
125 }
126
127 static void
128 psppire_axis_class_init (PsppireAxisClass *class)
129 {
130   GObjectClass *object_class = G_OBJECT_CLASS (class);
131   GParamSpec *min_extent_spec;
132   GParamSpec *default_size_spec;
133
134   object_class->set_property = psppire_axis_set_property;
135   object_class->get_property = psppire_axis_get_property;
136
137   min_extent_spec =
138     g_param_spec_long ("minimum-extent",
139                        "Minimum Extent",
140                        "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget).",
141                        0, G_MAXLONG,
142                        0,
143                        G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
144
145   g_object_class_install_property (object_class,
146                                    PROP_MIN_EXTENT,
147                                    min_extent_spec);
148
149
150   default_size_spec =
151     g_param_spec_int ("default-size",
152                       "Default Size",
153                       "The size given to units which haven't been explicity inserted",
154                       0, G_MAXINT,
155                       25,
156                       G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
157
158
159   g_object_class_install_property (object_class,
160                                    PROP_DEFAULT_SIZE,
161                                    default_size_spec);
162
163   parent_class = g_type_class_peek_parent (class);
164
165   object_class->finalize = psppire_axis_finalize;
166 }
167
168
169 static void
170 psppire_axis_init (PsppireAxis *axis)
171 {
172 }
173
174
175 static void
176 psppire_axis_finalize (GObject *object)
177 {
178   G_OBJECT_CLASS (parent_class)->finalize (object);
179 }
180
181 gint
182 psppire_axis_unit_size (const PsppireAxis *a, gint unit)
183 {
184   g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
185
186   g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1);
187
188
189   if  (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a))
190     return a->default_size;
191
192   return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit);
193 }
194
195 gint
196 psppire_axis_unit_count (const PsppireAxis *a)
197 {
198   glong padding = 0;
199   glong actual_size;
200
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);
203
204   actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
205
206   if ( actual_size < a->min_extent )
207     padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size);
208
209   return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding;
210 }
211
212
213 /* Return the starting pixel of UNIT */
214 glong
215 psppire_axis_start_pixel (const PsppireAxis *a, gint unit)
216 {
217   gint the_count, total_size ;
218   g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
219
220   the_count =  PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
221   total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
222
223   if ( unit >= the_count)
224     {
225       return  total_size + (unit - the_count) * a->default_size;
226     }
227
228   return PSPPIRE_AXIS_GET_IFACE (a)->start_pixel (a, unit);
229 }
230
231
232 /* Return the unit covered by PIXEL */
233 gint
234 psppire_axis_unit_at_pixel (const PsppireAxis *a, glong pixel)
235 {
236   glong total_size;
237
238   g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
239
240   g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1);
241
242   g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel, -1);
243
244   total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
245
246   if (pixel >= total_size)
247     {
248       gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
249       glong extra = pixel - total_size;
250
251       return n_items - 1 + DIV_RND_UP (extra,  a->default_size);
252     }
253
254   return PSPPIRE_AXIS_GET_IFACE (a)->unit_at_pixel (a, pixel);
255 }