// fltk code to draw a simple y=x^a function
// (C) Matteo Lucarelli 2006
// fastcompile cmd: fltk --compile fer-con.cxx

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Hor_Value_Slider.H>
#include <FL/fl_draw.H>
#include <math.h>
#include <errno.h>

// slides values
const char* name[2] = { "SCALE", "EXP"};
double arg[2]      = {   10  ,  1  };
double limit[2][3]  = {{0.1,100,0.01},{-10,10,0.01}};

class Drawing : public Fl_Widget {
	// overwriting of draw function
	void draw() {
		double cx,cy;
		int i;
		
		// to clip all draw inside the widget
		fl_push_clip(x(),y(),w(),h());
		
		// background
		fl_color(FL_WHITE);
		fl_rectf(x(),y(),w(),h());
		
		// transformation matrix
		fl_push_matrix();
		fl_translate(x(),y());
		fl_scale(w()/(arg[0]*2),h()/(arg[0]*2));
		fl_mult_matrix(1,0,0,-1,arg[0],arg[0]);

		// axis
		fl_color(FL_RED);
		fl_begin_line();
		fl_vertex(-arg[0],0);
		fl_vertex(arg[0],0);		
		fl_end_line();		
		fl_begin_line();
		fl_vertex(0,-arg[0]);
		fl_vertex(0,arg[0]);		
		fl_end_line();
		
		// the function
		fl_color(FL_BLACK);
		fl_line_style(FL_SOLID);
		fl_begin_line();
		for (cx=0;cx<=arg[0];cx+=2*arg[0]/w()){
			cy=pow(cx,arg[1]);
			if ((cy<=100*arg[0])&&(cy>=-100*arg[0])) fl_vertex(cx,cy);
		}
		fl_end_line();
		fl_begin_line();
		for (cx=0;cx>=-arg[0];cx-=2*arg[0]/w()){
			cy=pow(cx,arg[1]);
			if ((cy<=100*arg[0])&&(cy>=-100*arg[0])) fl_vertex(cx,cy);
		}
		fl_end_line();
		
		fl_pop_matrix();
		fl_pop_clip();
	}
	public:
		Drawing(int X,int Y,int W,int H) : Fl_Widget(X,Y,W,H) {}
};

Drawing *d;

// the sliders callback
void slider_cb(Fl_Widget* o, void* v) 
{
	Fl_Slider* s = (Fl_Slider*)o;
	arg[long(v)] = s->value();
	d->redraw();
}

int main(int argc, char** argv) 
{
	Fl_Double_Window win(300,350);
	win.label("f(x): x^EXP");
	
	Drawing drawing(10,10,280,280);
	d = &drawing;
	win.resizable(d);

	int y = 300;
	for (int n = 0; n<2; n++) {
		Fl_Slider* s = new Fl_Hor_Value_Slider(70,300+20*n,220,20,name[n]);
		s->minimum(limit[n][0]); s->maximum(limit[n][1]);
		s->step(limit[n][2]);
		s->value(arg[n]);
		s->align(FL_ALIGN_LEFT);
		s->callback(slider_cb, (void*)n);
	}
	win.end();
	win.show(argc,argv);
	return Fl::run();
}

