1 /*
2  * Copyright (C) 2002 2003 2004 2005 2011, Magnus Hjorth
3  *
4  * This file is part of mhWaveEdit.
5  *
6  * mhWaveEdit is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * mhWaveEdit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mhWaveEdit; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 
22 #include <config.h>
23 
24 #include <stdlib.h>
25 #include <gtk/gtk.h>
26 #include "um.h"
27 #include "float_box.h"
28 #include "main.h"
29 #include "gettext.h"
30 
31 #if GTK_MAJOR_VERSION==2
32 static GtkEntryClass *parent_class;
33 #else
34 static GtkEditableClass *parent_class;
35 #endif
36 
37 enum {
38      NUMCHANGED_SIGNAL,
39      LAST_SIGNAL
40 };
41 
42 #if GTK_MAJOR_VERSION == 2
43 
44 #include "float_box_marsh.c"
45 #define gtk_marshal_NONE__FLOAT gtk_marshal_VOID__FLOAT
46 
47 #else
48 typedef void (*GtkSignal_NONE__FLOAT) (GtkObject *object, gfloat arg,
49 				       gpointer user_data);
50 
gtk_marshal_NONE__FLOAT(GtkObject * object,GtkSignalFunc func,gpointer func_data,GtkArg * args)51 static void gtk_marshal_NONE__FLOAT(GtkObject *object, GtkSignalFunc func,
52 				    gpointer func_data, GtkArg *args)
53 {
54      GtkSignal_NONE__FLOAT rfunc;
55      rfunc=(GtkSignal_NONE__FLOAT)func;
56      rfunc(object,GTK_VALUE_FLOAT(args[0]),func_data);
57 }
58 #endif
59 
60 static guint floatbox_signals[LAST_SIGNAL] = { 0 };
61 
floatbox_update_text(Floatbox * box)62 static void floatbox_update_text(Floatbox *box)
63 {
64      char e[30];
65      format_float(box->val, e, sizeof(e));
66      gtk_entry_set_text(GTK_ENTRY(box),e);
67 }
68 
69 #if GTK_MAJOR_VERSION==2
floatbox_activate(GtkEntry * editable)70 static void floatbox_activate(GtkEntry *editable)
71 #else
72 static void floatbox_activate(GtkEditable *editable)
73 #endif
74 {
75      float f;
76      char *c,*d;
77      c=(char *)gtk_entry_get_text(GTK_ENTRY(editable));
78      f=strtod(c,&d);
79      if (*d==0)
80 	  floatbox_set(FLOATBOX(editable),f);
81      else
82 	  floatbox_update_text(FLOATBOX(editable));
83      if (parent_class->activate) parent_class->activate(editable);
84 }
85 
floatbox_focus_out(GtkWidget * widget,GdkEventFocus * event)86 static gint floatbox_focus_out(GtkWidget *widget, GdkEventFocus *event)
87 {
88      char *c,*d;
89      float f;
90      Floatbox *b = FLOATBOX(widget);
91      c=(char *)gtk_entry_get_text(GTK_ENTRY(widget));
92      f=strtod(c,&d);
93      if (*d==0 && b->adj!=NULL && f>=gtk_adjustment_get_lower(b->adj) &&
94 	 f<=gtk_adjustment_get_upper(b->adj)) {
95 	  gtk_adjustment_set_value(b->adj,f);
96      }
97      return GTK_WIDGET_CLASS(parent_class)->focus_out_event(widget,event);
98 }
99 
floatbox_class_init(FloatboxClass * klass)100 static void floatbox_class_init(FloatboxClass *klass)
101 {
102      parent_class = gtk_type_class(gtk_entry_get_type());
103 
104 #if GTK_MAJOR_VERSION==2
105      GTK_ENTRY_CLASS(klass)->activate = floatbox_activate;
106 #else
107      GTK_EDITABLE_CLASS(klass)->activate = floatbox_activate;
108 #endif
109      GTK_WIDGET_CLASS(klass)->focus_out_event = floatbox_focus_out;
110      klass->numchange=NULL;
111 
112      floatbox_signals[NUMCHANGED_SIGNAL] =
113 	  gtk_signal_new("numchanged",GTK_RUN_FIRST,
114 			 GTK_CLASS_TYPE(klass),
115 			 GTK_SIGNAL_OFFSET(FloatboxClass,numchange),
116 			 gtk_marshal_NONE__FLOAT,GTK_TYPE_NONE,1,
117 			 GTK_TYPE_FLOAT);
118 
119      gtk_object_class_add_signals(GTK_OBJECT_CLASS(klass),floatbox_signals,
120 				  LAST_SIGNAL);
121 }
122 
floatbox_init(Floatbox * fbox)123 static void floatbox_init(Floatbox *fbox)
124 {
125 #if GTK_MAJOR_VERSION == 2
126      gtk_entry_set_width_chars(GTK_ENTRY(fbox),10);
127 #else
128      GtkRequisition req;
129      gtk_widget_size_request(GTK_WIDGET(fbox),&req);
130      gtk_widget_set_usize(GTK_WIDGET(fbox),req.width/3,req.height);
131 #endif
132      fbox->adj = NULL;
133 }
134 
floatbox_get_type(void)135 GtkType floatbox_get_type(void)
136 {
137      static GtkType id=0;
138      if (!id) {
139 	  GtkTypeInfo info = {
140 	       "Floatbox",
141 	       sizeof(Floatbox),
142 	       sizeof(FloatboxClass),
143 	       (GtkClassInitFunc) floatbox_class_init,
144 	       (GtkObjectInitFunc) floatbox_init };
145 	  id=gtk_type_unique(gtk_entry_get_type(),&info);
146      }
147      return id;
148 }
149 
floatbox_set(Floatbox * box,float val)150 void floatbox_set(Floatbox *box, float val)
151 {
152      if (box->val == val) return;
153      if (box->adj != NULL &&
154 	 val >= gtk_adjustment_get_lower(box->adj) &&
155 	 val <= gtk_adjustment_get_upper(box->adj)) {
156 
157 	  gtk_adjustment_set_value(box->adj, val);
158 	  return;
159      }
160      box->val=val;
161      floatbox_update_text(box);
162      gtk_signal_emit(GTK_OBJECT(box),floatbox_signals[NUMCHANGED_SIGNAL],box->val);
163 }
164 
floatbox_new(float val)165 GtkWidget *floatbox_new(float val)
166 {
167      Floatbox *box;
168      box=gtk_type_new(floatbox_get_type());
169      box->val = val-1.0; /* To force update */
170      floatbox_set(box,val);
171      return GTK_WIDGET(box);
172 }
173 
floatbox_check(Floatbox * box)174 gboolean floatbox_check(Floatbox *box)
175 {
176      gfloat f;
177      char *c,*d;
178      c=(char *)gtk_entry_get_text(GTK_ENTRY(box));
179      f=strtod(c,&d);
180      if (*d==0) {
181 	  floatbox_set(box,f);
182 	  return FALSE;
183      } else {
184 	  d = g_strdup_printf(_("'%s' is not a number!"),c);
185 	  user_error(d);
186 	  g_free(d);
187 	  return TRUE;
188      }
189 }
190 
floatbox_check_limit(Floatbox * box,float lowest,float highest,gchar * valuename)191 gboolean floatbox_check_limit(Floatbox *box, float lowest, float highest,
192 			      gchar *valuename)
193 {
194      gfloat f;
195      char *c,*d;
196      c=(char *)gtk_entry_get_text(GTK_ENTRY(box));
197      f=strtod(c,&d);
198      if (*d==0 && f >= lowest && f <= highest) {
199 	  floatbox_set(box,f);
200 	  return FALSE;
201      } else {
202 	  d = g_strdup_printf(_("Value for '%s' must be a number between %f and "
203 			      "%f"),valuename,lowest,highest);
204 	  user_error(d);
205 	  g_free(d);
206 	  return TRUE;
207      }
208 }
209 
210 
floatbox_adj_changed(GtkAdjustment * adjustment,gpointer user_data)211 static void floatbox_adj_changed(GtkAdjustment *adjustment, gpointer user_data)
212 {
213      Floatbox *box = FLOATBOX(user_data);
214      box->val = box->adj->value;
215      floatbox_update_text(box);
216      gtk_signal_emit(GTK_OBJECT(box),floatbox_signals[NUMCHANGED_SIGNAL],
217 		     box->val);
218 }
219 
floatbox_create_scale(Floatbox * box,float minval,float maxval)220 GtkWidget *floatbox_create_scale(Floatbox *box, float minval, float maxval)
221 {
222      GtkWidget *w;
223 #if GTK_MAJOR_VERSION > 1
224      GtkRequisition req;
225 #endif
226      if (box->adj == NULL) {
227 	  box->adj = GTK_ADJUSTMENT(gtk_adjustment_new(minval,minval,
228 						       maxval+
229 						       (maxval-minval)/10.0,
230 						       (maxval-minval)/100.0,
231 						       (maxval-minval)/4.0,
232 						       (maxval-minval)/10.0));
233 	  gtk_signal_connect(GTK_OBJECT(box->adj),"value_changed",
234 			     GTK_SIGNAL_FUNC(floatbox_adj_changed),box);
235 	  gtk_adjustment_set_value(box->adj,box->val);
236      }
237      w = gtk_hscale_new(box->adj);
238 #if GTK_MAJOR_VERSION > 1
239      gtk_widget_size_request(w,&req);
240      gtk_widget_set_usize(w,req.width*5,req.height);
241 #endif
242      return w;
243 }
244