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