1 /*
2 * Gnome Chemistry Utils
3 * programs/gchemtable-data-allocator.cc
4 *
5 * Copyright (C) 2007-2011 Jean Bréfort <jean.brefort@normalesup.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
21 */
22
23 #include "config.h"
24 #include "gchemtable-data-allocator.h"
25 #include "gchemtable-curve.h"
26 #include "gchemtable-data.h"
27 #include <gtk/gtk.h>
28 #include <gsf/gsf-impl-utils.h>
29 #include <glib/gi18n-lib.h>
30
31 struct _GctControlGUI
32 {
33 GObject base;
34 GChemTableCurve *pCurve;
35 };
36
37 //
38 // GogDataAllocator interface implementation for GChemTableCurve
39 //
40
41 static void
gct_data_allocator_allocate(G_GNUC_UNUSED GogDataAllocator * dalloc,G_GNUC_UNUSED GogPlot * plot)42 gct_data_allocator_allocate (G_GNUC_UNUSED GogDataAllocator *dalloc, G_GNUC_UNUSED GogPlot *plot)
43 {
44 // Nothing needed
45 }
46
47 static void
gct_data_editor_set_format(G_GNUC_UNUSED GogDataEditor * editor,G_GNUC_UNUSED GOFormat const * fmt)48 gct_data_editor_set_format (G_GNUC_UNUSED GogDataEditor *editor, G_GNUC_UNUSED GOFormat const *fmt)
49 {
50 }
51
52 static void
gct_data_editor_set_value_double(G_GNUC_UNUSED GogDataEditor * editor,G_GNUC_UNUSED double val,G_GNUC_UNUSED GODateConventions const * date_conv)53 gct_data_editor_set_value_double (G_GNUC_UNUSED GogDataEditor *editor, G_GNUC_UNUSED double val,
54 G_GNUC_UNUSED GODateConventions const *date_conv)
55 {
56 }
57
58 typedef GtkComboBoxText GctComboBox;
59 typedef GtkComboBoxTextClass GctComboBoxClass;
60
61 static void
gct_data_editor_iface_init(GogDataEditorClass * iface)62 gct_data_editor_iface_init (GogDataEditorClass *iface)
63 {
64 iface->set_format = gct_data_editor_set_format;
65 iface->set_value_double = gct_data_editor_set_value_double;
66 }
67
68 GSF_CLASS_FULL (GctComboBox, gct_combo_box,
69 NULL, NULL, NULL, NULL,
70 NULL, GTK_TYPE_COMBO_BOX_TEXT, 0,
71 GSF_INTERFACE (gct_data_editor_iface_init, GOG_TYPE_DATA_EDITOR))
72
gct_combo_box_new()73 GogDataEditor *gct_combo_box_new ()
74 {
75 return GOG_DATA_EDITOR (g_object_new (gct_combo_box_get_type (), NULL));
76 }
77
78 static void
gct_entry_set_value_double(GogDataEditor * editor,double val,G_GNUC_UNUSED GODateConventions const * date_conv)79 gct_entry_set_value_double (GogDataEditor *editor, double val,
80 G_GNUC_UNUSED GODateConventions const *date_conv)
81 {
82 GtkEntry *entry = GTK_ENTRY (editor);
83 char *buf = g_strdup_printf ("%g", val);
84 gtk_entry_set_text (entry, buf);
85 g_free (buf);
86 }
87
88 typedef GtkEntry GctEntry;
89 typedef GtkEntryClass GctEntryClass;
90
91 static void
gct_entry_iface_init(GogDataEditorClass * iface)92 gct_entry_iface_init (GogDataEditorClass *iface)
93 {
94 iface->set_format = gct_data_editor_set_format;
95 iface->set_value_double = gct_entry_set_value_double;
96 }
97
98 GSF_CLASS_FULL (GctEntry, gct_entry,
99 NULL, NULL, NULL, NULL,
100 NULL, GTK_TYPE_ENTRY, 0,
101 GSF_INTERFACE (gct_entry_iface_init, GOG_TYPE_DATA_EDITOR))
102
gct_entry_new()103 GogDataEditor *gct_entry_new ()
104 {
105 return GOG_DATA_EDITOR (g_object_new (gct_entry_get_type (), NULL));
106 }
107
108 typedef GtkLabel GctLabel;
109 typedef GtkLabelClass GctLabelClass;
110
111 GSF_CLASS_FULL (GctLabel, gct_label,
112 NULL, NULL, NULL, NULL,
113 NULL, GTK_TYPE_LABEL, 0,
114 GSF_INTERFACE (gct_data_editor_iface_init, GOG_TYPE_DATA_EDITOR))
115
gct_label_new(char const * label)116 GogDataEditor *gct_label_new (char const *label)
117 {
118 return GOG_DATA_EDITOR (g_object_new (gct_label_get_type (), "label", label, NULL));
119 }
120
121 typedef struct {
122 GogDataEditor *box;
123 GogDataset *dataset;
124 int dim_i;
125 GogDataType data_type;
126 } GraphDimEditor;
127
128 static void
on_graph_dim_editor_changed(GtkEntry * box,GraphDimEditor * editor)129 on_graph_dim_editor_changed (GtkEntry *box,
130 GraphDimEditor *editor)
131 {
132 bool sensitive = false;
133 g_object_get (G_OBJECT (box), "sensitive", &sensitive, NULL);
134 if (!sensitive || editor->dataset == NULL)
135 return;
136
137 GOData *data = go_data_scalar_str_new (g_strdup (gtk_entry_get_text (box)), TRUE);
138
139 if (!data) {
140 g_message (_("Invalid data"));
141 } else
142 gog_dataset_set_dim (editor->dataset, editor->dim_i, data, NULL);
143 }
144
145 static void
on_dim_editor_weakref_notify(GraphDimEditor * editor,GogDataset * dataset)146 on_dim_editor_weakref_notify (GraphDimEditor *editor, GogDataset *dataset)
147 {
148 g_return_if_fail (editor->dataset == dataset);
149 editor->dataset = NULL;
150 }
151
152 static void
graph_dim_editor_free(GraphDimEditor * editor)153 graph_dim_editor_free (GraphDimEditor *editor)
154 {
155 if (editor->dataset)
156 g_object_weak_unref (G_OBJECT (editor->dataset),
157 (GWeakNotify) on_dim_editor_weakref_notify, editor);
158 g_free (editor);
159 }
160
on_vector_data_changed(GtkComboBoxText * box,GraphDimEditor * editor)161 static void on_vector_data_changed (GtkComboBoxText *box, GraphDimEditor *editor)
162 {
163 char *name = gtk_combo_box_text_get_active_text (box);
164 GOData *data = gct_data_vector_get_from_name (name);
165 gog_dataset_set_dim (editor->dataset, editor->dim_i, data, NULL);
166 g_free (name);
167 }
168
169 static GogDataEditor *
gct_data_allocator_editor(G_GNUC_UNUSED GogDataAllocator * dalloc,GogDataset * dataset,int dim_i,GogDataType data_type)170 gct_data_allocator_editor (G_GNUC_UNUSED GogDataAllocator *dalloc,
171 GogDataset *dataset, int dim_i, GogDataType data_type)
172 {
173 GraphDimEditor *editor;
174
175 editor = g_new (GraphDimEditor, 1);
176 editor->dataset = dataset;
177 editor->dim_i = dim_i;
178 editor->data_type = data_type;
179
180 if (GOG_IS_SERIES (dataset) && data_type != GOG_DATA_SCALAR) {
181 GogPlot *plot = gog_series_get_plot (GOG_SERIES (dataset));
182 if (plot->desc.series.dim[dim_i].priority == GOG_SERIES_ERRORS) {
183 // FIXME: we might know the errors
184 editor->box = gct_label_new (_("Not supported"));
185 g_object_set_data_full (G_OBJECT (editor->box),
186 "editor", editor, (GDestroyNotify) graph_dim_editor_free);
187 return editor->box;
188 }
189 editor->box = GOG_DATA_EDITOR (gct_combo_box_new ());
190 GOData *data = gog_dataset_get_dim (dataset, dim_i), *cur;
191 int i = 1, sel = 0;
192 GtkComboBoxText *box = GTK_COMBO_BOX_TEXT (editor->box);
193 gtk_combo_box_text_append_text (box, _("None"));
194 if (data_type == GOG_DATA_VECTOR) {
195 void *closure = NULL;
196 char const *entry = gct_data_vector_get_first (&cur, &closure);
197 while (entry) {
198 gtk_combo_box_text_append_text (box, entry);
199 if (cur == data)
200 sel = i;
201 i++;
202 g_object_unref (cur);
203 entry = gct_data_vector_get_next (&cur, &closure);
204 };
205 }
206 gtk_combo_box_set_active (GTK_COMBO_BOX (box), sel);
207 g_signal_connect (G_OBJECT (editor->box), "changed",
208 G_CALLBACK (on_vector_data_changed), editor);
209 // FIXME: what about matrices?
210 } else {
211 editor->box = GOG_DATA_EDITOR (gct_entry_new ());
212 GOData *val = gog_dataset_get_dim (dataset, dim_i);
213 if (val != NULL) {
214 char *txt = go_data_serialize (val, NULL);
215 gtk_entry_set_text (GTK_ENTRY (editor->box), txt);
216 g_free (txt);
217 }
218
219 g_signal_connect (G_OBJECT (editor->box),
220 "changed",
221 G_CALLBACK (on_graph_dim_editor_changed), editor);
222 }
223 g_object_weak_ref (G_OBJECT (editor->dataset),
224 (GWeakNotify) on_dim_editor_weakref_notify, editor);
225
226 g_object_set_data_full (G_OBJECT (editor->box),
227 "editor", editor, (GDestroyNotify) graph_dim_editor_free);
228
229 return editor->box;
230 }
231
232 static void
gct_go_plot_data_allocator_init(GogDataAllocatorClass * iface)233 gct_go_plot_data_allocator_init (GogDataAllocatorClass *iface)
234 {
235 iface->allocate = gct_data_allocator_allocate;
236 iface->editor = gct_data_allocator_editor;
237 }
238
239 static void
gct_control_gui_init(G_GNUC_UNUSED GObject * object)240 gct_control_gui_init (G_GNUC_UNUSED GObject *object)
241 {
242 }
243
244 static GObjectClass *parent_klass;
245
246 static void
gct_control_gui_finalize(GObject * object)247 gct_control_gui_finalize (GObject *object)
248 {
249 // GctControlGUI *control = GCT_CONTROL_GUI (object);
250 (parent_klass->finalize) (object);
251 }
252
253 static void
gct_control_gui_class_init(GObjectClass * klass)254 gct_control_gui_class_init (GObjectClass *klass)
255 {
256 parent_klass = static_cast<GObjectClass*> (g_type_class_peek_parent (klass));
257 klass->finalize = gct_control_gui_finalize;
258 }
259
260 GSF_CLASS_FULL (GctControlGUI, gct_control_gui,
261 NULL, NULL, gct_control_gui_class_init, NULL,
262 gct_control_gui_init, G_TYPE_OBJECT, 0,
263 GSF_INTERFACE (gct_go_plot_data_allocator_init, GOG_TYPE_DATA_ALLOCATOR));
264
265 void
gct_control_gui_set_owner(GctControlGUI * gui,GChemTableCurve * curve)266 gct_control_gui_set_owner (GctControlGUI *gui, GChemTableCurve *curve)
267 {
268 gui->pCurve = curve;
269 }
270
271 GChemTableCurve *
gct_control_gui_get_owner(GctControlGUI * gui)272 gct_control_gui_get_owner (GctControlGUI *gui)
273 {
274 return gui->pCurve;
275 }
276