1 /*
2  * Gnome Chemisty Utils
3  * spectrumview.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 "spectrumdoc.h"
25 #include "spectrumview.h"
26 #include <gsf/gsf-output-gio.h>
27 #include <glib/gi18n-lib.h>
28 #include <cmath>
29 #include <map>
30 #include <string>
31 
32 using namespace std;
33 
34 namespace gcugtk
35 {
36 
37 class SpectrumViewPrivate
38 {
39 public:
40 	static void OnSize (GtkWidget* w, GtkAllocation *allocation, SpectrumView *view);
41 };
42 
OnSize(G_GNUC_UNUSED GtkWidget * w,GtkAllocation * allocation,SpectrumView * view)43 void SpectrumViewPrivate::OnSize (G_GNUC_UNUSED GtkWidget* w, GtkAllocation *allocation, SpectrumView *view)
44 {
45 	view->m_Width = allocation->width;
46 	view->m_Height = allocation->height;
47 }
48 
on_min_changed(SpectrumView * view)49 static void on_min_changed (SpectrumView *view)
50 {
51 	view->OnMinChanged ();
52 }
53 
on_max_changed(SpectrumView * view)54 static void on_max_changed (SpectrumView *view)
55 {
56 	view->OnMaxChanged ();
57 }
58 
on_ymin_changed(SpectrumView * view)59 static void on_ymin_changed (SpectrumView *view)
60 {
61 	view->OnYMinChanged ();
62 }
63 
on_ymax_changed(SpectrumView * view)64 static void on_ymax_changed (SpectrumView *view)
65 {
66 	view->OnYMaxChanged();
67 }
68 
on_xrange_changed(SpectrumView * view)69 static void on_xrange_changed (SpectrumView *view)
70 {
71 	view->OnXRangeChanged ();
72 }
73 
on_yrange_changed(SpectrumView * view)74 static void on_yrange_changed (SpectrumView *view)
75 {
76 	view->OnYRangeChanged ();
77 }
78 
SpectrumView(SpectrumDocument * pDoc)79 SpectrumView::SpectrumView (SpectrumDocument *pDoc)
80 {
81 	m_Doc = pDoc;
82 	m_Widget = go_graph_widget_new (NULL);
83 	g_signal_connect (G_OBJECT (m_Widget), "size_allocate", G_CALLBACK (SpectrumViewPrivate::OnSize), this);
84 	GogGraph *graph = go_graph_widget_get_graph (GO_GRAPH_WIDGET (m_Widget));
85 	/* Add a title */
86 	GogLabel *label = (GogLabel *) g_object_new (GOG_TYPE_LABEL, NULL);
87 	gog_object_add_by_name (GOG_OBJECT (graph), "Title", GOG_OBJECT (label));
88 	/* Get the chart created by the widget initialization */
89 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
90 	/* Create a scatter plot and add it to the chart */
91 	GogPlot *plot = (GogPlot *) gog_plot_new_by_name ("GogXYPlot");
92 	g_object_set (plot, "default-style-has-markers", false, NULL);
93 	gog_object_add_by_name (GOG_OBJECT (chart), "Plot", GOG_OBJECT (plot));
94 	/* Create a series for the plot */
95 	m_Series = gog_plot_new_series (plot);
96 	m_OptionBox = gtk_grid_new ();
97 	g_object_set (G_OBJECT (m_OptionBox),
98 	              "orientation", GTK_ORIENTATION_VERTICAL,
99 	              "margin-left", 6,
100 	              "margin-top", 6,
101 	              "margin-right", 6,
102 	              NULL);
103 	GtkGrid *grid = GTK_GRID (m_OptionBox);
104 	if (!gtk_check_version (3, 2, 0)) {
105 		gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
106 		gtk_grid_set_row_spacing (grid, 6);
107 	} else {
108 		gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
109 		gtk_grid_set_row_spacing (grid, 6);
110 	}
111 	GtkWidget *w = gtk_label_new (_("Minimum X value:"));
112 	gtk_grid_attach (grid, w, 0, 0, 1, 1);
113 	xminbtn = GTK_SPIN_BUTTON (gtk_spin_button_new_with_range (0., 1., 0.1));
114 	minsgn = g_signal_connect_swapped (xminbtn, "value-changed", G_CALLBACK (on_min_changed), this);
115 	gtk_grid_attach (grid, GTK_WIDGET (xminbtn), 1, 0, 1, 1);
116 	w = gtk_label_new (_("Maximum X value:"));
117 	gtk_grid_attach (grid, w, 2, 0, 1, 1);
118 	xmaxbtn = GTK_SPIN_BUTTON (gtk_spin_button_new_with_range (0., 1., 0.1));
119 	maxsgn = g_signal_connect_swapped (xmaxbtn, "value-changed", G_CALLBACK (on_max_changed), this);
120 	gtk_grid_attach (grid, GTK_WIDGET (xmaxbtn), 3, 0, 1, 1);
121 	xrange = GTK_RANGE (gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, NULL));
122 	g_object_set (G_OBJECT (xrange), "hexpand", true, NULL);
123 	gtk_widget_set_sensitive (GTK_WIDGET (xrange), false);
124 	xrangesgn = g_signal_connect_swapped (xrange, "value-changed", G_CALLBACK (on_xrange_changed), this);
125 	gtk_grid_attach (grid, GTK_WIDGET (xrange), 4, 0, 1, 1);
126 	w = gtk_label_new (_("Minimum Y value:"));
127 	gtk_grid_attach (grid, w, 0, 1, 1, 1);
128 	yminbtn = GTK_SPIN_BUTTON (gtk_spin_button_new_with_range (0., 1., 0.1));
129 	yminsgn = g_signal_connect_swapped (yminbtn, "value-changed", G_CALLBACK (on_ymin_changed), this);
130 	gtk_grid_attach (grid, GTK_WIDGET (yminbtn), 1, 1, 1, 1);
131 	w = gtk_label_new (_("Maximum Y value:"));
132 	gtk_grid_attach (grid, w, 2, 1, 1, 1);
133 	ymaxbtn = GTK_SPIN_BUTTON (gtk_spin_button_new_with_range (0., 1., 0.1));
134 	ymaxsgn = g_signal_connect_swapped (ymaxbtn, "value-changed", G_CALLBACK (on_ymax_changed), this);
135 	gtk_grid_attach (grid, GTK_WIDGET (ymaxbtn), 3, 1, 1, 1);
136 	yrange = GTK_RANGE (gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, NULL));
137 	gtk_widget_set_sensitive (GTK_WIDGET (yrange), false);
138 	yrangesgn = g_signal_connect_swapped (yrange, "value-changed", G_CALLBACK (on_yrange_changed), this);
139 	gtk_grid_attach (grid, GTK_WIDGET (yrange), 4, 1, 1, 1);
140 	m_ExtraWidget = NULL;
141 }
142 
~SpectrumView()143 SpectrumView::~SpectrumView ()
144 {
145 	g_signal_handler_disconnect (xminbtn, minsgn);
146 	g_signal_handler_disconnect (xmaxbtn, maxsgn);
147 	g_signal_handler_disconnect (yminbtn, yminsgn);
148 	g_signal_handler_disconnect (ymaxbtn, ymaxsgn);
149 	g_signal_handler_disconnect (xrange, xrangesgn);
150 	g_signal_handler_disconnect (yrange, yrangesgn);
151 }
152 
SetAxisBounds(GogAxisType target,double min,double max,bool inverted)153 void SpectrumView::SetAxisBounds (GogAxisType target, double min, double max, bool inverted)
154 {
155 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
156 	GSList *axes = gog_chart_get_axes (chart, target);
157 	GogAxis *axis = GOG_AXIS (axes->data);
158 	gog_axis_set_bounds (axis, min, max);
159 	g_object_set (axis, "invert-axis", inverted, NULL);
160 	if (target == GOG_AXIS_X) {
161 		double l = log10 (fabs (max - min));
162 		int n = (l < 3)? rint (3 - l): 0;
163 		xstep = pow (10., -n);
164 		g_signal_handler_block (xminbtn, minsgn);
165 		g_signal_handler_block (xmaxbtn, maxsgn);
166 		gtk_spin_button_set_range (xminbtn, min, max);
167 		gtk_spin_button_set_range (xmaxbtn, min, max);
168 		gtk_spin_button_set_increments (xminbtn, xstep, 100 * xstep);
169 		gtk_spin_button_set_increments (xmaxbtn, xstep, 100 * xstep);
170 		gtk_range_set_increments (xrange, xstep, 100 * xstep);
171 		gtk_range_set_inverted (xrange, !inverted);
172 		g_signal_handler_block (xrange, xrangesgn);
173 		gtk_range_set_value (xrange, 0.);
174 		gtk_widget_set_sensitive (GTK_WIDGET (xrange), false);
175 		g_signal_handler_unblock (xrange, xrangesgn);
176 		gtk_spin_button_set_value (xminbtn, min);
177 		gtk_spin_button_set_value (xmaxbtn, max);
178 		gtk_spin_button_set_digits (xminbtn, n);
179 		gtk_spin_button_set_digits (xmaxbtn, n);
180 		g_signal_handler_unblock (xminbtn, minsgn);
181 		g_signal_handler_unblock (xmaxbtn, maxsgn);
182 		xmin = min;
183 		xmax = max;
184 	}
185 	else if (target == GOG_AXIS_Y) {
186 		double l = log10 (fabs (max - min));
187 		int n = (l < 3)? rint (3 - l): 0;
188 		ystep = pow (10., -n);
189 		g_signal_handler_block (yminbtn, yminsgn);
190 		g_signal_handler_block (ymaxbtn, ymaxsgn);
191 		gtk_spin_button_set_range (yminbtn, min, max);
192 		gtk_spin_button_set_range (ymaxbtn, min, max);
193 		gtk_spin_button_set_increments (yminbtn, ystep, 100 * ystep);
194 		gtk_spin_button_set_increments (ymaxbtn, ystep, 100 * ystep);
195 		gtk_range_set_increments (yrange, ystep, 100 * ystep);
196 		gtk_range_set_inverted (yrange, !inverted);
197 		g_signal_handler_block (yrange, yrangesgn);
198 		gtk_range_set_value (yrange, 0.);
199 		gtk_widget_set_sensitive (GTK_WIDGET (yrange), false);
200 		g_signal_handler_unblock (yrange, yrangesgn);
201 		gtk_spin_button_set_value (yminbtn, min);
202 		gtk_spin_button_set_value (ymaxbtn, max);
203 		gtk_spin_button_set_digits (yminbtn, n);
204 		gtk_spin_button_set_digits (ymaxbtn, n);
205 		g_signal_handler_unblock (yminbtn, yminsgn);
206 		g_signal_handler_unblock (ymaxbtn, ymaxsgn);
207 		ymin = min;
208 		ymax = max;
209 	}
210 }
211 
SetAxisLabel(GogAxisType target,char const * unit)212 void SpectrumView::SetAxisLabel (GogAxisType target, char const *unit)
213 {
214 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
215 	GSList *axes = gog_chart_get_axes (chart, target);
216 	GogObject *axis = GOG_OBJECT (axes->data);
217 	GOData *data = go_data_scalar_str_new (unit, false);
218 	GogObject *label = gog_object_get_child_by_name (axis, "Label");
219 	if (label) {
220 		// remove the old label if any
221 		gog_object_clear_parent (label);
222 		g_object_unref (label);
223 	}
224 	label = GOG_OBJECT (g_object_new (GOG_TYPE_LABEL, NULL));
225 	g_object_set (G_OBJECT (label), "allow-markup", TRUE, NULL);
226 	gog_dataset_set_dim (GOG_DATASET (label), 0, data, NULL);
227 	gog_object_add_by_name (axis, "Label", label);
228 
229 }
230 
ShowAxis(GogAxisType target,G_GNUC_UNUSED bool show)231 void SpectrumView::ShowAxis (GogAxisType target, G_GNUC_UNUSED bool show)
232 {
233 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
234 	GSList *axes = gog_chart_get_axes (chart, target);
235 	GogObject *axis = GOG_OBJECT (axes->data);
236 	g_object_set (G_OBJECT (axis), "major-tick-labeled", false, NULL);
237 	GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (axis));
238 	style->line.dash_type = GO_LINE_NONE;
239 	style->line.auto_dash = false;
240 }
241 
Render(cairo_t * cr,double width,double height)242 void SpectrumView::Render (cairo_t *cr, double width, double height)
243 {
244 	gog_graph_render_to_cairo (go_graph_widget_get_graph (GO_GRAPH_WIDGET (m_Widget)), cr, width, height);
245 }
246 
OnMinChanged()247 void SpectrumView::OnMinChanged ()
248 {
249 	double min = gtk_spin_button_get_value (xminbtn);
250 	double max = gtk_spin_button_get_value (xmaxbtn);
251 	if (max <= min) {
252 		double step;
253 		gtk_spin_button_get_increments (xminbtn, &step, NULL);
254 		min = max - step;
255 		g_signal_handler_block (xminbtn, minsgn);
256 		gtk_spin_button_set_value (xminbtn, min);
257 		g_signal_handler_unblock (xminbtn, minsgn);
258 	}
259 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
260 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_X);
261 	GogAxis *axis = GOG_AXIS (axes->data);
262 	gog_axis_set_bounds (axis, min, max);
263 	g_signal_handler_block (xrange, xrangesgn);
264 	if (max - min < xmax - xmin) {
265 		gtk_range_set_range (xrange, 0., xmax - xmin - max + min);
266 		gtk_range_set_value (xrange, min - xmin);
267 		gtk_widget_set_sensitive (GTK_WIDGET (xrange), true);
268 	} else {
269 		gtk_range_set_value (xrange, 0.);
270 		gtk_widget_set_sensitive (GTK_WIDGET (xrange), false);
271 	}
272 	g_signal_handler_unblock (xrange, xrangesgn);
273 }
274 
OnYMinChanged()275 void SpectrumView::OnYMinChanged ()
276 {
277 	double min = gtk_spin_button_get_value (yminbtn);
278 	double max = gtk_spin_button_get_value (ymaxbtn);
279 	if (max <= min) {
280 		double step;
281 		gtk_spin_button_get_increments (yminbtn, &step, NULL);
282 		min = max - step;
283 		g_signal_handler_block (yminbtn, yminsgn);
284 		gtk_spin_button_set_value (yminbtn, min);
285 		g_signal_handler_unblock (yminbtn, yminsgn);
286 	}
287 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
288 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_Y);
289 	GogAxis *axis = GOG_AXIS (axes->data);
290 	gog_axis_set_bounds (axis, min, max);
291 	g_signal_handler_block (yrange, yrangesgn);
292 	if (max - min < ymax - ymin) {
293 		gtk_range_set_range (yrange, 0., ymax - ymin - max + min);
294 		gtk_range_set_value (yrange, min - ymin);
295 		gtk_widget_set_sensitive (GTK_WIDGET (yrange), true);
296 	} else {
297 		gtk_range_set_value (yrange, 0.);
298 		gtk_widget_set_sensitive (GTK_WIDGET (yrange), false);
299 	}
300 	g_signal_handler_unblock (yrange, yrangesgn);
301 }
302 
OnMaxChanged()303 void SpectrumView::OnMaxChanged ()
304 {
305 	double min = gtk_spin_button_get_value (xminbtn);
306 	double max = gtk_spin_button_get_value (xmaxbtn);
307 	if (max <= min) {
308 		double step;
309 		gtk_spin_button_get_increments (xmaxbtn, &step, NULL);
310 		max = min + step;
311 		g_signal_handler_block (xmaxbtn, maxsgn);
312 		gtk_spin_button_set_value (xmaxbtn, max);
313 		g_signal_handler_unblock (xmaxbtn, maxsgn);
314 	}
315 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
316 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_X);
317 	GogAxis *axis = GOG_AXIS (axes->data);
318 	gog_axis_set_bounds (axis, min, max);
319 	g_signal_handler_block (xrange, xrangesgn);
320 	if (max - min < xmax - xmin) {
321 		gtk_range_set_range (xrange, 0., xmax - xmin - max + min);
322 		gtk_range_set_value (xrange, min - xmin);
323 		gtk_widget_set_sensitive (GTK_WIDGET (xrange), true);
324 	} else {
325 		gtk_range_set_value (xrange, 0.);
326 		gtk_widget_set_sensitive (GTK_WIDGET (xrange), false);
327 	}
328 	g_signal_handler_unblock (xrange, xrangesgn);
329 }
330 
OnYMaxChanged()331 void SpectrumView::OnYMaxChanged ()
332 {
333 	double min = gtk_spin_button_get_value (yminbtn);
334 	double max = gtk_spin_button_get_value (ymaxbtn);
335 	if (max <= min) {
336 		double step;
337 		gtk_spin_button_get_increments (ymaxbtn, &step, NULL);
338 		max = min + step;
339 		g_signal_handler_block (ymaxbtn, ymaxsgn);
340 		gtk_spin_button_set_value (ymaxbtn, max);
341 		g_signal_handler_unblock (ymaxbtn, ymaxsgn);
342 	}
343 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
344 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_Y);
345 	GogAxis *axis = GOG_AXIS (axes->data);
346 	gog_axis_set_bounds (axis, min, max);
347 	g_signal_handler_block (yrange, yrangesgn);
348 	if (max - min < ymax - ymin) {
349 		gtk_range_set_range (yrange, 0., ymax - ymin - max + min);
350 		gtk_range_set_value (yrange, min - xmin);
351 		gtk_widget_set_sensitive (GTK_WIDGET (yrange), true);
352 	} else {
353 		gtk_range_set_value (yrange, 0.);
354 		gtk_widget_set_sensitive (GTK_WIDGET (yrange), false);
355 	}
356 	g_signal_handler_unblock (yrange, yrangesgn);
357 }
358 
OnXRangeChanged()359 void SpectrumView::OnXRangeChanged ()
360 {
361 	double max = gtk_spin_button_get_value (xmaxbtn) - gtk_spin_button_get_value (xminbtn);
362 	double min = xmin + gtk_range_get_value (xrange);
363 	max += min;
364 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
365 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_X);
366 	GogAxis *axis = GOG_AXIS (axes->data);
367 	gog_axis_set_bounds (axis, min, max);
368 	g_signal_handler_block (xminbtn, minsgn);
369 	gtk_spin_button_set_value (xminbtn, min);
370 	g_signal_handler_unblock (xminbtn, minsgn);
371 	g_signal_handler_block (xmaxbtn, maxsgn);
372 	gtk_spin_button_set_value (xmaxbtn, max);
373 	g_signal_handler_unblock (xmaxbtn, maxsgn);
374 }
375 
OnYRangeChanged()376 void SpectrumView::OnYRangeChanged ()
377 {
378 	double max = gtk_spin_button_get_value (ymaxbtn) - gtk_spin_button_get_value (yminbtn);
379 	double min = ymin + gtk_range_get_value (yrange);
380 	max += min;
381 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
382 	GSList *axes = gog_chart_get_axes (chart, GOG_AXIS_Y);
383 	GogAxis *axis = GOG_AXIS (axes->data);
384 	gog_axis_set_bounds (axis, min, max);
385 	g_signal_handler_block (yminbtn, yminsgn);
386 	gtk_spin_button_set_value (yminbtn, min);
387 	g_signal_handler_unblock (yminbtn, yminsgn);
388 	g_signal_handler_block (ymaxbtn, ymaxsgn);
389 	gtk_spin_button_set_value (ymaxbtn, max);
390 	g_signal_handler_unblock (ymaxbtn, ymaxsgn);
391 }
392 
NewSeries(bool new_plot)393 GogSeries *SpectrumView::NewSeries (bool new_plot)
394 {
395 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
396 	GogPlot *plot = NULL;
397 	if (new_plot) {
398 		/* Create a scatter plot and add it to the chart */
399 		plot = (GogPlot *) gog_plot_new_by_name ("GogXYPlot");
400 		g_object_set (plot, "default-style-has-markers", false, NULL);
401 		gog_object_add_by_name (GOG_OBJECT (chart), "Plot", GOG_OBJECT (plot));
402 	} else {
403 		// find the first plot in the chart
404 		GSList *l = gog_object_get_children (GOG_OBJECT (chart), gog_object_find_role_by_name (GOG_OBJECT (chart), "Plot"));
405 		plot = (GogPlot*) l->data;
406 		g_slist_free (l);
407 	}
408 	return gog_plot_new_series (plot);
409 }
410 
SaveAsImage(string const & filename,char const * mime_type,unsigned width,unsigned height) const411 void SpectrumView::SaveAsImage (string const &filename, char const *mime_type, unsigned width, unsigned height) const
412 {
413 	char *fname = go_mime_to_image_format (mime_type);
414 	GOImageFormat format = go_image_get_format_from_name ((fname)? fname: filename.c_str ());
415 	if (format == GO_IMAGE_FORMAT_UNKNOWN)
416 		return;
417 	GError *error = NULL;
418 	GsfOutput *output = gsf_output_gio_new_for_uri (filename.c_str (), &error);
419 	if (error) {
420 		g_error_free (error);
421 		return;
422 	}
423 	GogGraph *graph = gog_graph_dup (go_graph_widget_get_graph (GO_GRAPH_WIDGET (m_Widget)));
424 	gog_graph_set_size (graph, width, height);
425 	gog_graph_export_image (graph, format, output, -1., -1.);
426 	g_object_unref (graph);
427 }
428 
InvertAxis(GogAxisType target,bool inverted)429 void SpectrumView::InvertAxis (GogAxisType target, bool inverted)
430 {
431 	GogChart *chart = go_graph_widget_get_chart (GO_GRAPH_WIDGET (m_Widget));
432 	GSList *axes = gog_chart_get_axes (chart, target);
433 	GogAxis *axis = GOG_AXIS (axes->data);
434 	g_object_set (axis, "invert-axis", inverted, NULL);
435 }
436 
AddToOptionBox(GtkWidget * w)437 void SpectrumView::AddToOptionBox (GtkWidget *w)
438 {
439 	gtk_grid_attach (GTK_GRID (m_OptionBox), w, 0, 2, 5, 1);
440 	m_ExtraWidget = w;
441 }
442 
DestroyExtraWidget()443 void SpectrumView::DestroyExtraWidget ()
444 {
445 	if (m_ExtraWidget) {
446 		gtk_widget_destroy (m_ExtraWidget);
447 		m_ExtraWidget = NULL;
448 	}
449 }
450 
451 }	//	namespace gcu
452