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)
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
19 #include <glib/gi18n.h>
20 #include <gdk/gdkkeysyms.h>
22 #include "math-variable-popup.h"
29 struct MathVariablePopupPrivate
31 MathEquation
*equation
;
34 GtkWidget
*variable_name_entry
;
35 GtkWidget
*add_variable_button
;
38 G_DEFINE_TYPE (MathVariablePopup
, math_variable_popup
, GTK_TYPE_WINDOW
);
41 math_variable_popup_new(MathEquation
*equation
)
43 return g_object_new(math_variable_popup_get_type(), "equation", equation
, NULL
);
48 variable_focus_out_event_cb(GtkWidget
*widget
, GdkEventFocus
*event
, MathVariablePopup
*popup
)
50 gtk_widget_destroy(widget
);
55 insert_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
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
));
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
;
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');
86 add_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
91 name
= gtk_entry_get_text(GTK_ENTRY(popup
->priv
->variable_name_entry
));
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
));
100 g_warning("Can't add variable %s, the display is not a number", name
);
102 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
107 save_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
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
));
118 g_warning("Can't save variable %s, the display is not a number", name
);
120 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
125 delete_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
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
));
137 make_variable_entry(MathVariablePopup
*popup
, const gchar
*name
, const MPNumber
*value
, gboolean writable
)
139 GtkWidget
*hbox
, *button
, *label
;
142 hbox
= gtk_hbox_new(FALSE
, 6);
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
);
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
);
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
);
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
);
195 math_variable_popup_set_property(GObject
*object
,
200 MathVariablePopup
*self
;
203 GtkWidget
*entry
, *image
;
205 self
= MATH_VARIABLE_POPUP(object
);
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
++) {
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);
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);
252 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
259 math_variable_popup_get_property(GObject
*object
,
264 MathVariablePopup
*self
;
266 self
= MATH_VARIABLE_POPUP(object
);
270 g_value_set_object(value
, self
->priv
->equation
);
273 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
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
,
291 g_param_spec_object("equation",
293 "Equation being controlled",
294 math_equation_get_type(),
295 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
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
);