Changed mind about translating short currency names, instead use the full name in...
[gcalctool.git] / src / math-variable-popup.c
blobf9d149b04554f87c0a28e2e3a4ce441f44e61a25
1 /* Copyright (c) 2008-2009 Robert Ancell
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16 * 02111-1307, USA.
19 #include <glib/gi18n.h>
20 #include <gdk/gdkkeysyms.h>
22 #include "math-variable-popup.h"
24 enum {
25 PROP_0,
26 PROP_EQUATION
29 struct MathVariablePopupPrivate
31 MathEquation *equation;
33 GtkWidget *vbox;
34 GtkWidget *variable_name_entry;
35 GtkWidget *add_variable_button;
38 G_DEFINE_TYPE (MathVariablePopup, math_variable_popup, GTK_TYPE_WINDOW);
40 MathVariablePopup *
41 math_variable_popup_new(MathEquation *equation)
43 return g_object_new(math_variable_popup_get_type(), "equation", equation, NULL);
47 static void
48 variable_focus_out_event_cb(GtkWidget *widget, GdkEventFocus *event, MathVariablePopup *popup)
50 gtk_widget_destroy(widget);
54 static void
55 insert_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
57 const gchar *name;
59 name = g_object_get_data(G_OBJECT(widget), "variable_name");
60 math_equation_insert(popup->priv->equation, name);
62 gtk_widget_destroy(gtk_widget_get_toplevel(widget));
66 static gboolean
67 variable_name_key_press_cb(GtkWidget *widget, GdkEventKey *event, MathVariablePopup *popup)
69 /* Can't have whitespace in names, so replace with underscores */
70 if (event->keyval == GDK_KEY_space || event->keyval == GDK_KEY_KP_Space)
71 event->keyval = GDK_KEY_underscore;
73 return FALSE;
77 static void
78 variable_name_changed_cb(GtkWidget *widget, MathVariablePopup *popup)
80 const gchar *text = gtk_entry_get_text(GTK_ENTRY(popup->priv->variable_name_entry));
81 gtk_widget_set_sensitive(popup->priv->add_variable_button, text[0] != '\0');
85 static void
86 add_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
88 const gchar *name;
89 MPNumber z;
91 name = gtk_entry_get_text(GTK_ENTRY(popup->priv->variable_name_entry));
92 if (name[0] == '\0')
93 return;
95 if (math_equation_get_number(popup->priv->equation, &z))
96 math_variables_set(math_equation_get_variables(popup->priv->equation), name, &z);
97 else if (math_equation_is_result(popup->priv->equation))
98 math_variables_set(math_equation_get_variables(popup->priv->equation), name, math_equation_get_answer(popup->priv->equation));
99 else
100 g_warning("Can't add variable %s, the display is not a number", name);
102 gtk_widget_destroy(gtk_widget_get_toplevel(widget));
106 static void
107 save_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
109 const gchar *name;
110 MPNumber z;
112 name = g_object_get_data(G_OBJECT(widget), "variable_name");
113 if (math_equation_get_number(popup->priv->equation, &z))
114 math_variables_set(math_equation_get_variables(popup->priv->equation), name, &z);
115 else if (math_equation_is_result(popup->priv->equation))
116 math_variables_set(math_equation_get_variables(popup->priv->equation), name, math_equation_get_answer(popup->priv->equation));
117 else
118 g_warning("Can't save variable %s, the display is not a number", name);
120 gtk_widget_destroy(gtk_widget_get_toplevel(widget));
124 static void
125 delete_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
127 const gchar *name;
129 name = g_object_get_data(G_OBJECT(widget), "variable_name");
130 math_variables_delete(math_equation_get_variables(popup->priv->equation), name);
132 gtk_widget_destroy(gtk_widget_get_toplevel(widget));
136 static GtkWidget *
137 make_variable_entry(MathVariablePopup *popup, const gchar *name, const MPNumber *value, gboolean writable)
139 GtkWidget *hbox, *button, *label;
140 gchar *text;
142 hbox = gtk_hbox_new(FALSE, 6);
144 if (value)
146 gchar *value_text = mp_serializer_to_string(math_equation_get_serializer(popup->priv->equation), value);
147 text = g_strdup_printf("<b>%s</b> = %s", name, value_text);
148 g_free (value_text);
150 else
151 text = g_strdup_printf("<b>%s</b>", name);
153 button = gtk_button_new();
154 g_object_set_data(G_OBJECT(button), "variable_name", g_strdup(name)); // FIXME: These will all leak memory
155 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_variable_cb), popup);
156 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
157 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
158 gtk_widget_show(button);
160 label = gtk_label_new(text);
161 g_free(text);
162 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
163 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
164 gtk_container_add(GTK_CONTAINER(button), label);
165 gtk_widget_show(label);
167 if (writable)
169 GtkWidget *image;
171 button = gtk_button_new();
172 g_object_set_data(G_OBJECT(button), "variable_name", g_strdup(name));
173 image = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_BUTTON);
174 gtk_container_add(GTK_CONTAINER(button), image);
175 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, TRUE, 0);
176 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_variable_cb), popup);
177 gtk_widget_show(image);
178 gtk_widget_show(button);
180 button = gtk_button_new();
181 g_object_set_data(G_OBJECT(button), "variable_name", g_strdup(name));
182 image = gtk_image_new_from_stock(GTK_STOCK_DELETE, GTK_ICON_SIZE_BUTTON);
183 gtk_container_add(GTK_CONTAINER(button), image);
184 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, TRUE, 0);
185 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(delete_variable_cb), popup);
186 gtk_widget_show(image);
187 gtk_widget_show(button);
190 return hbox;
194 static void
195 math_variable_popup_set_property(GObject *object,
196 guint prop_id,
197 const GValue *value,
198 GParamSpec *pspec)
200 MathVariablePopup *self;
201 gchar **names;
202 int i;
203 GtkWidget *entry, *image;
205 self = MATH_VARIABLE_POPUP(object);
207 switch (prop_id) {
208 case PROP_EQUATION:
209 self->priv->equation = g_value_get_object(value);
211 names = math_variables_get_names(math_equation_get_variables(self->priv->equation));
212 for (i = 0; names[i]; i++) {
213 MPNumber *value;
215 value = math_variables_get(math_equation_get_variables(self->priv->equation), names[i]);
216 entry = make_variable_entry(self, names[i], value, TRUE);
217 gtk_widget_show(entry);
218 gtk_box_pack_start(GTK_BOX(self->priv->vbox), entry, FALSE, TRUE, 0);
220 g_strfreev(names);
222 entry = gtk_hbox_new(FALSE, 6);
223 gtk_widget_show(entry);
225 // TODO: Show greyed "variable name" text to give user a hint how to use
226 self->priv->variable_name_entry = gtk_entry_new();
227 g_signal_connect(G_OBJECT(self->priv->variable_name_entry), "key-press-event", G_CALLBACK(variable_name_key_press_cb), self);
228 g_signal_connect(G_OBJECT(self->priv->variable_name_entry), "changed", G_CALLBACK(variable_name_changed_cb), self);
229 g_signal_connect(G_OBJECT(self->priv->variable_name_entry), "activate", G_CALLBACK(add_variable_cb), self);
230 gtk_box_pack_start(GTK_BOX(entry), self->priv->variable_name_entry, TRUE, TRUE, 0);
231 gtk_widget_show(self->priv->variable_name_entry);
233 self->priv->add_variable_button = gtk_button_new();
234 gtk_widget_set_sensitive(self->priv->add_variable_button, FALSE);
235 g_signal_connect(G_OBJECT(self->priv->add_variable_button), "clicked", G_CALLBACK(add_variable_cb), self);
236 image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
237 gtk_container_add(GTK_CONTAINER(self->priv->add_variable_button), image);
238 gtk_box_pack_start(GTK_BOX(entry), self->priv->add_variable_button, FALSE, TRUE, 0);
239 gtk_widget_show(image);
240 gtk_widget_show(self->priv->add_variable_button);
241 gtk_box_pack_end(GTK_BOX(self->priv->vbox), entry, FALSE, TRUE, 0);
243 entry = make_variable_entry(self, "rand", NULL, FALSE);
244 gtk_widget_show(entry);
245 gtk_box_pack_end(GTK_BOX(self->priv->vbox), entry, FALSE, TRUE, 0);
247 entry = make_variable_entry(self, "ans", math_equation_get_answer(self->priv->equation), FALSE);
248 gtk_widget_show(entry);
249 gtk_box_pack_end(GTK_BOX(self->priv->vbox), entry, FALSE, TRUE, 0);
250 break;
251 default:
252 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
253 break;
258 static void
259 math_variable_popup_get_property(GObject *object,
260 guint prop_id,
261 GValue *value,
262 GParamSpec *pspec)
264 MathVariablePopup *self;
266 self = MATH_VARIABLE_POPUP(object);
268 switch (prop_id) {
269 case PROP_EQUATION:
270 g_value_set_object(value, self->priv->equation);
271 break;
272 default:
273 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
274 break;
279 static void
280 math_variable_popup_class_init(MathVariablePopupClass *klass)
282 GObjectClass *object_class = G_OBJECT_CLASS(klass);
284 object_class->get_property = math_variable_popup_get_property;
285 object_class->set_property = math_variable_popup_set_property;
287 g_type_class_add_private(klass, sizeof(MathVariablePopupPrivate));
289 g_object_class_install_property(object_class,
290 PROP_EQUATION,
291 g_param_spec_object("equation",
292 "equation",
293 "Equation being controlled",
294 math_equation_get_type(),
295 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
299 static void
300 math_variable_popup_init(MathVariablePopup *popup)
302 popup->priv = G_TYPE_INSTANCE_GET_PRIVATE(popup, math_variable_popup_get_type(), MathVariablePopupPrivate);
304 gtk_window_set_decorated(GTK_WINDOW(popup), FALSE);
305 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(popup), TRUE);
307 gtk_container_set_border_width(GTK_CONTAINER(popup), 6);
309 /* Destroy this window when it loses focus */
310 g_signal_connect(G_OBJECT(popup), "focus-out-event", G_CALLBACK(variable_focus_out_event_cb), popup);
312 popup->priv->vbox = gtk_vbox_new(TRUE, 6);
313 gtk_container_add(GTK_CONTAINER(popup), popup->priv->vbox);
314 gtk_widget_show(popup->priv->vbox);