1 /* table.cpp is part of UDAV
2  * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin@gmail.ru>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 #include <FL/Fl_Spinner.H>
18 #include <FL/Fl_Output.H>
19 #include <FL/Fl_Float_Input.H>
20 #include <FL/Fl_Value_Input.H>
21 #include <FL/Fl_Round_Button.H>
22 #include "mgllab.h"
23 
24 //-----------------------------------------------------------------------------
addto_cb(Fl_Widget *,void * v)25 void addto_cb(Fl_Widget*, void*v)
26 {
27 	TableWindow* e = (TableWindow*)v;
28 	const char *s = fl_input(_("Enter number for addition to data values"),0);
29 	HMDT d = dynamic_cast<HMDT>(e->var);
30 	if(d && s)	{	mgl_data_add_num(d, atof(s));	e->refresh();	}
31 	HADT c = dynamic_cast<HADT>(e->var);
32 	if(c && s)	{	mgl_datac_add_num(c, mgl_atoc(s,true));	e->refresh();	}
33 }
34 //-----------------------------------------------------------------------------
subto_cb(Fl_Widget *,void * v)35 void subto_cb(Fl_Widget*, void*v)
36 {
37 	TableWindow* e = (TableWindow*)v;
38 	const char *s = fl_input(_("Enter number for subtraction from data values"),0);
39 	HMDT d = dynamic_cast<HMDT>(e->var);
40 	if(d && s)	{	mgl_data_sub_num(d, atof(s));	e->refresh();	}
41 	HADT c = dynamic_cast<HADT>(e->var);
42 	if(c && s)	{	mgl_datac_sub_num(c, mgl_atoc(s,true));	e->refresh();	}
43 }
44 //-----------------------------------------------------------------------------
multo_cb(Fl_Widget *,void * v)45 void multo_cb(Fl_Widget*, void*v)
46 {
47 	TableWindow* e = (TableWindow*)v;
48 	const char *s = fl_input(_("Enter number for multiplication of data values"),0);
49 	HMDT d = dynamic_cast<HMDT>(e->var);
50 	if(d && s)	{	mgl_data_mul_num(d, atof(s));	e->refresh();	}
51 	HADT c = dynamic_cast<HADT>(e->var);
52 	if(c && s)	{	mgl_datac_mul_num(c, mgl_atoc(s,true));	e->refresh();	}
53 }
54 //-----------------------------------------------------------------------------
divto_cb(Fl_Widget *,void * v)55 void divto_cb(Fl_Widget*, void*v)
56 {
57 	TableWindow* e = (TableWindow*)v;
58 	const char *s = fl_input(_("Enter number for division of data values"),0);
59 	HMDT d = dynamic_cast<HMDT>(e->var);
60 	if(d && s)	{	mgl_data_div_num(d, atof(s));	e->refresh();	}
61 	HADT c = dynamic_cast<HADT>(e->var);
62 	if(c && s)	{	mgl_datac_div_num(c, mgl_atoc(s,true));	e->refresh();	}
63 }
64 //-----------------------------------------------------------------------------
65 class XYZDlg : public GeneralDlg
66 {
67 	Fl_Box *box;
68 	Fl_Check_Button *wch;
69 	Fl_Spinner *wmx, *wmy, *wmz;
70 public:
71 	bool OK;
rx()72 	double rx()	{	return wmx->value();	}
ry()73 	double ry()	{	return wmy->value();	}
rz()74 	double rz()	{	return wmz->value();	}
nx()75 	double nx()	{	return mgl_int(wmx->value());	}
ny()76 	double ny()	{	return mgl_int(wmy->value());	}
nz()77 	double nz()	{	return mgl_int(wmz->value());	}
ch()78 	double ch()	{	return wch->value();	}
setup(const char * desc,const char * ch=NULL)79 	void setup(const char *desc, const char *ch=NULL)
80 	{
81 		if(desc)	box->label(desc);
82 		if(ch && *ch)
83 		{	wch->label(ch);	wch->activate();	}
84 		else
85 		{	wch->label(_("not used"));
86 			wch->deactivate();	}
87 	}
init()88 	void init()	{	OK=false;	}
XYZDlg()89 	XYZDlg() : GeneralDlg()
90 	{
91 		w = new Fl_Double_Window(325, 125, _("Change data sizes"));
92 		box = new Fl_Box(10, 10, 305, 40);
93 		box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
94 		wmx = new Fl_Spinner(30, 55, 75, 25, "mx");
95 		wmx->tooltip(_("New size of data on 1st dimension (x-direction)"));
96 		wmy = new Fl_Spinner(135, 55, 75, 25, "my");
97 		wmy->tooltip(_("New size of data on 2nd dimension (y-direction)"));
98 		wmz = new Fl_Spinner(240, 55, 75, 25, "mz");
99 		wmz->tooltip(_("New size of data on 3d dimension (z-direction)"));
100 		wch = new Fl_Check_Button(15, 90, 95, 25);
101 		Fl_Button *o = new Fl_Button(125, 90, 85, 25, _("Cancel"));
102 		o->tooltip(_("Do nothing and close this window"));	o->callback(cb_dlg_cancel,this);
103 		o = new Fl_Return_Button(230, 90, 85, 25, _("Change"));
104 		o->tooltip(_("Change (resize) data"));	o->callback(cb_dlg_ok,this);
105 		w->end();	w->set_modal();	OK=false;
106 	}
cb_ok()107 	void cb_ok()	{	OK=true;	hide();	}
run()108 	bool run()	{	OK=false;	w->show();	while(w->shown())	Fl::wait();	return OK;	}
109 } xyz_dlg;
110 //-----------------------------------------------------------------------------
new_dat_cb(Fl_Widget *,void * v)111 void new_dat_cb(Fl_Widget*, void*v)
112 {
113 	TableWindow* e = (TableWindow*)v;
114 	xyz_dlg.setup(_("Specify new data size\nData will be zero filled"));
115 	if(xyz_dlg.run())
116 	{
117 		HMDT d = dynamic_cast<HMDT>(e->var);
118 		if(d)
119 		{	d->Create(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
120 		HADT c = dynamic_cast<HADT>(e->var);
121 		if(c)
122 		{	c->Create(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
123 	}
124 }
125 //-----------------------------------------------------------------------------
resize_cb(Fl_Widget *,void * v)126 void resize_cb(Fl_Widget*, void*v)
127 {
128 	TableWindow* e = (TableWindow*)v;
129 	xyz_dlg.setup(_("Specify new data size\nData will be interpolated"));
130 	if(xyz_dlg.run())
131 	{
132 		HMDT d = dynamic_cast<HMDT>(e->var);
133 		if(d)
134 		{	*d = d->Resize(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
135 		HADT c = dynamic_cast<HADT>(e->var);
136 		if(c)
137 		{	*c = c->Resize(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
138 	}
139 }
140 //-----------------------------------------------------------------------------
squeeze_cb(Fl_Widget *,void * v)141 void squeeze_cb(Fl_Widget*, void*v)
142 {
143 	TableWindow* e = (TableWindow*)v;
144 	xyz_dlg.setup(_("Specify the skipping step\nEach m-th point will be saved only"), _("smoothed"));	if(xyz_dlg.run())
145 	{
146 		HMDT d = dynamic_cast<HMDT>(e->var);
147 		if(d)
148 		{	d->Squeeze(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz(), xyz_dlg.ch());	e->refresh();	}
149 		HADT c = dynamic_cast<HADT>(e->var);
150 		if(c)
151 		{	c->Squeeze(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz(), xyz_dlg.ch());	e->refresh();	}
152 	}
153 }
154 //-----------------------------------------------------------------------------
155 class ChngDlg : public GeneralDlg
156 {
157 	Fl_Check_Button *dx, *dy, *dz;
158 	Fl_Choice *kind, *type;
159 	Fl_Float_Input *val;
160 public:
ChngDlg()161 	ChngDlg() : GeneralDlg()
162 	{
163 		Fl_Menu_Item k[]={{_("Smooth")}, {_("CumSum")}, { _("Integrate")},
164 		{ _("Difference")}, { _("Double diff.")}, { _("Swap parts")},
165 		{ _("Sinus FFT")}, { _("Cosine FFT")}, { _("Hankel")},
166 		{ _("Mirror")}, { _("Roll")}, { _("Sew phase")}, { _("Envelop")}, {0}};
167 		Fl_Menu_Item t[]={{_("Linear *3")}, {_("Linear *5")}, {_("Parabolic *5")},{0}};
168 		w = new Fl_Double_Window(165, 215, _("Change data"));
169 		kind = new Fl_Choice(10, 25, 145, 25, _("Type of operation"));
170 		kind->align(FL_ALIGN_TOP_LEFT);	kind->copy(k);
171 		dx = new Fl_Check_Button(10, 55, 140, 25, _("along x"));
172 		dy = new Fl_Check_Button(10, 80, 140, 25, _("along y"));
173 		dz = new Fl_Check_Button(10, 105, 140, 25, _("along z"));
174 		type = new Fl_Choice(10, 145, 145, 25, _("Type of smoothing"));
175 		type->align(FL_ALIGN_TOP_LEFT);	type->copy(t);
176 		val = new Fl_Float_Input(10, 145, 145, 25, _("Numeric parameter"));
177 		val->align(FL_ALIGN_TOP_LEFT);
178 		Fl_Button *o;
179 		o = new Fl_Button(10, 180, 65, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
180 		o = new Fl_Return_Button(90, 180, 65, 25, _("Do"));	o->callback(cb_dlg_ok,this);
181 		w->end();	w->set_modal();
182 	}
cb_ok()183 	void cb_ok()
184 	{
185 		result.clear();
186 		if(dx->value())	result += 'x';
187 		if(dy->value())	result += 'y';
188 		if(dz->value())	result += 'z';
189 		if(result.empty())
190 		{	fl_alert(_("You need to specify direction(s)"));	return;	}
191 		if(type->value()==0)	result += '3';
192 		if(type->value()==1)	result += '5';
193 		HMDT d = dynamic_cast<HMDT>(dat);
194 		HADT c = dynamic_cast<HADT>(dat);
195 		const char *r = result.c_str();
196 		bool err = false;
197 		double v = val->value() ? atof(val->value()) : 0;
198 		if(d)	switch(kind->value())
199 		{
200 		case 0:	d->Smooth(r);	break;
201 		case 1:	d->CumSum(r);	break;
202 		case 2:	d->Integral(r);	break;
203 		case 3:	d->Diff(r);		break;
204 		case 4:	d->Diff2(r);	break;
205 		case 5:	d->Swap(r);		break;
206 		case 6:	d->SinFFT(r);	break;
207 		case 7:	d->CosFFT(r);	break;
208 		case 8:	d->Hankel(r);	break;
209 		case 9:	d->Mirror(r);	break;
210 		case 10:d->Roll(*r ,v);	break;
211 		case 11:d->Sew(r);		break;
212 		case 12:d->Envelop(*r);	break;
213 		}
214 		else if(c)	switch(kind->value())
215 		{
216 		case 0:	c->Smooth(r);	break;
217 		case 1:	c->CumSum(r);	break;
218 		case 2:	c->Integral(r);	break;
219 		case 3:	c->Diff(r);		break;
220 		case 4:	c->Diff2(r);	break;
221 		case 5:	c->Swap(r);		break;
222 		case 6:	c->SinFFT(r);	break;
223 		case 7:	c->CosFFT(r);	break;
224 		case 8:	c->Hankel(r);	break;
225 		case 9:	c->Mirror(r);	break;
226 		case 10:c->Roll(*r, v);	break;
227 		case 11:err=true;		break;
228 		case 12:c->Envelop(*r);	break;
229 		}
230 		else	err=true;
231 		if(err)	fl_alert(_("Operation is not supported for this type of data."));
232 		else	hide();
233 	}
run(int k,mglDataA * d)234 	void run(int k, mglDataA *d)
235 	{
236 		init();	dat=d;	kind->value(k);
237 		if(k)	{	type->hide();	val->show();	}
238 		else	{	type->show();	val->hide();	}
239 		w->show();	while(w->shown())	Fl::wait();
240 	}
241 } chng_dlg;
242 //-----------------------------------------------------------------------------
smooth_cb(Fl_Widget *,void * v)243 void smooth_cb(Fl_Widget*, void*v)
244 {
245 	TableWindow* e = (TableWindow*)v;
246 	chng_dlg.run(0, e->var);
247 	if(!chng_dlg.result.empty())	e->refresh();
248 }
249 //-----------------------------------------------------------------------------
cumsum_cb(Fl_Widget *,void * v)250 void cumsum_cb(Fl_Widget*, void*v)
251 {
252 	TableWindow* e = (TableWindow*)v;
253 	chng_dlg.run(1, e->var);
254 	if(!chng_dlg.result.empty())	e->refresh();
255 }
256 //-----------------------------------------------------------------------------
integr_cb(Fl_Widget *,void * v)257 void integr_cb(Fl_Widget*, void*v)
258 {
259 	TableWindow* e = (TableWindow*)v;
260 	chng_dlg.run(2, e->var);
261 	if(!chng_dlg.result.empty())	e->refresh();
262 }
263 //-----------------------------------------------------------------------------
diff_cb(Fl_Widget *,void * v)264 void diff_cb(Fl_Widget*, void*v)
265 {
266 	TableWindow* e = (TableWindow*)v;
267 	chng_dlg.run(3, e->var);
268 	if(!chng_dlg.result.empty())	e->refresh();
269 }
270 //-----------------------------------------------------------------------------
diff2_cb(Fl_Widget *,void * v)271 void diff2_cb(Fl_Widget*, void*v)
272 {
273 	TableWindow* e = (TableWindow*)v;
274 	chng_dlg.run(4, e->var);
275 	if(!chng_dlg.result.empty())	e->refresh();
276 }
277 //-----------------------------------------------------------------------------
swap_cb(Fl_Widget *,void * v)278 void swap_cb(Fl_Widget*, void*v)
279 {
280 	TableWindow* e = (TableWindow*)v;
281 	chng_dlg.run(5, e->var);
282 	if(!chng_dlg.result.empty())	e->refresh();
283 }
284 //-----------------------------------------------------------------------------
sinfft_cb(Fl_Widget *,void * v)285 void sinfft_cb(Fl_Widget*, void*v)
286 {
287 	TableWindow* e = (TableWindow*)v;
288 	chng_dlg.run(6, e->var);
289 	if(!chng_dlg.result.empty())	e->refresh();
290 }
291 //-----------------------------------------------------------------------------
cosfft_cb(Fl_Widget *,void * v)292 void cosfft_cb(Fl_Widget*, void*v)
293 {
294 	TableWindow* e = (TableWindow*)v;
295 	chng_dlg.run(7, e->var);
296 	if(!chng_dlg.result.empty())	e->refresh();
297 }
298 //-----------------------------------------------------------------------------
hankel_cb(Fl_Widget *,void * v)299 void hankel_cb(Fl_Widget*, void*v)
300 {
301 	TableWindow* e = (TableWindow*)v;
302 	chng_dlg.run(8, e->var);
303 	if(!chng_dlg.result.empty())	e->refresh();
304 }
305 //-----------------------------------------------------------------------------
mirror_cb(Fl_Widget *,void * v)306 void mirror_cb(Fl_Widget*, void*v)
307 {
308 	TableWindow* e = (TableWindow*)v;
309 	chng_dlg.run(9, e->var);
310 	if(!chng_dlg.result.empty())	e->refresh();
311 }
312 //-----------------------------------------------------------------------------
roll_cb(Fl_Widget *,void * v)313 void roll_cb(Fl_Widget*, void*v)
314 {
315 	TableWindow* e = (TableWindow*)v;
316 	chng_dlg.run(10, e->var);
317 	if(!chng_dlg.result.empty())	e->refresh();
318 }
319 //-----------------------------------------------------------------------------
sew_cb(Fl_Widget *,void * v)320 void sew_cb(Fl_Widget*, void*v)
321 {
322 	TableWindow* e = (TableWindow*)v;
323 	chng_dlg.run(11, e->var);
324 	if(!chng_dlg.result.empty())	e->refresh();
325 }
326 //-----------------------------------------------------------------------------
envelop_cb(Fl_Widget *,void * v)327 void envelop_cb(Fl_Widget*, void*v)
328 {
329 	TableWindow* e = (TableWindow*)v;
330 	chng_dlg.run(12, e->var);
331 	if(!chng_dlg.result.empty())	e->refresh();
332 }
333 //-----------------------------------------------------------------------------
334 class NwdtDlg : public GeneralDlg
335 {
336 	Fl_Check_Button *dx, *dy, *dz;
337 	Fl_Choice *kind;
338 	Fl_Input *name;
339 public:
NwdtDlg()340 	NwdtDlg() : GeneralDlg()
341 	{
342 		Fl_Menu_Item k[]={{_("Summation of")}, {_("Maximum of")}, { _("Minimum of")}, { _("Pulse prop.")}, {0}};
343 		w = new Fl_Double_Window(165, 215, _("Extract data"));
344 		kind = new Fl_Choice(10, 25, 145, 25, _("Type of operation"));
345 		kind->align(FL_ALIGN_TOP_LEFT);	kind->copy(k);
346 		dx = new Fl_Check_Button(10, 55, 140, 25, _("along x"));
347 		dy = new Fl_Check_Button(10, 80, 140, 25, _("along y"));
348 		dz = new Fl_Check_Button(10, 105, 140, 25, _("along z"));
349 		name = new Fl_Input(10, 145, 145, 25, _("Name for output"));
350 		name->align(FL_ALIGN_TOP_LEFT);
351 
352 		Fl_Button *o;
353 		o = new Fl_Button(10, 180, 65, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
354 		o = new Fl_Return_Button(90, 180, 65, 25, _("Do"));	o->callback(cb_dlg_ok,this);
355 		w->set_modal();	w->end();
356 	}
cb_ok()357 	void cb_ok()
358 	{
359 		result.clear();
360 		if(dx->value())	result += 'x';
361 		if(dy->value())	result += 'y';
362 		if(dz->value())	result += 'z';
363 		if(result.empty())
364 		{	fl_alert(_("You need to specify direction(s)"));	return;	}
365 		const char *s = name->value();
366 		if(!s || !s[0])
367 		{	fl_alert(_("You need to provide output name"));	return;	}
368 		mglDataA *out = Parse->AddVar(s);
369 
370 		HMDT d = dynamic_cast<HMDT>(dat);
371 		HADT c = dynamic_cast<HADT>(dat);
372 		const char *r = result.c_str();
373 		if(d)	switch(kind->value())
374 		{
375 			case 0:	*out = d->Sum(r);	break;
376 			case 1:	*out = d->Max(r);	break;
377 			case 2:	*out = d->Min(r);	break;
378 			case 3:	*out = d->Pulse(*r);break;
379 		}
380 		if(c)	switch(kind->value())
381 		{
382 			case 0:	*out = c->Sum(r);	break;
383 			case 1:	*out = c->Max(r);	break;
384 			case 2:	*out = c->Min(r);	break;
385 			case 3:	*out = mglData(true,mgl_data_pulse(c,*r));	break;
386 		}
387 		hide();
388 	}
run(int k,mglDataA * d)389 	void run(int k, mglDataA *d)
390 	{
391 		init();	dat=d;	kind->value(k);
392 		w->show();	while(w->shown())	Fl::wait();
393 	}
394 } nwdt_dlg;
395 //-----------------------------------------------------------------------------
asum_cb(Fl_Widget *,void * v)396 void asum_cb(Fl_Widget*, void*v)
397 {
398 	TableWindow* e = (TableWindow*)v;
399 	nwdt_dlg.run(0, e->var);
400 	if(!chng_dlg.result.empty())	e->refresh();
401 }
402 //-----------------------------------------------------------------------------
amax_cb(Fl_Widget *,void * v)403 void amax_cb(Fl_Widget*, void*v)
404 {
405 	TableWindow* e = (TableWindow*)v;
406 	nwdt_dlg.run(1, e->var);
407 	if(!chng_dlg.result.empty())	e->refresh();
408 }
409 //-----------------------------------------------------------------------------
amin_cb(Fl_Widget *,void * v)410 void amin_cb(Fl_Widget*, void*v)
411 {
412 	TableWindow* e = (TableWindow*)v;
413 	nwdt_dlg.run(2, e->var);
414 	if(!chng_dlg.result.empty())	e->refresh();
415 }
416 //-----------------------------------------------------------------------------
pulse_cb(Fl_Widget *,void * v)417 void pulse_cb(Fl_Widget*, void*v)
418 {
419 	TableWindow* e = (TableWindow*)v;
420 	nwdt_dlg.run(3, e->var);
421 	if(!chng_dlg.result.empty())	e->refresh();
422 }
423 //-----------------------------------------------------------------------------
load_dat_cb(Fl_Widget *,void * v)424 void load_dat_cb(Fl_Widget*, void*v)
425 {
426 	TableWindow* e = (TableWindow*)v;
427 	const char *newfile = mgl_file_chooser(_("Load Data?"),
428 		_("DAT Files \t*.{dat,csv}\nHDF Files \t*.{h5,hdf}"));
429 	if(newfile)
430 	{
431 		const char *ext = fl_filename_ext(newfile);
432 		HMDT d = dynamic_cast<HMDT>(e->var);
433 		HADT c = dynamic_cast<HADT>(e->var);
434 		if(!strcmp(ext,"h5") || !strcmp(ext,"hdf"))	// this is HDF file
435 		{	// TODO add dialog with choice of HDF names
436 			const char *name = fl_input(_("Enter name of data"),"");
437 			if(name)
438 			{
439 				if(d)	d->ReadHDF(newfile,name);
440 				if(c)	c->ReadHDF(newfile,name);
441 				e->refresh();
442 			}
443 		}
444 		else
445 		{
446 			if(d)	d->Read(newfile);
447 			if(c)	c->Read(newfile);
448 			e->refresh();
449 		}
450 	}
451 }
452 //-----------------------------------------------------------------------------
save_dat_cb(Fl_Widget *,void * v)453 void save_dat_cb(Fl_Widget*, void*v)
454 {
455 	TableWindow* e = (TableWindow*)v;
456 	const char *newfile = mgl_file_chooser(_("Save Data?"),
457 		_("DAT Files \t*.{dat,csv}\nHDF Files \t*.{h5,hdf}"), true);
458 	if(newfile)
459 	{
460 		const char *ext = fl_filename_ext(newfile);
461 		if(!strcmp(ext,"h5") || !strcmp(ext,"hdf"))	// this is HDF file
462 		{
463 			std::string name = wcstombs(e->var->Name());
464 			e->var->SaveHDF(newfile, name.c_str());
465 		}
466 		else	e->var->Save(newfile);
467 	}
468 }
469 //-----------------------------------------------------------------------------
exp_dat_cb(Fl_Widget *,void * v)470 void exp_dat_cb(Fl_Widget*, void*v)
471 {
472 	TableWindow* e = (TableWindow*)v;
473 	const char *newfile = mgl_file_chooser(_("Export Data?"),
474 		_("PNG Files \t*.png"), true);
475 	if(newfile)
476 	{	// TODO show dialog for color scheme
477 		const char *scheme = fl_input(_("Enter color scheme"),MGL_DEF_SCH);
478 		if(scheme)	e->var->Export(newfile,scheme);
479 	}
480 }
481 //-----------------------------------------------------------------------------
imp_dat_cb(Fl_Widget *,void * v)482 void imp_dat_cb(Fl_Widget*, void*v)
483 {
484 	TableWindow* e = (TableWindow*)v;
485 	const char *newfile = mgl_file_chooser(_("Import Data?"),
486 		_("PNG Files \t*.png"));
487 	HMDT d = dynamic_cast<HMDT>(e->var);
488 	if(d && newfile)
489 	{
490 		const char *scheme = fl_input(_("Enter color scheme"),MGL_DEF_SCH);
491 		if(scheme)
492 		{	d->Import(newfile,scheme);	e->refresh();	}
493 	}
494 	if(!d)	fl_alert(_("This operation is not supported for this kind of data."));
495 }
496 //-----------------------------------------------------------------------------
list_dat_cb(Fl_Widget *,void * v)497 void list_dat_cb(Fl_Widget*, void*v)
498 {
499 	TableWindow* e = (TableWindow*)v;
500 	HMDT d = dynamic_cast<HMDT>(e->var);
501 	HADT c = dynamic_cast<HADT>(e->var);
502 	if(!d && !c)
503 	{	fl_message(_("Incorrect type of base data"));	return;	}
504 	if(e->var->GetNz()>1)	fl_message(_("Only current slice will be inserted"));
505 
506 	std::string list = "list " + wcstombs(e->var->Name());
507 	long k=e->get_slice(), nx=e->var->GetNx(), ny=e->var->GetNy();
508 	for(long j=0;j<ny;j++)
509 	{
510 		for(long i=0;i<nx;i++)
511 		{
512 			if(d)	list += '\t'+mgl_str_num(d->a[i+nx*(j+k*ny)]);
513 			if(c)	list += '\t'+mgl_str_num(c->a[i+nx*(j+k*ny)]);
514 		}
515 		if(j<ny-1)	list += "\t|";
516 	}
517 	textbuf->insert(0,list.c_str());
518 }
519 //-----------------------------------------------------------------------------
modify_cb(Fl_Widget *,void * v)520 void modify_cb(Fl_Widget*, void*v)
521 {
522 	TableWindow* e = (TableWindow*)v;
523 	const char *eq=fl_input(_("Enter formula for data modification\nHere x, y, z in range [0,1], u is data value"),0);
524 	if(eq)
525 	{
526 		HMDT d = dynamic_cast<HMDT>(e->var);
527 		HADT c = dynamic_cast<HADT>(e->var);
528 		if(d)	{	d->Modify(eq);	e->refresh();	}
529 		if(c)	{	c->Modify(eq);	e->refresh();	}
530 	}
531 }
532 //-----------------------------------------------------------------------------
533 class NrmDlg : public GeneralDlg
534 {
535 	Fl_Value_Input *wmin, *wmax;
536 	Fl_Choice *dir;
537 	Fl_Check_Button *wsym;
538 public:
NrmDlg()539 	NrmDlg() : GeneralDlg()
540 	{
541 		Fl_Menu_Item k[]={{"x"}, {"y"}, { "z"}, {0}};
542 		w = new Fl_Double_Window(135, 215);
543 		wmin = new Fl_Value_Input(10, 25, 115, 25, _("Minimal value (v1)"));
544 		wmin->align(FL_ALIGN_TOP_LEFT);
545 		wmin->tooltip(_("Minimal value for resulting data values"));
546 		wmax = new Fl_Value_Input(10, 70, 115, 25, _("Maximal value (v2)"));
547 		wmax->align(FL_ALIGN_TOP_LEFT);
548 		wmax->tooltip(_("Maximal value for resulting data values"));
549 		dir = new Fl_Choice(10, 115, 115, 25, _("Direction"));
550 		dir->align(FL_ALIGN_TOP_LEFT);	dir->copy(k);	dir->value(0);
551 		dir->tooltip(_("Direction along which data will be filled"));
552 		wsym = new Fl_Check_Button(10, 115, 115, 25, _("Symmetrical range"));
553 		wsym->tooltip(_("Normalize in symmetrical range: -max(|v1|,|v2|) ... max(|v1|,|v2|)"));
554 
555 		Fl_Button *o;
556 		o = new Fl_Button(25, 150, 85, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
557 		o->tooltip(_("Do nothing and close this window"));
558 		o = new Fl_Return_Button(25, 180, 85, 25, _("Change"));	o->callback(cb_dlg_ok,this);
559 		o->tooltip(_("Change data values and close this window"));
560 		w->set_modal();	w->end();
561 	}
vmin()562 	double vmin()	{	return wmin->value();	}
vmax()563 	double vmax()	{	return wmax->value();	}
sym()564 	int sym()		{	return wsym->value();	}
ok()565 	bool ok()		{	return !result.empty();	}
cb_ok()566 	void cb_ok()
567 	{	result = dir->value();	hide();	}
run(const char * lbl)568 	void run(const char *lbl)
569 	{
570 		init();	w->label(lbl?lbl:"");
571 		w->show();	while(w->shown())	Fl::wait();
572 	}
573 } nrm_dlg;
574 //-----------------------------------------------------------------------------
fill_cb(Fl_Widget *,void * v)575 void fill_cb(Fl_Widget*, void*v)
576 {
577 	TableWindow* e = (TableWindow*)v;
578 	nrm_dlg.run(_("Fill in range"));
579 	if(nrm_dlg.ok())
580 	{
581 		HMDT d = dynamic_cast<HMDT>(e->var);
582 		HADT c = dynamic_cast<HADT>(e->var);
583 		char ch = nrm_dlg.result[0];
584 		if(d)	{	d->Fill(nrm_dlg.vmin(),nrm_dlg.vmax(),ch);	e->refresh();	}
585 		if(c)	{	c->Fill(nrm_dlg.vmin(),nrm_dlg.vmax(),ch);	e->refresh();	}
586 	}
587 }
588 //-----------------------------------------------------------------------------
normal_cb(Fl_Widget *,void * v)589 void normal_cb(Fl_Widget*, void*v)
590 {
591 	TableWindow* e = (TableWindow*)v;
592 	nrm_dlg.run(_("Fill in range"));
593 	if(nrm_dlg.ok())
594 	{
595 		HMDT d = dynamic_cast<HMDT>(e->var);
596 		HADT c = dynamic_cast<HADT>(e->var);
597 		if(d)	{	d->Norm(nrm_dlg.vmin(),nrm_dlg.vmax(),nrm_dlg.sym());	e->refresh();	}
598 		if(c)	{	c->Fill(nrm_dlg.vmin(),nrm_dlg.vmax(),nrm_dlg.sym());	e->refresh();	}
599 	}
600 }
601 //-----------------------------------------------------------------------------
602 struct CropDlg : public GeneralDlg
603 {
604 	Fl_Spinner *x1,*x2, *y1,*y2, *z1,*z2;
CropDlgCropDlg605 	CropDlg() : GeneralDlg()
606 	{
607 		w = new Fl_Double_Window(230, 155, _("Crop data"));
608 		x1 = new Fl_Spinner(45, 25, 80, 25, _("From"));	x1->align(FL_ALIGN_TOP);
609 		x2 = new Fl_Spinner(140, 25, 80, 25, _("To"));	x2->align(FL_ALIGN_TOP);
610 		y1 = new Fl_Spinner(45, 55, 80, 25);
611 		y2 = new Fl_Spinner(140, 55, 80, 25);
612 		z1 = new Fl_Spinner(45, 85, 80, 25);
613 		z2 = new Fl_Spinner(140, 85, 80, 25);
614 
615 		new Fl_Box(15, 25, 25, 25, "X");
616 		new Fl_Box(15, 55, 25, 25, "Y");
617 		new Fl_Box(15, 85, 25, 25, "Z");
618 		Fl_Button *o;
619 		o = new Fl_Button(45, 120, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
620 		o->tooltip(_("Do nothing and close this window"));
621 		o = new Fl_Return_Button(145, 120, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
622 		o->tooltip(_("Change data values and close this window"));
623 		w->set_modal();	w->end();
624 	}
initCropDlg625 	void init()
626 	{
627 		long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
628 		x1->range(0,nx-1);	x1->value(0);
629 		x2->range(0,nx-1);	x2->value(nx-1);
630 		y1->range(0,nx-1);	y1->value(0);
631 		y2->range(0,nx-1);	y2->value(ny-1);
632 		z1->range(0,nx-1);	z1->value(0);
633 		z2->range(0,nx-1);	z2->value(nz-1);
634 	}
cb_okCropDlg635 	void cb_ok()
636 	{
637 		long n1,n2;
638 		HMDT d = dynamic_cast<HMDT>(dat);
639 		HADT c = dynamic_cast<HADT>(dat);
640 		n1=mgl_int(x1->value());	n2=mgl_int(x2->value());
641 		if(d)	d->Crop(n1,n2,'x');
642 		if(c)	c->Crop(n1,n2,'x');
643 		n1=mgl_int(y1->value());	n2=mgl_int(y2->value());
644 		if(d)	d->Crop(n1,n2,'y');
645 		if(c)	c->Crop(n1,n2,'y');
646 		n1=mgl_int(z1->value());	n2=mgl_int(z2->value());
647 		if(d)	d->Crop(n1,n2,'z');
648 		if(c)	c->Crop(n1,n2,'z');
649 		hide();
650 	}
runCropDlg651 	void run(mglDataA *d)
652 	{
653 		dat = d;	init();
654 		w->show();	while(w->shown())	Fl::wait();
655 	}
656 } crop_dlg;
657 //-----------------------------------------------------------------------------
crop_cb(Fl_Widget *,void * v)658 void crop_cb(Fl_Widget*, void*v)
659 {
660 	TableWindow* e = (TableWindow*)v;
661 	crop_dlg.run(e->var);	e->refresh();
662 }
663 //-----------------------------------------------------------------------------
664 struct TrspDlg : public GeneralDlg
665 {
666 	Fl_Choice *how;
667 public:
TrspDlgTrspDlg668 	TrspDlg() : GeneralDlg()
669 	{
670 		Fl_Menu_Item k[]={{"yxz"}, {"zxy"}, {"zyx"}, {"yzx"}, {"xzy"}, {0}};
671 		w = new Fl_Double_Window(200, 90, _("Transpose data"));
672 		how = new Fl_Choice(10, 20, 180, 25, _("New order of dimensions"));
673 		how->align(FL_ALIGN_TOP_LEFT);	how->copy(k);	how->value(0);
674 		Fl_Button *o;
675 		o = new Fl_Button(30, 55, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
676 		o->tooltip(_("Do nothing and close this window"));
677 		o = new Fl_Return_Button(115, 55, 75, 25, _("Do"));	o->callback(cb_dlg_ok,this);
678 		o->tooltip(_("Change data values and close this window"));
679 		w->set_modal();	w->end();
680 	}
cb_okTrspDlg681 	void cb_ok()
682 	{
683 		HMDT d = dynamic_cast<HMDT>(dat);
684 		HADT c = dynamic_cast<HADT>(dat);
685 		if(d)	d->Transpose(how->text());
686 		if(c)	c->Transpose(how->text());
687 		hide();
688 	}
runTrspDlg689 	void run(mglDataA *d)
690 	{
691 		dat = d;	init();
692 		w->show();	while(w->shown())	Fl::wait();
693 	}
694 } trsp_dlg;
695 //-----------------------------------------------------------------------------
transp_cb(Fl_Widget *,void * v)696 void transp_cb(Fl_Widget*, void*v)
697 {
698 	TableWindow* e = (TableWindow*)v;
699 	trsp_dlg.run(e->var);	e->refresh();
700 }
701 //-----------------------------------------------------------------------------
first_sl_cb(Fl_Widget *,void * v)702 void first_sl_cb(Fl_Widget*, void*v)
703 {
704 	TableWindow* e = (TableWindow*)v;
705 	e->slice->value(0);
706 	e->set_slice(0);
707 	e->go_home();
708 }
709 //-----------------------------------------------------------------------------
last_sl_cb(Fl_Widget *,void * v)710 void last_sl_cb(Fl_Widget*, void*v)
711 {
712 	TableWindow* e = (TableWindow*)v;
713 	e->slice->value(e->num_slice()-1);
714 	e->set_slice(e->num_slice()-1);
715 	e->go_home();
716 }
717 //-----------------------------------------------------------------------------
prev_sl_cb(Fl_Widget *,void * v)718 void prev_sl_cb(Fl_Widget*, void*v)
719 {
720 	TableWindow* e = (TableWindow*)v;
721 	int p = int(e->slice->value())-1;
722 	if(p<0)	p = 0;
723 	e->slice->value(p);		e->set_slice(p);
724 	e->go_home();
725 }
726 //-----------------------------------------------------------------------------
next_sl_cb(Fl_Widget *,void * v)727 void next_sl_cb(Fl_Widget*, void*v)
728 {
729 	TableWindow* e = (TableWindow*)v;
730 	int p = int(e->slice->value())+1;
731 	if(p>=e->num_slice())	p = e->num_slice()-1;
732 	e->slice->value(p);		e->set_slice(p);
733 	e->go_home();
734 }
735 //-----------------------------------------------------------------------------
first_cl_cb(Fl_Widget *,void * v)736 void first_cl_cb(Fl_Widget*, void*v)
737 {
738 	TableWindow* e = (TableWindow*)v;
739 	e->go_home();
740 }
741 //-----------------------------------------------------------------------------
change_sl_cb(Fl_Widget * w,void * v)742 void change_sl_cb(Fl_Widget*w, void*v)
743 {
744 	TableWindow* e = (TableWindow*)v;
745 	e->set_slice(long(e->slice->value()));
746 	e->go_home();
747 }
748 //-----------------------------------------------------------------------------
749 Fl_Menu_Item tablemenu[60] = {
750 	{ _("File"), 0, 0, 0, FL_SUBMENU },
751 		{ _("Load from file"),0, load_dat_cb },
752 		{ _("Import from PNG"),0, imp_dat_cb },
753 		{ _("Save to file"),	0, save_dat_cb },
754 		{ _("Export to PNG"),	0, exp_dat_cb, 0, FL_MENU_DIVIDER },
755 		{ _("Insert as 'list'"),0, list_dat_cb },
756 //		{ _("Plot data"),		0, plot_dat_cb },
757 //		{ _("Info for data"),	0, info_dat_cb },
758 		{ 0 },
759 	{ _("Sizes"), 0, 0, 0, FL_SUBMENU },
760 		{ _("Create new"),	0, new_dat_cb },
761 		{ _("Resize"),		0, resize_cb },
762 		{ _("Squeeze"),	0, squeeze_cb },
763 		{ _("Crop"),		0, crop_cb },
764 		{ _("Transpose"),	0, transp_cb },
765 //		{ _("Extend"),	0, extend_cb },
766 		{ 0 },
767 	{ _("Fill"), 0, 0, 0, FL_SUBMENU },
768 		{ _("By formula"),	0, modify_cb },
769 		{ _("In range"),	0, fill_cb },
770 		{ _("Normalize"),	0, normal_cb },
771 		{ 0 },
772 	{ _("Change"), 0, 0, 0, FL_SUBMENU },
773 		{ _("Smooth"),	0, smooth_cb },
774 		{ _("CumSum"),	0, cumsum_cb },
775 		{ _("Integrate"),	0, integr_cb },
776 		{ _("Difference"),0, diff_cb },
777 		{ _("Laplacian"),	0, diff2_cb },
778 		{ _("Swap parts"),0, swap_cb },
779 		{ _("Sin FFT"),	0, sinfft_cb },
780 		{ _("Cos FFT"),	0, cosfft_cb },
781 		{ _("Hankel"),	0, hankel_cb },
782 //		{ _("Wavelet"),	0, wavelet_cb },
783 		{ _("Mirror"),	0, mirror_cb },
784 		{ _("Roll"),		0, roll_cb },
785 		{ _("Sew phase"),	0, sew_cb },
786 		{ _("Envelop"),	0, envelop_cb },
787 		{ 0 },
788 	{ _("Another"), 0, 0, 0, FL_SUBMENU },
789 //		{ _("Histogram of"),	0, hist_cb },
790 		{ _("Summation of"),	0, asum_cb },
791 		{ _("Maximum of"),	0, amax_cb },
792 		{ _("Minimum of"),	0, amin_cb },
793 		{ _("Pulse prop."),	0, pulse_cb },
794 		{ 0 },
795 	{ _("Operations"), 0, 0, 0, FL_SUBMENU },
796 		{ _("Add to"),		0, addto_cb },
797 		{ _("Subtract to"),0, subto_cb },
798 		{ _("Multiply by"),0, multo_cb },
799 		{ _("Divide by"),	0, divto_cb },
800 		{ 0 },
801 	{ _("Navigation"), 0, 0, 0, FL_SUBMENU },
802 		{ _("First slice"), FL_CTRL + FL_F + 1, first_sl_cb },
803 		{ _("Prev slice"), FL_CTRL + FL_F + 2, prev_sl_cb },
804 		{ _("Next slice"), FL_CTRL + FL_F + 3, next_sl_cb },
805 		{ _("Last slice"),	FL_CTRL + FL_F + 4, last_sl_cb, 0, FL_MENU_DIVIDER },
806 		{ _("First cell"), FL_ALT + FL_F + 1, first_cl_cb },
807 //		{ _("Last cell"), FL_ALT + FL_F + 2, last_cl_cb },
808 //		{ _("Center grid"), FL_ALT + FL_F + 3, center_cl_cb },
809 		{ 0 },
810 	{ 0 }
811 };
812 //-----------------------------------------------------------------------------
plot_dat_cb(Fl_Widget *,void * v)813 void plot_dat_cb(Fl_Widget*,void *v)
814 {
815 	TableWindow *e=(TableWindow*)v;
816 	info_dlg_cb(e->var);
817 }
818 //-----------------------------------------------------------------------------
819 #include "../widgets/image.h"
820 #include "xpm/document-import.xpm"
821 #include "xpm/document-export.xpm"
822 #include "xpm/diff.xpm"
823 #include "xpm/func.xpm"
824 #include "xpm/size.xpm"
825 #include "xpm/tran.xpm"
826 #include "xpm/crop.xpm"
827 #include "xpm/go-first.xpm"
828 #include "xpm/go-last.xpm"
TableWindow(ScriptWindow * e)829 TableWindow::TableWindow(ScriptWindow *e)
830 {
831 	main = e;
832 	const int ww = 600, hh = 430;	// initial width (>300) and height (>430)
833 	w = new Fl_Double_Window(ww,430);		var = 0;
834 	menu = new Fl_Menu_Bar(0, 0, ww, 30);	menu->copy(tablemenu, this);
835 	Fl_Button *o;
836 	Fl_Group *g = new Fl_Group(0,0,30,350);
837 	o = new Fl_Button(0, 30, 25, 25);	o->image(img_new);
838 	o->callback(new_dat_cb,this);		o->tooltip(_("Create new data with zero filling"));
839 	o = new Fl_Button(0, 55, 25, 25);	o->image(img_load);
840 	o->callback(load_dat_cb,this);		o->tooltip(_("Load data from file"));
841 	o = new Fl_Button(0, 80, 25, 25);	o->image(new Fl_Pixmap(document_import_xpm));
842 	o->callback(imp_dat_cb,this);		o->tooltip(_("Import data from PNG file"));
843 	o = new Fl_Button(0, 105, 25, 25);	o->image(img_save);
844 	o->callback(save_dat_cb,this);		o->tooltip(_("Save data to file"));
845 	o = new Fl_Button(0, 130, 25, 25);	o->image(new Fl_Pixmap(document_export_xpm));
846 	o->callback(exp_dat_cb,this);		o->tooltip(_("Export data to PNG file"));
847 
848 	o = new Fl_Button(0, 160, 25, 25);	o->image(img_insert);
849 	o->callback(list_dat_cb,this);		o->tooltip(_("Insert to script as 'list' command"));
850 	o = new Fl_Button(0, 185, 25, 25);	o->image(img_plot);
851 	o->callback(plot_dat_cb,this);		o->tooltip(_("Data information and preview."));
852 
853 	o = new Fl_Button(0, 215, 25, 25);	o->image(new Fl_Pixmap(diff_xpm));
854 	o->callback(smooth_cb,this);		o->tooltip(_("Apply operator (smoothing, integration, difference ...) to data"));
855 	o = new Fl_Button(0, 240, 25, 25);	o->image(new Fl_Pixmap(func_xpm));
856 	o->callback(modify_cb,this);		o->tooltip(_("Fill data by formula"));
857 	o = new Fl_Button(0, 265, 25, 25);	o->image(new Fl_Pixmap(size_xpm));
858 	o->callback(resize_cb,this);		o->tooltip(_("Resize data with smoothing"));
859 	o = new Fl_Button(0, 290, 25, 25);	o->image(new Fl_Pixmap(crop_xpm));
860 	o->callback(crop_cb,this);		o->tooltip(_("Crop (cut off edges) data"));
861 	o = new Fl_Button(0, 315, 25, 25);	o->image(new Fl_Pixmap(tran_xpm));
862 	o->callback(transp_cb,this);		o->tooltip(_("Transpose data dimensions"));
863 	g->end();	g->resizable(0);
864 
865 	g = new Fl_Group(30, 30, 200, 30);
866 	o = new Fl_Button(30, 30, 25, 25);	o->image(new Fl_Pixmap(go_first_xpm));
867 	o->callback(first_sl_cb,this);		o->tooltip(_("Go to first slice for 3D data (Ctrl-F1)."));
868 	slice = new Fl_Counter(55, 30, 90, 25, 0);	slice->callback(change_sl_cb,this);
869 	slice->lstep(10);	slice->step(1);	slice->tooltip(_("Id of slice on third (z-) dimension"));
870 	o = new Fl_Button(147, 30, 25, 25);	o->image(new Fl_Pixmap(go_last_xpm));
871 	o->callback(last_sl_cb,this);		o->tooltip(_("Go to last slice for 3D data (Ctrl-F4)."));
872 	g->end();	g->resizable(0);
873 
874 	data = new Fl_Data_Table(30,60,ww-30,hh-60);
875 	data->row_header(1);	data->row_header_width(80);
876 	data->row_resize(1);	data->rows(1);
877 	data->row_height_all(25);
878 	data->col_header(1);	data->col_header_height(25);
879 	data->col_resize(1);	data->cols(1);
880 	data->col_width_all(80);
881 	data->tooltip(_("Colors denote values: magenta - local max, cyan - local min,\n"
882 	"\tred - Re(v)>0, blue - Re(v)<0, purple - Im(v)>0, teal - Im(v)<0."));
883 
884 	w->end();	w->resizable(data);
885 }
886 //-----------------------------------------------------------------------------
~TableWindow()887 TableWindow::~TableWindow()	{	if(var)	var->o=NULL;	Fl::delete_widget(w);	}
888 //-----------------------------------------------------------------------------
delete_cb(void * v)889 void delete_cb(void *v)
890 {
891 	if(v)
892 	{
893 		TableWindow *w = (TableWindow *)v;
894 		w->var->o=NULL;		delete w;
895 	}
896 }
897 //-----------------------------------------------------------------------------
update(mglDataA * v)898 void TableWindow::update(mglDataA *v)
899 {
900 	static std::string name;
901 	if(v==0)	return;
902 	name = wcstombs(v->Name());
903 	w->label(name.c_str());
904 	v->func = delete_cb;
905 	if(var)	var->o = 0;
906 	var = v; 	v->o = this;
907 	refresh();
908 }
909 //-----------------------------------------------------------------------------
refresh()910 void TableWindow::refresh()
911 {
912 	if(var==0)	return;
913 	w->deactivate();	nz = var->GetNz();
914 	sl = 0;	slice->range(0,nz-1);
915 
916 	data->rows(var->GetNy());	data->cols(var->GetNx());
917 	data->ny = var->GetNy();	data->nx = var->GetNx();
918 	data->data = var;
919 	w->activate();
920 //	show();
921 }
922 //-----------------------------------------------------------------------------
set_slice(long s)923 void TableWindow::set_slice(long s)
924 {
925 	if(s>=0 && s<nz)
926 	{
927 		data->sl = sl = s;
928 		refresh();
929 	}
930 }
931 //-----------------------------------------------------------------------------
go_home()932 void TableWindow::go_home()
933 {
934 }
935 //-----------------------------------------------------------------------------
936