#define call_pr printf("calling = %s\n",__PRETTY_FUNCTION__)

struct string {
  char *descr;
  string(char *descr) : descr(descr) {}
};

// attach a vector (in NR format) for display
// gamma = y-magnification factor 
struct disp_vector : public string { 
  float *vect;
  float gamma, y0;
  disp_vector(float *vect, char *descr, float gamma = 1.0, 
	     float y0 = 0.0) : vect(vect), string(descr), 
             gamma(gamma), y0(y0) { }
};

// operator function for one-dimensional problems
struct one_solver : public string {
  void (*func)(int);
  one_solver(void (*func)(int), char *descr) : func(func), string(descr) {}
};

// 3 modes for computing z-factor (gamma) 
// zauto : automatic adaption at each step
// zinit : adaption only at initial step, then constant
// zfixed : user defined (in constructor value given)

extern char *zauto, *zinit, *zfixed; 

// attach a double array (in NR format) to a lattice display
struct disp_array : public string { 
  double **array;
  float gamma, z0;
  char *zmode;
  disp_array(double **array, char *descr, float gamma, 
	     float z0 = 0.0) : array(array), string(descr), 
             gamma(gamma),  z0(z0) { zmode = zfixed; }
  
  disp_array(double **array, char *descr, char *zmode = zauto, 
	     float z0 = 0.0) : array(array), string(descr), 
             z0(z0), zmode(zmode) { gamma = 1.0; } // value not used
};

struct two_solver : public string {
  void (*func)(int,int);
  two_solver(void (*func)(int,int), char *descr) : func(func), string(descr) {}
};

// nr_scrollbars && nr_main
#include "window.h"
typedef void (*VVPF)(void*, float); // scrollbar cb

class nr_scrollbar;

// main_window with polling handling for scrollbars and rotating
class poll_main : public main_window {  
protected:
  int bh; // height of menu_bar = 20
  nr_scrollbar *scr; // the *active* scrollbar
  Bool top; 
  menu_bar *mb;
public:
  static poll_main *top_main;
  poll_main(char *name, int ww = 600, int wh = 300);
  virtual void polling_handler(); // virtual function of main_window

  virtual void solve_it() = 0; // call special solvers and redraw
  // install act_scr as active and toggle polling_mode
  void switch_mode(nr_scrollbar *act_scr);
};

class nr_scrollbar : public tick_scrollbar {
  float *fptr,fdel;
  poll_main *pm; 
  // called when setting the slider, or indirectly from step_xxx
  void updated() { *fptr = value; if (pm) pm->solve_it(); }
public:
  // button callback functions :
  void step_fwd() { if (value < max) change(value+fdel); } 
  void step_bck() { if (value > min) change(value-fdel); } 
  void reset() { change(min); }

  Bool play_mode;
  nr_scrollbar(window &parent, int w, int x, int y, int n_ticks, 
	       float *fptr, poll_main *pm, float minp = 0, float maxp = 100, 
	       float fdel = 1);
};

// interface class for constructing scrollbars
class parameter : public string {
public:
  float *fptr; // the value to alter
  float fmin,fmax,fdel; // scrollbar limits and delta value 

  parameter(char *descr, float *fptr, 
	     float fmin = 0, float fmax = 100, float fdel = 1) 
    : string(descr), fptr(fptr), fmin(fmin), fmax(fmax), fdel(fdel) { }
    
  nr_scrollbar* make_scrollbar(window *parent, poll_main *pm, int y) {
    new text_win(*parent,descr,parent->width,20,0,y);
    return new nr_scrollbar(*parent,parent->width,0,y+20,9,fptr,pm,
			    fmin,fmax,fdel);
  }
  void check() {
    if (*fptr <= fmin || *fptr >= fmax) *fptr = 0.5*(fmin+fmax);
  }
};

// specialized coord_window 
class nr_coord : public coord_window {  
  int nx;
public:
  disp_vector **dv; // zero terminated list of vectors to display
  nr_coord(window & parent, int nx, disp_vector **dv, 
	   int w, int h, int x, int y) :
  coord_window(parent,w,h,x,y), nx(nx), dv(dv) {} 
  void draw_vector(float *fv) {
    for (int i = 1; i < nx; i++) wline(i,fv[i],i+1,fv[i+1]);
  }
  virtual void draw_interior() {
    draw_coords();
    x_ticks(100.0);
    y_ticks(1.0);
 
    if (dv == 0) return;
    int i = 0;
    disp_vector *dvi = dv[i]; 
    unsigned cols[4] = { black, Red, Blue, Green };
    while (dvi) {
      set_color(cols[i % 4]); // use colors cylically
      int w = 6*strlen(dvi->descr); // right oriented
      DrawString(width-w-5,i*12+12,dvi->descr);
      // printf(" %d %s\n",i,dvi->descr);
      draw_vector(dvi->vect);
      dvi = dv[++i];
    }
    set_color(black);
  }
};

extern char info_text[]; // to display infos in windows from one_solvers

class one_main : public poll_main {  
public:
  info_window *infw;
  nr_coord *cw;  
  int nx;
  disp_vector **dv; 
  one_solver **sv; // list of solvers
  one_solver *svact; // actual solver

  // hc is vertical position of cw   
  one_main(char *name, int nx, disp_vector **dv, one_solver **sv, 
	   int ww = 600, int wh = 400, int hc = 20);
  
  virtual void solve_it();
  virtual void action(char* menu, char* value); 
  virtual void redraw() { 
    // call_pr;
    cw->redraw(); infw->redraw(); 
  }
};

// interface function for simple creating a onedim interactive visualization
void one_show(char *name, int n, disp_vector **dv, one_solver **sv, 
	      parameter **scr = 0);

// interface function for two_main creating 
void two_show(char *name, int nx, int ny, disp_array **da, two_solver **sv,
	      parameter **scr = 0);

