/*******************************************************************************
+
+  LEDA 3.5
+
+  base_window.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef LEDA_BASE_WINDOW_H
#define LEDA_BASE_WINDOW_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350016
#include <LEDA/REDEFINE_NAMES.h>
#endif


#include <LEDA/system.h>
#include <LEDA/impl/x_window.h>
#include <LEDA/color.h>


#define MOUSE_BUTTON(i) (-i)       

#define NO_BUTTON -16

class BASE_WINDOW;

typedef double (*win_draw_func) (double);
typedef void   (*win_redraw_func0) ();
typedef void   (*win_redraw_func1) (BASE_WINDOW*);
typedef void   (*win_redraw_func2) (BASE_WINDOW*,double,double,double,double);
typedef void   (*mouse_action_func) (double,double);
typedef void   (*panel_action_func)(int);
typedef void   (*panel_str_action_func)(char*);

typedef void   (*coord_handler_func)(BASE_WINDOW*,double,double);


//------------------------------------------------------------------------------
// panel items
//------------------------------------------------------------------------------

enum { Text_Item, 
       String_Item, 
       String_Menu_Item, 
       Int_Item, 
       Slider_Item, 
       Float_Item, 
       Button_Item, 
       Choice_Item,
       Choice_Mult_Item,
       Bool_Item,
       Color_Item,
       Bitmap_Choice_Item,
       Bitmap_Choice_Mult_Item,
       Newline_Item,
       Space_Item,
       Fill_Item };


class Panel_Item {

int    enabled;
int    index;
int    kind;
char*  label_str;
char*  data_str;
char*  help_str;
void*  ref;
int    xcoord;
int    ycoord;
int    width;
int    height;
int    dat1;     // min (slider)
int    dat2;     // max (slider)  step (choice)
int    offset;   // choice item
int    argc;     // choice item, string_menu_item
char** argv;  

BASE_WINDOW*  menu_win;

Panel_Item*   menu_but;

panel_action_func action;
panel_str_action_func str_action;

Panel_Item(int,const char*,void*,int,int);
~Panel_Item();

friend class BASE_WINDOW;

friend void str_menu_selection(int sel);

};

typedef Panel_Item* panel_item;

#define MAX_ITEM_NUM 256 



class BASE_WINDOW {

friend class window;
friend class panel;
friend class menu;
friend class GraphWin;

friend void str_menu_selection(int sel);

private: 

// LEDA windows cannot be copied, use reference parameters! 

BASE_WINDOW(const BASE_WINDOW&) { }
BASE_WINDOW& operator=(const BASE_WINDOW&) { return *this; }


// functions telling me how to access strings

virtual char* access_str(void*);
virtual void  assign_str(void*, const char*);

BASE_WINDOW* win_parent;   // window parent
BASE_WINDOW* p_win;        // window parent (panel/menu)
BASE_WINDOW* p_root;       // window root   (panel/menu)

int draw_win;

char default_frame_label[128];

mouse_action_func mouse_action;

win_redraw_func0     redraw0;
win_redraw_func1     redraw1;
win_redraw_func2     redraw2;

win_redraw_func1     timer_action;

coord_handler_func   coord_handler;


int show_grid_cursor;

// pixel coordinates
int xdots;
int ydots;
int xorigin;
int yorigin;


// mouse button return values

int button_table[4];  
int shift_table[4];

// mouse data

int mouse_key;
int mouse_xpix;
int mouse_ypix;

unsigned long mouse_press_time;
unsigned long mouse_release_time;
unsigned long event_time;

double mouse_xreal;
double mouse_yreal;
double mouse_last_xreal;
double mouse_last_yreal;
double mouse_start_xreal;
double mouse_start_yreal;

// shift key state of last event
int shift_key_state;  


char* mesg_list[64];
int   mesg_count;

//window coordinates
double max_xcoord;
double min_xcoord;
double max_ycoord;
double min_ycoord;
double scaling;

//window geometry
int window_xpos;
int window_ypos;
int window_width;
int window_height;

// hot area
int hotx1;
int hotx2;
int hoty1;
int hoty2;


int grid_mode;
int node_width;
int win_flush;

int panel_enabled;

// user defined data slots

void* data[1];


// static data members

static void REDRAW_FUNC(void* p);
static BASE_WINDOW*  read_window; 
static BASE_WINDOW*  active_window; 
static int win_count;

protected:

static BASE_WINDOW*  call_window; 

panel_item  owner_item;


private:

void cursor(void);

static int event_handler(BASE_WINDOW*&,int blocking = 1);

#if defined(unix)
static void timer_handler(int);
#endif

static void mouse_default_action(double,double);
static void mouse_segment_action(double x, double y) ;
static void mouse_rect_action(double x, double y);
static void mouse_circle_action(double x, double y);

void set_color(int c);
void draw_grid(int,int,int,int);
void draw_messages(void);
void clipping(int mode);


public:

void draw_grid();

void* get_inf();
void* set_inf(void*); 


int state;
int fg_color;
int bg_color;

static int screen_width(void);
static int screen_height(void);

static void quit_action(int);

// set and read mouse button return values

void set_buttons(int b0, int b1, int b2, int b3, 
                 int s0=0, int s1=-1, int s2=-2, int s3=-3);
void set_buttons(int* new_value, int* save_values=0);
void std_buttons(int* save_values=0);
void old_buttons(int* save_values=0);

int  mouse_button_val(int i) { return button_table[i]; }
int  mouse_shift_val(int i) { return shift_table[i]; }


// setting parameters

void set_coord_handler(coord_handler_func f);

void set_show_coordinates(int x) 
{ coord_handler = (x) ? default_coord_handler : 0; }

void set_show_cursor(int x)      { show_grid_cursor = x; }

void set_redraw(win_redraw_func0);
void set_redraw(win_redraw_func1);
void set_redraw(win_redraw_func2);

int load_text_font(const char* fname);
int load_bold_font(const char* fname);
int load_fixed_font(const char* fname);

int set_bg_color(int);
int set_fg_color(int);


int          set_font(const char* s);
void         set_grid_mode(int i);
line_style   set_line_style(line_style s);
int          set_join_style(int s);
int          set_line_width(int w);
drawing_mode set_mode(drawing_mode m);
int          set_node_width(int w);
text_mode    set_text_mode(text_mode m);
void         set_frame_label(const char* s);
void         reset_frame_label();
void         set_flush(int b) { win_flush = b; }

void set_icon_pixrect(char*);

int          get_line_width();
line_style   get_line_style();
drawing_mode get_mode();
text_mode    get_text_mode();

int get_node_width() { return node_width; }
int get_grid_mode()  { return grid_mode; }
int get_fg_color()   { return fg_color; }
int get_bg_color()   { return bg_color; }

double  text_width(const char*);
double  text_height(const char*);


int    mono();

double xmin()  { return min_xcoord; }
double xmax()  { return max_xcoord; }
double ymin()  { return min_ycoord; }
double ymax()  { return max_ycoord; }
double scale() { return scaling; }

int xpos() { return window_xpos; }
int ypos() { return window_ypos; }
int width() { return window_width; }
int height() { return window_height; }

int xpix(double xcoord);
int ypix(double ycoord);

double xreal(int xpix);
double yreal(int ypix);

double pix_to_real(int p);
int    real_to_pix(double d);



double pix_num(int p)        { return p/scaling; }



void create(float w_width, float w_height, const char* label);
void display(int w_xpos, int w_ypos, BASE_WINDOW* parent = 0);

void resize(int width, int height);

void close();
void init(double x0, double x1, double y0, int g_mode=0);
void configure();
void flush();


int panel_open(int,int,BASE_WINDOW*);

int  is_open();
int  is_closed();


 BASE_WINDOW(float width,float height, const char *frame_label = "");
 BASE_WINDOW(const char* frame_label);
 BASE_WINDOW();

virtual ~BASE_WINDOW();



// events & mouse input

void grab_mouse();
void ungrab_mouse();

int  read_event(int& val, double& x, double& y);
int  read_event(int& val, double& x, double& y, unsigned long& t);
int  read_event(int& val, double& x, double& y, unsigned long& t, int timeout);
int  get_event(int& val, double& x, double& y);

int read_mouse_action(mouse_action_func action, double xstart, 
                      double ystart, double& x, double& y);

int read_mouse(int kind, double xstart, double ystart, double& x, double& y);

int read_mouse(double& x, double& y) 
{ return read_mouse(0,0,0,x,y); }

int read_mouse() 
{ double x,y; 
  return read_mouse(x,y); 
 }

int get_mouse(double& x, double& y);

int get_mouse()
{ double x,y; 
  return get_mouse(x,y); 
 }



static void default_coord_handler(BASE_WINDOW*,double,double);

static int read_mouse(BASE_WINDOW*&,double&,double&);
static int get_mouse(BASE_WINDOW*&,double&,double&);

static int  read_event(BASE_WINDOW*&, int& val, double& x, double& y);
static int  get_event(BASE_WINDOW*&, int& val, double& x, double& y);
static void put_back_event();


unsigned long button_press_time();
unsigned long button_release_time();

// wait for panel button

int read_menu();


// get shift key info for last handled mouse button event

int shift_key_down();
int ctrl_key_down();
int alt_key_down();

// timer

void start_timer(int msec, win_redraw_func1 = 0);
void stop_timer();


int query_pix(double x, double y);

// drawing

void draw_pix(double x, double y, int col=black);
void draw_pixels(int, double*, double*, int col=black);
void draw_point(double x, double y, int col=black);
void draw_segment(double x1, double y1, double x2, double y2, int col=black);
void draw_segments(int, double*, double*, double*, double*, int col=black);
void draw_line(double x1, double y1, double x2, double y2, int col=black);
void draw_ray(double x1, double y1, double x2, double y2, int col=black);

void draw_node(double x0, double y0, int col=black);
void draw_filled_node(double x0, double y0, int col=black);
void draw_text_node(double x0, double y0, const char *s, int col=white);
void draw_int_node(double x0, double y0, int i, int col=white);

void draw_edge(double x1, double y1, double x2, double y2, int col=black);

void draw_circle(double x0, double y0, double r, int col=black);
void draw_filled_circle(double x0, double y0, double r, int col=black);
void draw_ellipse(double x0, double y0, double a, double b, int col=black);
void draw_filled_ellipse(double x0, double y0, double a, double b, int col=black);
void draw_arc(double x0, double y0, double r1, double r2, double start, double angle, int col=black);
void draw_filled_arc(double x0, double y0, double r1, double r2, double start, double angle, int col=black);

void draw_polygon(int n, double *xcoord, double *ycoord, int col=black);
void draw_filled_polygon(int n, double *xcoord, double *ycoord, int col=black);
void draw_rectangle(double x1, double y1, double x2, double y2, int col=black);
void draw_filled_rectangle(double x1, double y1, double x2, double y2, int col=black);


void plot_xy(double x0, double x1, win_draw_func f, int col=black);
void plot_yx(double y0, double y1, win_draw_func f, int col=black);

// text

void draw_text(double x, double y, const char* s, int col=black);
void draw_ctext(double x, double y, const char* s, int col=black);


// misc

void draw_frame();
void clear(int col=white);

void message(const char *s);
void del_messages(void);

char* create_bitmap(int w, int h, char* data);
void  put_bitmap(double x, double y, char* bmap, int col=black);
void  del_bitmap(char*);

char* create_pixrect(int w, int h, char* data, int fc=black, int bc=white);
char* create_pixrect(char**);

char* get_pixrect(double x1, double y1, double x2, double y2);
char* get_window_pixrect();
char* get_buffer_pixrect();
void  put_pixrect(double x, double y, char*);
void  put_pixrect(double x, double y, char*,int,int,int,int);
void  put_pixrect(char*);
void  del_pixrect(char*);
void  copy_rect(double x1, double y1, double x2, double y2, double x, double y);

int   get_width(char*);
int   get_height(char*);

int  create_buffer();
void delete_buffer();
void flush_buffer(double,double,double,double);
void flush_buffer(double dx, double dy, double,double,double,double);
void flush_buffer();
void flush_buffer(double,double);
void start_buffering();
void start_buffering(int,int);
void stop_buffering();



//------------------------------------------------------------------------------
// panel section
//------------------------------------------------------------------------------

private:

panel_item  Item[MAX_ITEM_NUM];

int but_count;
int orig_but_count;
int item_count;


int panel_bg_color;
int item_bg_color;
int d3_box_bg_color;
int shadow_color;
int press_color;
int bitmap_color0;
int bitmap_color1;
int disable_color;

int panel_width;
int panel_height;

int   th;               // text height
int   tw;               // text width
int   xoff;             // left and right boundary space
int   yoff;             // top and bottom boundary space
int   label_w;          // label width
int   sl_num_w;         // width of numerical fields in sliders
int   slider_w;         // slider item length
int   slider_h;         // height of slider items  
int   string_w;         // string item length
int   string_h;         // string item height
int   number_w;         // int/float item length
int   number_h;         // int/float item height
int   choice_h;         // height of choice items
int   color_h;          // height of color items
int   choice_w;         // choice field width
int   button_h;         // button height
int   button_w;         // button width
int   ytskip;           // height of text items
int   yskip;            // height of other items
int   buts_per_line;    // number of buttons in line
int   menu_button_style;     

int   center_button_label; // if true center text on buttons

panel_item act_str_item;
panel_item last_sel_button;

int panel_menu_mode;

int has_menu_bar;

panel_item new_panel_item(int,const char*,void*,int,const char*);

void draw_label_str(int x, int y, const char* str, int enabled, int center);
void draw_label(panel_item);
void draw_box_with_shadow(int,int,int,int,int,int);
void draw_d3_box(int x1,int y1,int x2,int y2, int pressed, int enabled=1);
void draw_string_item(panel_item i, const char* s=0);
void activate_string_item(panel_item,int);
void panel_text_edit(panel_item i);
void put_text_item(int x, int y, const char* s, int t_len);
int  draw_text_item(panel_item i, int);
void draw_choice_item(panel_item i,int x);
void draw_bool_item(panel_item i);
void draw_color_button(int xt, int yt, int w, int col, int pressed, int enabled=1);
void draw_color_item(panel_item i);
void change_color_item(panel_item i, int j);
void draw_slider_item(panel_item i,int x);
void draw_bitmap_choice_item(panel_item i);
void change_bitmap_choice_item(panel_item i, int j);
void draw_button(panel_item i,int pressed);
void draw_menu_button(panel_item i,int pressed);
void draw_menu_item(panel_item i,int pressed);
void draw_down_menu_button(int x, int y,int pressed, int enabled);
void draw_right_menu_button(int x, int y,int pressed, int enabled);
void draw_left_menu_button(int x, int y,int pressed, int enabled);

void item_error();

void open_sub_panel(panel_item);
void close_sub_panel(BASE_WINDOW*);

int  panel_event_handler(int w, int k, int b, int x, int y, unsigned long t);

void panel_init();
void place_panel_items();
void draw_panel_items();

public:

void redraw_panel(panel_item=0);

void make_menu_bar();

void buttons_per_line(int n) 
{ buts_per_line = n; }

void set_menu_button_style(int n)   
{ menu_button_style = n; }

void set_bitmap_colors(int c0, int c1)
{ bitmap_color0 = c0; bitmap_color1 = c1; }

void set_panel_bg_color(int c) { panel_bg_color = c; }


panel_item text_item(const char*);

panel_item string_item(const char*, void* x, panel_str_action_func,
                                             const char* hlp);

void add_menu(panel_item,int,const char**);

panel_item string_menu_item(const char*, void* x, const char* menu_label, 
                            int argc, const char** argv, panel_str_action_func,
                                                         const char* hlp);

panel_item int_item(const char*, int* x,const char* hlp);
panel_item slider_item(const char*,int* x,int min,int max, panel_action_func,
                                                             const char* hlp);
panel_item float_item(const char*, double* x, const char* hlp);

panel_item bool_item(const char* text, char* address, panel_action_func,
                                                      const char* hlp);

panel_item color_item(const char* text, int* x, panel_action_func, 
                                                const char* hlp);


//choice items
panel_item choice_item(const char* text, int* address, int argc, 
                       const char** argv, int step, int offset, 
                       panel_action_func, const char* hlp);

panel_item choice_mult_item(const char* text,int* address,int argc,
                            const char** argv, panel_action_func, 
                            const char* hlp);

panel_item bitmap_choice_item(const char* label, int *address, int argc,
                              int width, int height, char **argv, 
                              panel_action_func, const char* hlp);

panel_item bitmap_choice_mult_item(const char* label, int *address, int argc,
                                  int width, int height, char **argv,
                                  panel_action_func, const char* hlp);



//buttons
int button(const char*, int val, panel_action_func F, const char* hlp=0);
int button(const char*, int val, BASE_WINDOW* p,const char* hlp=0);
int button(int w, int h, char* bm, const char* s, int val, panel_action_func F,
                                                           const char* hlp=0);
int button(int w, int h, char* bm, const char* s, int val, BASE_WINDOW* p,
                                                           const char* hlp=0);
int menu_button(const char*, int val, BASE_WINDOW* p, const char* hlp=0);

void new_line();
void hspace(int);
void vspace(int);
void fill_line();


// manipulation of panel items

void enable_panel()  { panel_enabled = 1; }
void disable_panel() { panel_enabled = 0; }

void enable_item(panel_item);
void disable_item(panel_item);

void enable_button(int);
void disable_button(int);

int          get_kind(panel_item it) { return it->kind; }
const char*  get_label(panel_item it) { return it->label_str; }
int          is_enabled(panel_item it) { return it->enabled; }

// iteration
panel_item first_item();
panel_item next_item(panel_item);


BASE_WINDOW* get_window(const char* s);
BASE_WINDOW* set_window(const char* s, BASE_WINDOW* p);


static int text_color(int);

};


inline int BASE_WINDOW::text_color(int col)
{ if (col==black || col==red || col==blue || col==violet || col==brown 
      || col==pink || col==blue2 || col==grey3) 
     return white;
  else
     return black;
}





// some useful functions

char* Read_Leda_Bitmap(const char* fname, int& w, int& h) ;





#if LEDA_ROOT_INCL_ID == 350016
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif

#endif
