]> git.sur5r.net Git - glabels/blob - glabels2/src/util.c
4441f1c08e4cc944668e69e9cf824817cc5173e5
[glabels] / glabels2 / src / util.c
1 /*
2  *  util.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "util.h"
24
25 #include <string.h>
26 #include <glib.h>
27 #include <math.h>
28 #include <gtk/gtk.h>
29
30 #include <libglabels/libglabels.h>
31
32 #define FRAC_EPSILON 0.00005
33
34
35 /****************************************************************************/
36 /* Append ".glabels" extension to filename if needed.                       */
37 /****************************************************************************/
38 gchar *
39 gl_util_add_extension (const gchar *orig_filename)
40 {
41         gchar *new_filename, *extension;
42
43         extension = strrchr (orig_filename, '.');
44         if (extension == NULL) {
45                 new_filename = g_strconcat (orig_filename, ".glabels", NULL);
46         } else {
47                 if (g_strcasecmp (extension, ".glabels") != 0) {
48                         new_filename =
49                             g_strconcat (orig_filename, ".glabels", NULL);
50                 } else {
51                         new_filename = g_strdup (orig_filename);
52                 }
53         }
54
55         return new_filename;
56 }
57
58
59 /****************************************************************************/
60 /* Remove ".glabels" extension from filename if needed.                     */
61 /****************************************************************************/
62 gchar *
63 gl_util_remove_extension (const gchar *orig_filename)
64 {
65         gchar *new_filename, *extension;
66
67         new_filename = g_strdup (orig_filename);
68
69         extension = strrchr (new_filename, '.');
70         if (extension != NULL) {
71                 if (g_strcasecmp (extension, ".glabels") == 0) {
72                         *extension = 0; /* truncate string, rm extension */
73                 }
74         }
75
76         return new_filename;
77 }
78
79
80 /****************************************************************************/
81 /* Make sure we have an absolute path to filename.                          */
82 /****************************************************************************/
83 gchar *
84 gl_util_make_absolute (const gchar *filename)
85 {
86         gchar *pwd, *absolute_filename;
87
88         if (g_path_is_absolute (filename)) {
89                 absolute_filename = g_strdup (filename);
90         } else {
91                 pwd = g_get_current_dir ();
92                 absolute_filename = g_build_filename (pwd, filename, NULL);
93                 g_free (pwd);
94         }
95
96         return absolute_filename;
97 }
98
99
100 /****************************************************************************/
101 /* Create fractional representation of number, if possible.                 */
102 /****************************************************************************/
103 gchar *
104 gl_util_fraction (gdouble x)
105 {
106         static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
107         gint i;
108         gdouble product, remainder;
109         gint n, d;
110
111         for ( i=0; denom[i] != 0.0; i++ ) {
112                 product = x * denom[i];
113                 remainder = fabs(product - ((gint)(product+0.5)));
114                 if ( remainder < FRAC_EPSILON ) break;
115         }
116
117         if ( denom[i] == 0.0 ) {
118                 /* None of our denominators work. */
119                 return g_strdup_printf ("%.5g", x);
120         }
121         if ( denom[i] == 1.0 ) {
122                 /* Simple integer. */
123                 return g_strdup_printf ("%d", (gint)x);
124         }
125         n = (gint)( x * denom[i] + 0.5 );
126         d = (gint)denom[i];
127         if ( n > d ) {
128                 return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d);
129         } else {
130                 return g_strdup_printf ("%d/%d", (n%d), d);
131         }
132 }
133
134
135 /****************************************************************************/
136 /* Utilities to deal with PangoAlignment types.                             */
137 /****************************************************************************/
138 const gchar *
139 gl_util_align_to_string (PangoAlignment align)
140 {
141         switch (align) {
142         case PANGO_ALIGN_LEFT:
143                 return "Left";
144         case PANGO_ALIGN_CENTER:
145                 return "Center";
146         case PANGO_ALIGN_RIGHT:
147                 return "Right";
148         default:
149                 return "?";
150         }
151 }
152
153
154 PangoAlignment
155 gl_util_string_to_align (const gchar *string)
156 {
157
158         if (g_strcasecmp (string, "Left") == 0) {
159                 return PANGO_ALIGN_LEFT;
160         } else if (g_strcasecmp (string, "Center") == 0) {
161                 return PANGO_ALIGN_CENTER;
162         } else if (g_strcasecmp (string, "Right") == 0) {
163                 return PANGO_ALIGN_RIGHT;
164         } else {
165                 return PANGO_ALIGN_LEFT;
166         }
167
168 }
169
170
171 /****************************************************************************/
172 /* Utilities to deal with PangoWeight types                                 */
173 /****************************************************************************/
174 const gchar *
175 gl_util_weight_to_string (PangoWeight weight)
176 {
177         switch (weight) {
178         case PANGO_WEIGHT_NORMAL:
179                 return "Regular";
180         case PANGO_WEIGHT_BOLD:
181                 return "Bold";
182         default:
183                 return "?";
184         }
185 }
186
187
188 PangoWeight
189 gl_util_string_to_weight (const gchar *string)
190 {
191
192         if (g_strcasecmp (string, "Regular") == 0) {
193                 return PANGO_WEIGHT_NORMAL;
194         } else if (g_strcasecmp (string, "Bold") == 0) {
195                 return PANGO_WEIGHT_BOLD;
196         } else {
197                 return PANGO_WEIGHT_NORMAL;
198         }
199
200 }
201
202
203 /****************************************************************************/
204 /* Convienience function to set strings in a text combo_box from a GList    */
205 /****************************************************************************/
206 void
207 gl_util_combo_box_set_strings (GtkComboBox       *combo,
208                                GList             *list)
209 {
210         GtkTreeModel *model;
211         GList        *p;
212
213         g_return_if_fail (list);
214
215         model = gtk_combo_box_get_model(combo);
216         gtk_list_store_clear (GTK_LIST_STORE (model));
217
218         for (p=list; p!=NULL; p=p->next) {
219                 if (p->data) {
220                         gtk_combo_box_append_text (combo, p->data);
221                 }
222         }
223 }
224
225
226 /*---------------------------------------------------------------------------*/
227 /* PRIVATE.  gl_util_combo_box_set_active_text support.                      */
228 /*---------------------------------------------------------------------------*/
229
230 typedef struct {
231   const gchar *text;
232   GtkTreeIter  iter;
233   gboolean     found;
234 } TextSearchData;
235
236 static gboolean
237 search_text_func (GtkTreeModel *model,
238                   GtkTreePath  *path,
239                   GtkTreeIter  *iter,
240                   gpointer      data)
241 {
242   TextSearchData *search_data = (TextSearchData *)data;
243   gchar          *text = NULL;
244
245   gtk_tree_model_get (model, iter, 0, &text, -1);
246
247   if (strcmp (text,search_data->text) == 0) {
248     search_data->found = TRUE;
249     search_data->iter  = *iter;
250   }
251
252   g_free (text);
253   
254   return FALSE;
255 }
256
257
258 /****************************************************************************/
259 /* Convienience function to set active text in a text combo_box from text   */
260 /****************************************************************************/
261 void
262 gl_util_combo_box_set_active_text (GtkComboBox       *combo,
263                                    const gchar       *text)
264 {
265         GtkTreeModel   *model = gtk_combo_box_get_model(combo);
266
267         g_return_if_fail (GTK_IS_LIST_STORE (model));
268
269         if (!text) {
270
271                 gtk_combo_box_set_active (combo, -1);
272
273         } else {
274                 TextSearchData  search_data;
275
276                 search_data.text        = text;
277                 search_data.found       = FALSE;
278
279                 gtk_tree_model_foreach (model, search_text_func, &search_data);
280                 if (search_data.found) {
281                         gtk_combo_box_set_active_iter (combo,
282                                                        &search_data.iter);
283                 } else {
284                         gtk_combo_box_set_active (combo, -1);
285                 }    
286
287         }
288
289 }
290
291
292 /****************************************************************************/
293 /* Convienience function to add a simple text model to an existing          */
294 /* combo_box.  This is needed since combo_boxes created with glade do not   */
295 /* use the gtk_combo_box_new_text() constructor.                            */
296 /****************************************************************************/
297 void
298 gl_util_combo_box_add_text_model (GtkComboBox       *combo)
299 {
300         GtkCellRenderer *cell;
301         GtkListStore *store;
302
303         store = gtk_list_store_new (1, G_TYPE_STRING);
304         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
305         g_object_unref (store);
306
307         cell = gtk_cell_renderer_text_new ();
308         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
309         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
310                                         "text", 0,
311                                         NULL);
312 }
313
314
315 /****************************************************************************/
316 /* Get widgets from GtkBuilder "en masse."                                  */
317 /****************************************************************************/
318 void gl_util_get_builder_widgets (GtkBuilder *builder,
319                                   gchar      *first_name,
320                                   ...)
321 {
322         va_list     args;
323         gchar      *name;
324         GtkWidget **p_widget;
325
326         va_start (args, first_name);
327
328         for ( name = first_name; name; name = va_arg (args, gchar *) )
329         {
330                 p_widget = va_arg (args, GtkWidget **);
331
332                 *p_widget = GTK_WIDGET (gtk_builder_get_object (builder, name));
333
334                 if (!*p_widget)
335                 {
336                         g_critical ("Could not load widget \"%s\".\n\ngLabels may not be installed correctly!",
337                                     name);
338                         break;
339                 }
340         }
341
342         va_end (args);
343 }
344
345
346
347 /*
348  * Local Variables:       -- emacs
349  * mode: C                -- emacs
350  * c-basic-offset: 8      -- emacs
351  * tab-width: 8           -- emacs
352  * indent-tabs-mode: nil  -- emacs
353  * End:                   -- emacs
354  */