2 * Copyright (C) 2008-2011 Robert Ancell
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 2 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
11 #include <glib/gi18n.h>
12 #include <gdk/gdkkeysyms.h>
14 #include "math-variable-popup.h"
21 struct MathVariablePopupPrivate
23 MathEquation
*equation
;
26 GtkWidget
*variable_name_entry
;
27 GtkWidget
*add_variable_button
;
30 G_DEFINE_TYPE (MathVariablePopup
, math_variable_popup
, GTK_TYPE_WINDOW
);
33 math_variable_popup_new(MathEquation
*equation
)
35 return g_object_new(math_variable_popup_get_type(), "equation", equation
, NULL
);
40 variable_focus_out_event_cb(GtkWidget
*widget
, GdkEventFocus
*event
, MathVariablePopup
*popup
)
42 gtk_widget_destroy(widget
);
47 insert_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
51 name
= g_object_get_data(G_OBJECT(widget
), "variable_name");
52 math_equation_insert(popup
->priv
->equation
, name
);
54 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
59 variable_name_key_press_cb(GtkWidget
*widget
, GdkEventKey
*event
, MathVariablePopup
*popup
)
61 /* Can't have whitespace in names, so replace with underscores */
62 if (event
->keyval
== GDK_KEY_space
|| event
->keyval
== GDK_KEY_KP_Space
)
63 event
->keyval
= GDK_KEY_underscore
;
70 variable_name_changed_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
72 const gchar
*text
= gtk_entry_get_text(GTK_ENTRY(popup
->priv
->variable_name_entry
));
73 gtk_widget_set_sensitive(popup
->priv
->add_variable_button
, text
[0] != '\0');
78 add_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
83 name
= gtk_entry_get_text(GTK_ENTRY(popup
->priv
->variable_name_entry
));
87 if (math_equation_get_number(popup
->priv
->equation
, &z
))
88 math_variables_set(math_equation_get_variables(popup
->priv
->equation
), name
, &z
);
89 else if (math_equation_is_result(popup
->priv
->equation
))
90 math_variables_set(math_equation_get_variables(popup
->priv
->equation
), name
, math_equation_get_answer(popup
->priv
->equation
));
92 g_warning("Can't add variable %s, the display is not a number", name
);
94 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
99 save_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
104 name
= g_object_get_data(G_OBJECT(widget
), "variable_name");
105 if (math_equation_get_number(popup
->priv
->equation
, &z
))
106 math_variables_set(math_equation_get_variables(popup
->priv
->equation
), name
, &z
);
107 else if (math_equation_is_result(popup
->priv
->equation
))
108 math_variables_set(math_equation_get_variables(popup
->priv
->equation
), name
, math_equation_get_answer(popup
->priv
->equation
));
110 g_warning("Can't save variable %s, the display is not a number", name
);
112 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
117 delete_variable_cb(GtkWidget
*widget
, MathVariablePopup
*popup
)
121 name
= g_object_get_data(G_OBJECT(widget
), "variable_name");
122 math_variables_delete(math_equation_get_variables(popup
->priv
->equation
), name
);
124 gtk_widget_destroy(gtk_widget_get_toplevel(widget
));
129 make_variable_entry(MathVariablePopup
*popup
, const gchar
*name
, const MPNumber
*value
, gboolean writable
)
131 GtkWidget
*hbox
, *button
, *label
;
134 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6);
138 gchar
*value_text
= mp_serializer_to_string(math_equation_get_serializer(popup
->priv
->equation
), value
);
139 text
= g_strdup_printf("<b>%s</b> = %s", name
, value_text
);
143 text
= g_strdup_printf("<b>%s</b>", name
);
145 button
= gtk_button_new();
146 g_object_set_data(G_OBJECT(button
), "variable_name", g_strdup(name
)); // FIXME: These will all leak memory
147 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(insert_variable_cb
), popup
);
148 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
149 gtk_box_pack_start(GTK_BOX(hbox
), button
, TRUE
, TRUE
, 0);
150 gtk_widget_show(button
);
152 label
= gtk_label_new(text
);
154 gtk_label_set_use_markup(GTK_LABEL(label
), TRUE
);
155 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
156 gtk_container_add(GTK_CONTAINER(button
), label
);
157 gtk_widget_show(label
);
163 button
= gtk_button_new();
164 g_object_set_data(G_OBJECT(button
), "variable_name", g_strdup(name
));
165 image
= gtk_image_new_from_stock(GTK_STOCK_SAVE
, GTK_ICON_SIZE_BUTTON
);
166 gtk_container_add(GTK_CONTAINER(button
), image
);
167 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
168 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(save_variable_cb
), popup
);
169 gtk_widget_show(image
);
170 gtk_widget_show(button
);
172 button
= gtk_button_new();
173 g_object_set_data(G_OBJECT(button
), "variable_name", g_strdup(name
));
174 image
= gtk_image_new_from_stock(GTK_STOCK_DELETE
, GTK_ICON_SIZE_BUTTON
);
175 gtk_container_add(GTK_CONTAINER(button
), image
);
176 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
177 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(delete_variable_cb
), popup
);
178 gtk_widget_show(image
);
179 gtk_widget_show(button
);
187 math_variable_popup_set_property(GObject
*object
,
192 MathVariablePopup
*self
;
195 GtkWidget
*entry
, *image
;
197 self
= MATH_VARIABLE_POPUP(object
);
201 self
->priv
->equation
= g_value_get_object(value
);
203 names
= math_variables_get_names(math_equation_get_variables(self
->priv
->equation
));
204 for (i
= 0; names
[i
]; i
++) {
207 value
= math_variables_get(math_equation_get_variables(self
->priv
->equation
), names
[i
]);
208 entry
= make_variable_entry(self
, names
[i
], value
, TRUE
);
209 gtk_widget_show(entry
);
210 gtk_box_pack_start(GTK_BOX(self
->priv
->vbox
), entry
, FALSE
, TRUE
, 0);
214 entry
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 6);
215 gtk_widget_show(entry
);
217 // TODO: Show greyed "variable name" text to give user a hint how to use
218 self
->priv
->variable_name_entry
= gtk_entry_new();
219 g_signal_connect(G_OBJECT(self
->priv
->variable_name_entry
), "key-press-event", G_CALLBACK(variable_name_key_press_cb
), self
);
220 g_signal_connect(G_OBJECT(self
->priv
->variable_name_entry
), "changed", G_CALLBACK(variable_name_changed_cb
), self
);
221 g_signal_connect(G_OBJECT(self
->priv
->variable_name_entry
), "activate", G_CALLBACK(add_variable_cb
), self
);
222 gtk_box_pack_start(GTK_BOX(entry
), self
->priv
->variable_name_entry
, TRUE
, TRUE
, 0);
223 gtk_widget_show(self
->priv
->variable_name_entry
);
225 self
->priv
->add_variable_button
= gtk_button_new();
226 gtk_widget_set_sensitive(self
->priv
->add_variable_button
, FALSE
);
227 g_signal_connect(G_OBJECT(self
->priv
->add_variable_button
), "clicked", G_CALLBACK(add_variable_cb
), self
);
228 image
= gtk_image_new_from_stock(GTK_STOCK_ADD
, GTK_ICON_SIZE_BUTTON
);
229 gtk_container_add(GTK_CONTAINER(self
->priv
->add_variable_button
), image
);
230 gtk_box_pack_start(GTK_BOX(entry
), self
->priv
->add_variable_button
, FALSE
, TRUE
, 0);
231 gtk_widget_show(image
);
232 gtk_widget_show(self
->priv
->add_variable_button
);
233 gtk_box_pack_end(GTK_BOX(self
->priv
->vbox
), entry
, FALSE
, TRUE
, 0);
235 entry
= make_variable_entry(self
, "rand", NULL
, FALSE
);
236 gtk_widget_show(entry
);
237 gtk_box_pack_end(GTK_BOX(self
->priv
->vbox
), entry
, FALSE
, TRUE
, 0);
239 entry
= make_variable_entry(self
, "ans", math_equation_get_answer(self
->priv
->equation
), FALSE
);
240 gtk_widget_show(entry
);
241 gtk_box_pack_end(GTK_BOX(self
->priv
->vbox
), entry
, FALSE
, TRUE
, 0);
244 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
251 math_variable_popup_get_property(GObject
*object
,
256 MathVariablePopup
*self
;
258 self
= MATH_VARIABLE_POPUP(object
);
262 g_value_set_object(value
, self
->priv
->equation
);
265 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
272 math_variable_popup_class_init(MathVariablePopupClass
*klass
)
274 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
276 object_class
->get_property
= math_variable_popup_get_property
;
277 object_class
->set_property
= math_variable_popup_set_property
;
279 g_type_class_add_private(klass
, sizeof(MathVariablePopupPrivate
));
281 g_object_class_install_property(object_class
,
283 g_param_spec_object("equation",
285 "Equation being controlled",
286 math_equation_get_type(),
287 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
292 math_variable_popup_init(MathVariablePopup
*popup
)
294 popup
->priv
= G_TYPE_INSTANCE_GET_PRIVATE(popup
, math_variable_popup_get_type(), MathVariablePopupPrivate
);
296 gtk_window_set_decorated(GTK_WINDOW(popup
), FALSE
);
297 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(popup
), TRUE
);
299 gtk_container_set_border_width(GTK_CONTAINER(popup
), 6);
301 /* Destroy this window when it loses focus */
302 g_signal_connect(G_OBJECT(popup
), "focus-out-event", G_CALLBACK(variable_focus_out_event_cb
), popup
);
304 popup
->priv
->vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 6);
305 gtk_box_set_homogeneous(GTK_BOX(popup
->priv
->vbox
), TRUE
);
306 gtk_container_add(GTK_CONTAINER(popup
), popup
->priv
->vbox
);
307 gtk_widget_show(popup
->priv
->vbox
);