~registry/gcalctool/trunk

« back to all changes in this revision

Viewing changes to src/math-variable-popup.c

  • Committer: Robert Ancell
  • Date: 2012-10-14 03:31:40 UTC
  • Revision ID: git-v1:12ba2c81b0a81bb3ac776d1034a3c41b3173196a
Port to Vala

https://bugzilla.gnome.org/show_bug.cgi?id=640685

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2008-2011 Robert Ancell
3
 
 *
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
8
 
 * license.
9
 
 */
10
 
 
11
 
#include <glib/gi18n.h>
12
 
#include <gdk/gdkkeysyms.h>
13
 
 
14
 
#include "math-variable-popup.h"
15
 
 
16
 
enum {
17
 
    PROP_0,
18
 
    PROP_EQUATION
19
 
};
20
 
 
21
 
struct MathVariablePopupPrivate
22
 
{
23
 
    MathEquation *equation;
24
 
 
25
 
    GtkWidget *vbox;
26
 
    GtkWidget *variable_name_entry;
27
 
    GtkWidget *add_variable_button;
28
 
};
29
 
 
30
 
G_DEFINE_TYPE (MathVariablePopup, math_variable_popup, GTK_TYPE_WINDOW);
31
 
 
32
 
MathVariablePopup *
33
 
math_variable_popup_new(MathEquation *equation)
34
 
{
35
 
    return g_object_new(math_variable_popup_get_type(), "equation", equation, NULL);
36
 
}
37
 
 
38
 
 
39
 
static void
40
 
variable_focus_out_event_cb(GtkWidget *widget, GdkEventFocus *event, MathVariablePopup *popup)
41
 
{
42
 
    gtk_widget_destroy(widget);
43
 
}
44
 
 
45
 
 
46
 
static void
47
 
insert_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
48
 
{
49
 
    const gchar *name;
50
 
 
51
 
    name = g_object_get_data(G_OBJECT(widget), "variable_name");
52
 
    math_equation_insert(popup->priv->equation, name);
53
 
 
54
 
    gtk_widget_destroy(gtk_widget_get_toplevel(widget));
55
 
}
56
 
 
57
 
 
58
 
static gboolean
59
 
variable_name_key_press_cb(GtkWidget *widget, GdkEventKey *event, MathVariablePopup *popup)
60
 
{
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;
64
 
 
65
 
    return FALSE;
66
 
}
67
 
 
68
 
 
69
 
static void
70
 
variable_name_changed_cb(GtkWidget *widget, MathVariablePopup *popup)
71
 
{
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');
74
 
}
75
 
                         
76
 
 
77
 
static void
78
 
add_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
79
 
{
80
 
    const gchar *name;
81
 
    MPNumber z;
82
 
 
83
 
    name = gtk_entry_get_text(GTK_ENTRY(popup->priv->variable_name_entry));
84
 
    if (name[0] == '\0')
85
 
        return;
86
 
 
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));
91
 
    else
92
 
        g_warning("Can't add variable %s, the display is not a number", name);
93
 
 
94
 
    gtk_widget_destroy(gtk_widget_get_toplevel(widget));
95
 
}
96
 
 
97
 
 
98
 
static void
99
 
save_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
100
 
{
101
 
    const gchar *name;
102
 
    MPNumber z;
103
 
 
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));
109
 
    else
110
 
        g_warning("Can't save variable %s, the display is not a number", name);
111
 
 
112
 
    gtk_widget_destroy(gtk_widget_get_toplevel(widget));
113
 
}
114
 
 
115
 
 
116
 
static void
117
 
delete_variable_cb(GtkWidget *widget, MathVariablePopup *popup)
118
 
{
119
 
    const gchar *name;
120
 
 
121
 
    name = g_object_get_data(G_OBJECT(widget), "variable_name");  
122
 
    math_variables_delete(math_equation_get_variables(popup->priv->equation), name);
123
 
 
124
 
    gtk_widget_destroy(gtk_widget_get_toplevel(widget));
125
 
}
126
 
 
127
 
 
128
 
static GtkWidget *
129
 
make_variable_entry(MathVariablePopup *popup, const gchar *name, const MPNumber *value, gboolean writable)
130
 
{
131
 
    GtkWidget *hbox, *button, *label;
132
 
    gchar *text;
133
 
 
134
 
    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
135
 
 
136
 
    if (value)
137
 
    {
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);
140
 
        g_free (value_text);
141
 
    }
142
 
    else
143
 
        text = g_strdup_printf("<b>%s</b>", name);
144
 
 
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);
151
 
 
152
 
    label = gtk_label_new(text);
153
 
    g_free(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);
158
 
 
159
 
    if (writable)
160
 
    {
161
 
        GtkWidget *image;
162
 
 
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);
171
 
 
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);
180
 
    }
181
 
 
182
 
    return hbox;
183
 
}
184
 
 
185
 
 
186
 
static void
187
 
math_variable_popup_set_property(GObject      *object,
188
 
                                 guint         prop_id,
189
 
                                 const GValue *value,
190
 
                                 GParamSpec   *pspec)
191
 
{
192
 
    MathVariablePopup *self;
193
 
    gchar **names;
194
 
    int i;
195
 
    GtkWidget *entry, *image;
196
 
 
197
 
    self = MATH_VARIABLE_POPUP(object);
198
 
 
199
 
    switch (prop_id) {
200
 
    case PROP_EQUATION:
201
 
        self->priv->equation = g_value_get_object(value);
202
 
 
203
 
        names = math_variables_get_names(math_equation_get_variables(self->priv->equation));
204
 
        for (i = 0; names[i]; i++) {
205
 
            MPNumber *value;
206
 
 
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);
211
 
        }
212
 
        g_strfreev(names);
213
 
 
214
 
        entry = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
215
 
        gtk_widget_show(entry);
216
 
 
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);
224
 
 
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);
234
 
 
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);
238
 
 
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);
242
 
        break;
243
 
    default:
244
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
245
 
        break;
246
 
    }
247
 
}
248
 
 
249
 
 
250
 
static void
251
 
math_variable_popup_get_property(GObject    *object,
252
 
                                 guint       prop_id,
253
 
                                 GValue     *value,
254
 
                                 GParamSpec *pspec)
255
 
{
256
 
    MathVariablePopup *self;
257
 
 
258
 
    self = MATH_VARIABLE_POPUP(object);
259
 
 
260
 
    switch (prop_id) {
261
 
    case PROP_EQUATION:
262
 
        g_value_set_object(value, self->priv->equation);
263
 
        break;
264
 
    default:
265
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
266
 
        break;
267
 
    }
268
 
}
269
 
 
270
 
 
271
 
static void
272
 
math_variable_popup_class_init(MathVariablePopupClass *klass)
273
 
{
274
 
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
275
 
 
276
 
    object_class->get_property = math_variable_popup_get_property;
277
 
    object_class->set_property = math_variable_popup_set_property;
278
 
 
279
 
    g_type_class_add_private(klass, sizeof(MathVariablePopupPrivate));
280
 
 
281
 
    g_object_class_install_property(object_class,
282
 
                                    PROP_EQUATION,
283
 
                                    g_param_spec_object("equation",
284
 
                                                        "equation",
285
 
                                                        "Equation being controlled",
286
 
                                                        math_equation_get_type(),
287
 
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
288
 
}
289
 
 
290
 
 
291
 
static void
292
 
math_variable_popup_init(MathVariablePopup *popup)
293
 
{
294
 
    popup->priv = G_TYPE_INSTANCE_GET_PRIVATE(popup, math_variable_popup_get_type(), MathVariablePopupPrivate);
295
 
 
296
 
    gtk_window_set_decorated(GTK_WINDOW(popup), FALSE);
297
 
    gtk_window_set_skip_taskbar_hint(GTK_WINDOW(popup), TRUE);
298
 
 
299
 
    gtk_container_set_border_width(GTK_CONTAINER(popup), 6);
300
 
 
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);
303
 
 
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);
308
 
}