_leda_panel.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:26k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _leda_panel.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. // defines the LEDA_PANEL operations declared in <LEDA/leda_panel.h>
  12. // using the basic graphics routines from <LEDA/impl/x_basic.h>
  13. #include <LEDA/leda_panel.h>
  14. #include <LEDA/impl/x_basic.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <stdlib.h>
  19. enum { Text_Item, 
  20.        String_Item, 
  21.        String_Menu_Item, 
  22.        Int_Item, 
  23.        Slider_Item, 
  24.        Float_Item, 
  25.        Button_Item, 
  26.        Choice_Item,
  27.        Bool_Item,
  28.        Color_Item };
  29. static char* duplicate_string(const char* p)
  30. { char* q = new char[strlen(p)+1];
  31.   if (q==0) 
  32.   { fprintf(stderr,"duplicate_string: out of memory");
  33.     abort();
  34.    }
  35.   strcpy(q,p);
  36.   return q;
  37. }
  38. static char* make_string(int x)
  39. { char str[256];
  40.   sprintf(str,"%d",x);
  41.   return duplicate_string(str);
  42.  }
  43. static char* make_string(double x)
  44. { char str[256];
  45.   sprintf(str,"%f",x);
  46.   return duplicate_string(str);
  47.  }
  48. void LEDA_PANEL::panel_redraw_func() 
  49. { if (active_window)
  50.   { LEDA_PANEL* p = (LEDA_PANEL*)active_window; 
  51.     p->open(p->XPOS, p->YPOS, 0, 0, 0, 0, 0); 
  52.    }
  53.  }
  54. void LEDA_PANEL::init(const char* s)
  55. { open_display();
  56.   header = duplicate_string(s);
  57.   XPOS = -1;
  58.   YPOS = -1;
  59.   but_layout = 0;
  60.   item_count = 0;
  61.   but_count = 0;
  62.   win = 0;
  63.   item_bg_color  = white;
  64.   bg_color       = grey1;
  65.   press_color    = grey2;
  66.   shadow_color   = grey3;
  67.   tw = text_width("H");
  68.   th = text_height("H");
  69.   ytskip   = th + 2;
  70.   yskip    = th + 11;
  71.   bskip    = th;
  72.   yoff     = th / 2;
  73.   xoff     = tw + 2;
  74.   last_ycoord = yoff;
  75.   slider_h = th - 1;
  76.   string_h = th + 2;
  77.   button_h = th + 4;
  78.   choice_h = th + 5;
  79.   slider_w  = 200; // minimal slider length
  80.   string_w  = 200; // minimal string/int/float item length
  81.   choice_w  = 35;  // minimal choice field width
  82.   button_w  = 40;  // minimal button width
  83.   but_per_line = 0;  
  84.  }
  85. LEDA_PANEL::LEDA_PANEL(const char* s, int bl)
  86. { WIDTH  = -1;
  87.   HEIGHT = -1;
  88.   init(s);
  89.   but_per_line = (bl == 1) ? 1 : 0;
  90. }
  91. LEDA_PANEL::LEDA_PANEL(const char* s, int width, int height)
  92. { WIDTH  = width;
  93.   HEIGHT = height;
  94.   init(s);
  95.  }
  96. LEDA_PANEL::LEDA_PANEL(int width, int height)
  97. { WIDTH  = width;
  98.   HEIGHT = height;
  99.   init("");
  100.  }
  101. void LEDA_PANEL::item_error()
  102. { fprintf(stderr,"Sorry, too many items."); 
  103.   exit(1);
  104.  }
  105. void LEDA_PANEL::text_item(const char* s)
  106. { if (item_count >= MAX_ITEM_NUM) item_error();
  107.   kind[item_count] = Text_Item;
  108.   label_str[item_count] = duplicate_string(s);
  109.   data_str[item_count] = 0;
  110.   ycoord[item_count] = last_ycoord;
  111.   last_ycoord += ytskip;
  112.   item_count++;
  113. }
  114. void LEDA_PANEL::string_item(const char* s, char** x)
  115. { if (item_count >= MAX_ITEM_NUM) item_error();
  116.   label_str[item_count] = duplicate_string(s);
  117.   data_str[item_count] = duplicate_string(*x);
  118.   ref[item_count] = x;
  119.   kind[item_count] = String_Item;
  120.   ycoord[item_count] = last_ycoord;
  121.   last_ycoord += yskip;
  122.   item_count++;
  123.  }
  124. void LEDA_PANEL::string_menu_item(const char* s, char** x, const char* ,
  125.                                   int argc,const char** argv)
  126.   if (item_count >= MAX_ITEM_NUM) item_error();
  127.   label_str[item_count] = duplicate_string(s);
  128.   data_str[item_count] = duplicate_string(*x);
  129.   ref[item_count] = x;
  130.   kind[item_count] = String_Menu_Item;
  131.   dat1[item_count] = argc;
  132.   choices[item_count] = new char*[argc];
  133.   for(int i = 0; i < argc; i++) 
  134.      choices[item_count][i] = duplicate_string(argv[i]);
  135.   ycoord[item_count] = last_ycoord;
  136.   last_ycoord += yskip;
  137.   item_count++;
  138.  }
  139. void LEDA_PANEL::int_item(const char* s, int* x)
  140. { if (item_count >= MAX_ITEM_NUM) item_error();
  141.   label_str[item_count] = duplicate_string(s);
  142.   data_str[item_count] = make_string(*x);
  143.   ref[item_count] = x;
  144.   kind[item_count] = Int_Item;
  145.   ycoord[item_count] = last_ycoord;
  146.   last_ycoord += yskip;
  147.   item_count++;
  148.  }
  149. void LEDA_PANEL::float_item(const char* s, double* x)
  150. { if (item_count >= MAX_ITEM_NUM) item_error();
  151.   label_str[item_count] = duplicate_string(s);
  152.   data_str[item_count] = make_string(*x);
  153.   ref[item_count] = x;
  154.   kind[item_count] = Float_Item;
  155.   ycoord[item_count] = last_ycoord;
  156.   last_ycoord += yskip;
  157.   item_count++;
  158.  }
  159. void  LEDA_PANEL::slider_item(const char* s, int* x, int min, int max, action_func F)
  160. { if (item_count >= MAX_ITEM_NUM) item_error();
  161.   label_str[item_count] = duplicate_string(s);
  162.   data_str[item_count] = make_string(*x);
  163.   ref[item_count] = x;
  164.   dat1[item_count] = min;
  165.   dat2[item_count] = max;
  166.   kind[item_count] = Slider_Item;
  167.   ycoord[item_count] = last_ycoord;
  168.   action[item_count] = F;
  169.   last_ycoord += yskip;
  170.   item_count++;
  171.  }
  172. void LEDA_PANEL::choice_item(const char* s, int* address, int argc,
  173.                              const char** argv, int step, int off)
  174.   if (item_count >= MAX_ITEM_NUM) item_error();
  175.   label_str[item_count] = duplicate_string(s);
  176.   data_str[item_count] = 0;
  177.   kind[item_count] = Choice_Item;
  178.   ref[item_count] = address;
  179.   dat1[item_count] = argc;
  180.   dat2[item_count] = step;
  181.   offset[item_count] = off;
  182.   choices[item_count] = new char*[argc];
  183.   for(int i=0; i<argc; i++) choices[item_count][i] = duplicate_string(argv[i]);
  184.   ycoord[item_count] = last_ycoord;
  185.   last_ycoord += yskip;
  186.   item_count++;
  187.  }
  188. void LEDA_PANEL::bool_item(const char* s, char* address)
  189. { if (item_count >= MAX_ITEM_NUM) item_error();
  190.   label_str[item_count] = duplicate_string(s);
  191.   data_str[item_count] = 0;
  192.   kind[item_count] = Bool_Item;
  193.   ref[item_count] = address;
  194.   dat1[item_count] = 2;
  195.   dat2[item_count] = 1;
  196.   offset[item_count] = 0;
  197.   choices[item_count] = new char*[2];
  198.   choices[item_count][0] = duplicate_string("off");
  199.   choices[item_count][1] = duplicate_string("on");
  200.   ycoord[item_count] = last_ycoord;
  201.   last_ycoord += yskip;
  202.   item_count++;
  203.  }
  204. void LEDA_PANEL::color_item(const char* s, int* x)
  205. { if (item_count >= MAX_ITEM_NUM) item_error();
  206.   label_str[item_count] = duplicate_string(s);
  207.   data_str[item_count] = 0;
  208.   ref[item_count] = x;
  209.   if (display_depth() > 1)
  210.      kind[item_count] = Color_Item;
  211.   else 
  212.    { // choice item [white][black]
  213.      kind[item_count] = Choice_Item;
  214.      dat1[item_count] = 2;
  215.      dat2[item_count] = 1;
  216.      offset[item_count] = 0;
  217.      choices[item_count] = new char*[2];
  218.      choices[item_count][0] = duplicate_string("white");
  219.      choices[item_count][1] = duplicate_string("black");
  220.     }
  221.   ycoord[item_count] = last_ycoord;
  222.   last_ycoord += yskip;
  223.   item_count++;
  224.  }
  225. int LEDA_PANEL::button(const char* s)
  226. { if (but_count == MAX_BUT_NUM) return -1;
  227.   // space before first line of buttons
  228.   if (but_count==0 && item_count>0)  text_item(""); 
  229.   button_str[but_count] = duplicate_string(s);
  230.   return but_count++;
  231.  }
  232. void  LEDA_PANEL::button_line(int n, const char** b) 
  233. { for(int i=0; i<n; i++) button(b[i]); }
  234. void LEDA_PANEL::draw_box_with_shadow(int x1,int y1,int x2,int y2,int c,int w)
  235. { // below and right of box(x1,y1,x2,y2)
  236.   ::set_color(shadow_color);
  237.   box(win,x1+3,y1+3,x2+w,y2+w);
  238.   ::set_color(c);
  239.   box(win,x1,y1,x2,y2);
  240.   ::set_color(black);
  241.   rectangle(win,x1,y1,x2,y2);
  242.  }
  243. void LEDA_PANEL::draw_d3_box(int x1,int y1,int x2,int y2, int pressed)
  244. {
  245.   ::set_color(bg_color);
  246.   box(win,x1,y1,x2,y2);
  247.    //if (pressed) { x1++; y1++; x2++; y2++; }
  248.    if (pressed) { x1++; y1++; }
  249.    int c1 = (pressed) ? shadow_color : white;
  250.    int c2 = (pressed) ? white        : shadow_color;
  251.    int c3 = (pressed) ? press_color  : bg_color;
  252.    ::set_color(c3);
  253.    box(win,x1,y1,x2,y2);
  254.    ::set_color(c1);
  255.    line(win,x1,y1,x2,y1);
  256.    line(win,x1,y1,x1,y2);
  257.    ::set_color(c2);
  258.    line(win,x1+1,y2,x2,y2);
  259.    line(win,x2,y1+1,x2,y2);
  260.   ::set_color(black);
  261. }
  262. void LEDA_PANEL::draw_string_item(int i,int active, const char* s)
  263.   int  yt = ycoord[i] + (yskip-th)/2;
  264.   put_text(win,xoff,yt,label_str[i],0);
  265.   int x1 = xoff1;
  266.   int x2 = x1 + string_w;
  267.   int y1 = yt - (string_h-th)/2 - 1;
  268.   int y2 = yt + string_h + (string_h-th)/2;
  269.   
  270.   if (s == 0)  s = data_str[i];
  271.   int max_c = string_w/tw - 1;
  272.   int d = strlen(s) - max_c;
  273.   if (active && d > 0) s += d;
  274.   if (bg_color == white)
  275.     { ::set_color(bg_color);
  276.       box(win,x1,y1,x2,y2);
  277.       ::set_color(black);
  278.       rectangle(win,x1,y1,x2,y2);
  279.      }
  280.   else
  281.     draw_d3_box(x1,y1,x2,y2,active);
  282.   // write text into box
  283.   ::set_color(black);
  284.   put_text(win,x1+4,yt,s,max_c,0);
  285.   if (active) put_text(win,x1+4+strlen(s)*tw,yt,"|",0);
  286. }
  287. void LEDA_PANEL::activate_string_item(int n)
  288. { if (n == act_str_item) return;
  289.   if (act_str_item > -1) 
  290.     draw_string_item(act_str_item);
  291.   draw_string_item(n,1);
  292.   act_str_item = n;
  293.  }
  294.    
  295. void LEDA_PANEL::panel_text_edit(int n)
  296.   int h  = yskip-8;
  297.   int y  = ycoord[n] + 4;
  298.   int yt = y + (h - th)/2 + 1;
  299.   int max_c = string_w/tw - 1;
  300.   char  str[128];
  301.   strcpy(str,data_str[n]);
  302.   int j = strlen(str);
  303.   for(;;)
  304.   { int  k,val;
  305.     char c = 13;
  306.     ::set_read_gc();
  307.     while(1)
  308.     { Window w;
  309.       int xc,yc;
  310.       unsigned long t;
  311.       k = get_next_event(&w,&val,&xc,&yc,&t);
  312.       if (w != win) continue;
  313.       if (k == key_press_event || k == button_press_event) break;
  314.      }
  315.      reset_gc();
  316.      if (k == key_press_event) c = val;
  317.      if (c == 13) 
  318.      { put_back_event();
  319.        break;
  320.       }
  321.      if (isprint(c))
  322.      { str[j++]=c;
  323.        str[j] = '';
  324.       }
  325.      if(c==8 && j>0) str[--j] = '';
  326.      draw_string_item(n,1,str);
  327.    }
  328.   delete data_str[n];
  329.   data_str[n] = duplicate_string(str);
  330. }
  331. void LEDA_PANEL::draw_choice_bool_item(int i, int x, int y, int c, int n)
  332. {
  333.   ::set_color(bg_color);
  334.   box(win,x,y,x+n*choice_w,y+choice_h);
  335.   int j;
  336.   if (bg_color != white)
  337.      for(j=0; j<n; j++)
  338.      { draw_d3_box(x,y,x+choice_w-1,y+choice_h,j==c);
  339.        ::set_color(black);
  340.        put_ctext(win,x+choice_w/2,y+choice_h/2,choices[i][j],0);
  341.        x += choice_w;
  342.       }
  343.   else
  344.     for(j=0; j<n; j++)
  345.     { ::set_color(item_bg_color);
  346.       box(win,x+1,y+1,x+choice_w-1,y+choice_h-1);
  347.       ::set_color(black);
  348.       put_ctext(win,x+choice_w/2,y+choice_h/2,choices[i][j],0);
  349.       if (bg_color == item_bg_color) rectangle(win,x,y,x+choice_w,y+choice_h);
  350.       if(j == c) 
  351.       { rectangle(win,x,y,x+choice_w,y+choice_h);
  352.         rectangle(win,x+1,y+1,x+choice_w-1,y+choice_h-1);
  353.        }
  354.       x += choice_w;
  355.      }
  356. }
  357. void LEDA_PANEL::draw_choice_item(int i)
  358.   int yt = ycoord[i] + (yskip-th)/2;
  359.   put_text(win,xoff,yt,label_str[i],0);
  360.   int y = yt - (choice_h-th)/2 - 1;
  361.   int c = (*(int*)ref[i]-offset[i])/dat2[i];
  362.   draw_choice_bool_item(i,xoff1,y,c,dat1[i]);
  363. }
  364. #if !(defined(__GNUC__) && __GNUC_MINOR__ > 5)
  365. typedef char bool;
  366. #endif
  367. void LEDA_PANEL::draw_bool_item(int i)
  368.   int yt = ycoord[i] + (yskip-th)/2 + 1;
  369.   put_text(win,xoff,yt,label_str[i],0);
  370.   int y = yt - (choice_h-th)/2;
  371.   int c = (*(bool*)ref[i]-offset[i])/dat2[i];
  372.   draw_choice_bool_item(i,xoff1,y,c,dat1[i]);
  373. }
  374. void LEDA_PANEL::change_color_item(int i, int j)
  375. { int yt = ycoord[i] + (yskip-th)/2 + 1;
  376.   int y = yt - (choice_h-th)/2 - 1;
  377.   int old = *(int*)ref[i];
  378.   *(int*)ref[i] = j;
  379.   char col_str[8];
  380.   int x = xoff1 + j*choice_h;
  381.   sprintf(col_str,"%d",j);
  382.   press_color = j;
  383.   draw_d3_box(x,y,x+choice_h-1,y+choice_h-1,1);
  384.   ::set_color((j==black) ? white : black);
  385.   put_ctext(win,x+choice_h/2,y+choice_h/2,col_str,0);
  386.   j = old;
  387.   x = xoff1 + j*choice_h;
  388.   sprintf(col_str,"%d",j);
  389.   press_color = grey2;
  390.   draw_d3_box(x,y,x+choice_h-1,y+choice_h-1,0);
  391.   ::set_color((j==bg_color) ? black : j);
  392.   put_ctext(win,x+choice_h/2,y+choice_h/2,col_str,0);
  393.   ::set_color(black);
  394. }
  395. void LEDA_PANEL::draw_color_item(int i)
  396.   int yt = ycoord[i] + (yskip-th)/2 + 1;
  397.   int x = xoff1;
  398.   int y = yt - (choice_h-th)/2 - 1;
  399.   put_text(win,xoff,yt,label_str[i],0);
  400.   char c = *(int*)ref[i];
  401.   ::set_color(bg_color);
  402.   box(win,x,y,x+16*choice_h,y+choice_h);
  403.   for(int j=0; j < 16; j++)
  404.   { char col_str[8];
  405.     sprintf(col_str,"%d",j);
  406.     press_color = j;
  407.     draw_d3_box(x,y,x+choice_h-1,y+choice_h-1,j==c);
  408.     if (j != c)
  409.       ::set_color((j==bg_color) ? black : j);
  410.     else
  411.       ::set_color((j==black) ? white : black);
  412.     put_ctext(win,x+choice_h/2,y+choice_h/2,col_str,0);
  413.     x += choice_h;
  414.    }
  415.   press_color = grey2;
  416.   ::set_color(black);
  417.   //end_group(win);
  418. }
  419. void LEDA_PANEL::draw_slider_item(int i, float x)
  420.   int x0 = xoff1;
  421.   int x1 = x0 + slider_w;
  422.   int y0 = ycoord[i] + (yskip-slider_h)/2 + 1;
  423.   int y1 = y0 + slider_h;
  424.   int yt = ycoord[i] + (yskip-th)/2 + 1;
  425.   if (x == 0) // first time
  426.   { float d = float(slider_w)/(dat2[i]-dat1[i]);
  427.     x = xoff1 + d * (*(int*)ref[i]-dat1[i]);
  428.     put_text(win,xoff,yt,label_str[i],0);
  429.    }
  430.   float mi = dat1[i];
  431.   float ma = dat2[i];
  432.   if (x < x0) x = x0;
  433.   if (x > x1) x = x1;
  434.   int val = int(mi + (ma-mi)*(x-x0)/slider_w + 0.5);
  435.   if (action[i]) action[i](val);
  436.   *(int*)ref[i] = val;
  437.   // text
  438.   char text[16];
  439.   sprintf(text,"%4d",val);
  440.   int t_w = text_width(text) + 3;
  441.   int t_h = text_height(text);
  442.   ::set_color(bg_color);
  443.   box(win,x0-t_w,y0,x0,y0+t_h);
  444.   ::set_color(black);
  445.   put_text(win,x0-t_w,yt,text,0);
  446.   // slider
  447.   if (bg_color == white)
  448.     { ::set_color(black);
  449.       box(win,x0,y0,int(x+0.5),y1);
  450.       ::set_color(white);
  451.       box(win,int(x+0.5),y0,x1,y1);
  452.       ::set_color(black);
  453.       rectangle(win,x0,y0,x1,y1);
  454.      }
  455.   else
  456.     { draw_d3_box(int(x+0.5),y0,x1,y1,1);
  457.       draw_d3_box(x0,y0,int(x+0.5)+1,y1);
  458.      }
  459.   ::set_color(black);
  460. }
  461. void LEDA_PANEL::draw_button(const char* s, int x, int y, int pressed)
  462.    int x1 = x+1;
  463.    int y1 = y+4;
  464.    int x2 = x1 + button_w;
  465.    int y2 = y1 + button_h + 1;
  466.    int yt = y1 + button_h/2;
  467.    int xt = x1 + button_w/2;
  468.    if (bg_color == white)
  469.      { draw_box_with_shadow(x1,y1,x2,y2,white,3);
  470.        if (pressed)
  471.        { box(win,x1+1,y1+1,x2-1,y2-1);
  472.          ::set_color(white);
  473.         }
  474.        put_ctext(win,xt,yt,s,0);
  475.       }
  476.    else
  477.      { draw_d3_box(x1,y1,x2,y2,pressed);
  478.        ::set_color(black);
  479.        put_ctext(win,xt,yt,s,0);
  480.       }
  481.    ::set_color(black);
  482.    flush_display();
  483. }
  484. void LEDA_PANEL::draw_menu_button(int x, int y, int pressed)
  485.   int x1 = x;
  486.   int y1 = y+4;
  487.   int x2 = x1+string_h;
  488.   int y2 = y1+string_h;
  489.   ::set_color(bg_color);
  490.   box(win,x1,y1,x2,y2);
  491.   if (bg_color == item_bg_color)
  492.   { ::set_color(black);
  493.     rectangle(win,x1,y1,x2,y2);
  494.   }
  495.   if (pressed) 
  496.   { ::set_color(black);
  497.     box(win,x1+1,y1+1,x2-1,y2-1);
  498.    }
  499.   y1 += 3;
  500.   y2 -= 3;
  501.   x1 += 4;
  502.   ::set_color(shadow_color);
  503.   line(win,x1,y1,x1,y2-1);
  504.   x1++;
  505.   y1++;
  506.   y2--;
  507.   ::set_color(item_bg_color);
  508.   while (y1 <= y2)
  509.   { ::set_color(item_bg_color);
  510.     line(win,x1,y1,x1,y2);
  511.     x1++;
  512.     line(win,x1,y1,x1,y2);
  513.     ::set_color(shadow_color);
  514.     pixel(win,x1-1,y1);
  515.     pixel(win,x1,  y1);
  516.     ::set_color(white);
  517.     pixel(win,x1-1,y2);
  518.     pixel(win,x1,  y1);
  519.     x1++;
  520.     y1++;
  521.     y2--;
  522.    }
  523.   flush_display();
  524. }
  525. static int read_panel_at(const char* header, int n, char** but,int x, int y)
  526. { LEDA_PANEL p(header);
  527.   for(int i=0; i<n; i++) p.button(but[i]);
  528.   return p.open(x,y,0,0,0,0,3);
  529.  }
  530. int  LEDA_PANEL::open(int xpos, int ypos, int win_x, int win_y, 
  531.                       int win_width, int win_height, int mode)
  532. {
  533.   // mode = 0:  just display panel window  on screen
  534.   // mode = 1:  display, read (blocking), and close 
  535.   // mode = 2:  read
  536.   // mode = 3:  display, read (non-blocking) , and close
  537.   if (display_depth() == 1)
  538.   { bg_color = white;   
  539.     shadow_color = black;   
  540.     item_bg_color = white;   
  541.    }
  542. repaint:
  543.   slider_w  = 200; // minimal slider length
  544.   string_w  = 200; // minimal string/int/float item length
  545.   choice_w  = 30;  // minimal choice field width
  546.   button_w  = 40;  // minimal button width
  547.   xoff1 = 0;       // start of items
  548.   bxoff = 0;       // left and right button boundary space
  549.   int width = (win) ? ::window_width(win) : 100;
  550.   int height; 
  551.   int   bw1;              /* button_w + bskip   */
  552.   int   but_lines;
  553.   int   but,w,i,j;
  554.   unsigned long t;
  555.   int user_buttons = but_count;
  556.   int save_lw = ::set_line_width(1);
  557.   int save_ls = ::set_line_style(0);
  558.   int save_mo = ::set_mode(0);
  559.   if (but_count==0)
  560.   { button("CONTINUE");
  561.     button("QUIT");
  562.    }
  563.   height = 2*yoff;
  564.   for(i=0;i<item_count; i++)
  565.     if (kind[i] != Text_Item)
  566.        { height += yskip;
  567.          if ((w = text_width(label_str[i])+50) > xoff1) xoff1 = w;
  568.  
  569.          if (kind[i] == Choice_Item || kind[i] == Bool_Item)
  570.          { int j;
  571.            for(j=0; j<dat1[i];j++)
  572.            if ((w = text_width(choices[i][j])+10) > choice_w) choice_w = w;
  573.           }
  574.        }
  575.     else
  576.        height += ytskip;
  577.   // adjust width of buttons
  578.   for(i=0; i < but_count; i++)
  579.      if ((w = text_width(button_str[i])+10) > button_w) button_w = w;
  580.   bw1 = button_w + bskip;
  581.   // adjust panel width
  582.   if ((w = text_width(header)) > width) width = w;
  583.   if ((w = but_per_line*bw1+2*xoff) > width) width = w;
  584.   for(i=0; i<item_count; i++)
  585.     switch (kind[i])
  586.     {
  587.       case  Text_Item:
  588.                   if ((w = 2*xoff + text_width(label_str[i])) > width) width=w;
  589.                   break;
  590.       case Choice_Item:
  591.                  if ((w = xoff1+choice_w*dat1[i]+yskip+xoff) > width) width = w;
  592.                  break;
  593.       case Color_Item:
  594.                  if ((w = xoff1+16*choice_h+yskip+xoff) > width) width = w;
  595.                  break;
  596.       case Slider_Item:
  597.                  if ((w = xoff1+slider_w+yskip+xoff) > width) width = w;
  598.                  break;
  599.       case String_Menu_Item:
  600.                  if ((w = xoff1+string_w+2*yskip+xoff) > width) width = w;
  601.                  break;
  602.       default:   if ((w = xoff1+string_w+yskip+xoff) > width) width = w;
  603.                  break;
  604.      }
  605.   // adjust width of slider & string boxes
  606.   w = width-xoff1-2*yskip;
  607.   if (w > slider_w) slider_w = w;
  608.   if (w > string_w) string_w = w;
  609.   // center buttons
  610.   if (but_per_line == 0)
  611.   { but_per_line = (width-2*xoff+bskip)/bw1;
  612.     if (but_per_line == 0)
  613.     { but_per_line = 1;
  614.       width = button_w + 2*xoff;
  615.      }
  616.    }
  617.     
  618.   but_lines = but_count/but_per_line;
  619.   if (but_count % but_per_line) but_lines++;
  620.   if (but_lines == 1)
  621.      bxoff = (width - but_count * bw1 + bskip)/2;
  622.   else
  623.      bxoff = (width - but_per_line * bw1 + bskip)/2;
  624.   height += but_lines * yskip;
  625.   height += yoff;
  626.   for (i=0; i< but_lines; i++)
  627.      kind[item_count+i] = Button_Item;
  628.   if (WIDTH  == -1)  WIDTH  = width;
  629.   if (HEIGHT == -1)  HEIGHT = height;
  630.   if(XPOS == -1)
  631.     if (xpos == -1)
  632.       if (win_width == 0)
  633.          { /* center panel window on the screen */
  634.            XPOS = (display_width() - WIDTH)/2;
  635.            YPOS = (display_height() - HEIGHT)/2;
  636.           }
  637.       else
  638.          { /* center panel window on draw window */
  639.            XPOS = win_x + (win_width - WIDTH)/2;
  640.            YPOS = win_y + (win_height- HEIGHT)/2;
  641.           }
  642.     else /* use supplied coordinates */
  643.       { XPOS = xpos;
  644.         YPOS = ypos;
  645.        }
  646.   if (win==0) 
  647.   { LEDA_WINDOW::open(WIDTH,HEIGHT,XPOS,YPOS,header,bg_color);
  648.     set_show_coordinates(0);
  649.     set_redraw(panel_redraw_func);
  650.     win = draw_win;
  651.    }
  652.   //clear_window(win);
  653.   act_str_item = -1;
  654.   ::set_color(1);
  655.   int y = yoff;
  656.   for(i=0;i<item_count; i++)
  657.   {
  658.     switch (kind[i]) {
  659.     case Text_Item:
  660.         { put_text(win,xoff,ycoord[i],label_str[i],0);
  661.           break;
  662.          }
  663.     case Choice_Item:
  664.         { draw_choice_item(i);
  665.           break;
  666.          }
  667.     case Bool_Item:
  668.         { draw_bool_item(i);
  669.           break;
  670.          }
  671.     case Color_Item:
  672.         { draw_color_item(i);
  673.           break;
  674.          }
  675.     case Slider_Item:
  676.         { draw_slider_item(i,0);
  677.           break;
  678.          }
  679.     case Int_Item:
  680.         { draw_string_item(i);
  681.           if (act_str_item == -1) activate_string_item(i);
  682.           break;
  683.          }
  684.  
  685.     case Float_Item:
  686.         { draw_string_item(i);
  687.           if (act_str_item == -1) activate_string_item(i);
  688.           break;
  689.          }
  690.   
  691.     case String_Item:
  692.         { draw_string_item(i);
  693.           if (act_str_item == -1) activate_string_item(i);
  694.           break;
  695.          }
  696.     case String_Menu_Item:
  697.         { draw_string_item(i);
  698.           draw_menu_button(xoff1+string_w+6,ycoord[i],0);
  699.           if (act_str_item == -1) activate_string_item(i);
  700.           break;
  701.          }
  702.    }
  703.    y += ((kind[i] == Text_Item) ?  ytskip : yskip);
  704.   }
  705.   // place buttons
  706.   //int y = ycoord[item_count-1];
  707.   y -= yskip;
  708.   int x = bxoff;
  709.   for(i=0; i < but_count; i++)
  710.   { if (i % but_per_line == 0)
  711.     { y += yskip;
  712.       x = bxoff;
  713.      }
  714.     draw_button(button_str[i],x,y,0);
  715.     x += bw1;
  716.   }
  717.   but = -1;
  718.   if (mode == 0) goto end;
  719.   while(but == -1)
  720.   { int b;
  721.     i = -1;
  722.     while (i < 0 || i >= item_count+but_lines)
  723.     { int k;
  724.       ::set_read_gc();
  725.       while (1)
  726.       { Window w;
  727.         k = get_next_event(&w,&b,&x,&y,&t);
  728.         if (w == win)
  729.         { if (k == button_press_event || k == key_press_event) break;
  730.           if (k == configure_event) 
  731.           { reset_gc();
  732.             goto repaint;
  733.            }
  734.          }
  735.         else
  736.           if (mode == 3 && k==button_press_event) 
  737.           { put_back_event();
  738.             reset_gc();
  739.             goto end;
  740.            }
  741.        }
  742.       reset_gc();
  743.       if (k==button_press_event)
  744.         { for(i=0,j=yoff;i<item_count+but_lines && j<y; i++)
  745.             if (kind[i] == Text_Item)
  746.                j += ytskip;
  747.             else
  748.                j += yskip;
  749.   
  750.            if (j >=y) i--;
  751.          }
  752.        else  /* key pressed */
  753.        if (act_str_item > -1)
  754.        { if (b == 13) // return key pressed
  755.          { j = act_str_item;
  756.            for(;;)
  757.            { j = (j + 1) % item_count;
  758.              k =  kind[j]; 
  759.              if (k==String_Item || k==String_Menu_Item || 
  760.                  k==Int_Item || k == Float_Item) break;
  761.              }
  762.            activate_string_item(j);
  763.          }
  764.          else
  765.          { x = xoff1;
  766.            i = act_str_item;
  767.            for(k=0,j=yoff; k <= i; k++)
  768.             if (kind[k] == Text_Item)
  769.                j += ytskip;
  770.             else
  771.                j += yskip;
  772.            put_back_event();
  773.           }
  774.        }
  775.      }
  776.     y  = j-yskip;
  777.     switch (kind[i]) {
  778.     case Text_Item: break;
  779.     case Slider_Item:
  780.     { Window w = win;
  781.       int xx = 0;
  782.       if (x < xoff1 || x > xoff1+slider_w) break;
  783.       ::set_read_gc();
  784.       while(w == win)
  785.       { if (xx != x)
  786.         { xx = x;
  787.           reset_gc();
  788.           draw_slider_item(i,xx);
  789.           ::set_read_gc();
  790.          }
  791.         if (get_next_event(&w,&b,&x,&j,&t) == button_release_event) break;
  792.        }
  793.       reset_gc();
  794.       break;
  795.      }
  796.     case Int_Item:
  797.     { activate_string_item(i);
  798.       panel_text_edit(i);
  799.       int x = atoi(data_str[i]);
  800.       delete data_str[i];
  801.       data_str[i] = make_string(x);
  802.       *(int*)ref[i] = x;
  803.       break;
  804.      }
  805.     case Float_Item:
  806.     { activate_string_item(i);
  807.       panel_text_edit(i);
  808.       double x = (double)atof(data_str[i]);
  809.       delete data_str[i];
  810.       data_str[i] = make_string(x);
  811.       *(double*)ref[i] = x;
  812.       break;
  813.      }
  814.     case String_Item:
  815.     { activate_string_item(i);
  816.       panel_text_edit(i);
  817.       delete *(char**)ref[i];
  818.       *(char**)ref[i] = duplicate_string(data_str[i]);
  819.       break;
  820.      }
  821.     case String_Menu_Item:
  822.     { activate_string_item(i);
  823.       if (x < xoff1+string_w+10)
  824.          { panel_text_edit(i);
  825.            delete *(char**)ref[i];
  826.            *(char**)ref[i] = duplicate_string(data_str[i]);
  827.           }
  828.       else
  829.          { Window w;
  830.            draw_menu_button(xoff1+string_w+6,y,1);
  831.            while (get_next_event(&w,&b,&x,&j,&t) != button_release_event);
  832.            draw_menu_button(xoff1+string_w+6,y,0);
  833.            int sel = read_panel_at(label_str[i],dat1[i],choices[i],
  834.                                    XPOS+xoff1+string_w+16, YPOS+y+24);
  835.            if (sel > -1)
  836.            { delete *(char**)ref[i];
  837.              *(char**)ref[i] = duplicate_string((choices[i])[sel]);
  838.              data_str[i] = duplicate_string((choices[i])[sel]);
  839.              draw_string_item(i,1);
  840.             }
  841.           }
  842.       break;
  843.     }
  844.    case Choice_Item:
  845.    { j = (x-xoff1)/choice_w;
  846.      if (j >= 0 && j<dat1[i])
  847.      { *(int*)ref[i] = offset[i] + j * dat2[i];
  848.        draw_choice_item(i);
  849.       }
  850.      break;
  851.     }
  852.    case Bool_Item:
  853.    { j = (x-xoff1)/choice_w;
  854.      if (j >= 0 && j<dat1[i])
  855.      { *(char*)ref[i] = offset[i] + j * dat2[i];
  856.        draw_bool_item(i);
  857.       }
  858.      break;
  859.     }
  860.    case Color_Item:
  861.    { j = (x-xoff1)/choice_h;
  862.      if (0 <= j && j <= 15) change_color_item(i,j);
  863.      break;
  864.     }
  865.    case Button_Item:
  866.    { j = (x-bxoff)/bw1;
  867.      i = (i-item_count)*but_per_line +j;
  868.      if (x > bxoff && j < but_per_line && i < but_count)
  869.      { Window w;
  870.        draw_button(button_str[i],bxoff+j*bw1,y,1);
  871.        while (get_next_event(&w,&b,&b,&b,&t) != button_release_event);
  872.        but = i;
  873.        //if (mode == 2) draw_button(button_str[i],bxoff+j*bw1,y,1);
  874.       }
  875.      break;
  876.     }
  877.    }
  878.    if (mode == 2) break; // no button click neccessary
  879.  } // while but == -1
  880.  if (mode == 2) // redisplay  (mode = 0)
  881.      open(XPOS,YPOS,0,0,0,0,0);
  882. end:
  883. /*
  884.   window_position(win,&(XPOS),&(YPOS));
  885. */
  886.   ::set_line_width(save_lw);
  887.   ::set_line_style(save_ls);
  888.   ::set_mode(save_mo);
  889.   if (user_buttons == 0)
  890.   { but_count = 0;
  891.     item_count--;
  892.     if (but == 1)   /* quit button pressed */
  893.     { close_display();
  894.       exit(0);
  895.      }
  896.    }
  897.   if (mode == 1 || mode == 3) close();
  898.   return but;
  899. }
  900. void LEDA_PANEL::display(int xpos, int ypos, int win_x, int win_y, int win_width, int win_height)
  901. { open(xpos, ypos, win_x, win_y, win_width, win_height, 0); }
  902. /*
  903. int  LEDA_PANEL::read(int xpos, int ypos, int win_x, int win_y, int win_width, int win_height)
  904. { return open(xpos, ypos, win_x, win_y, win_width, win_height, 2); }
  905. */
  906. int  LEDA_PANEL::read() { return open(XPOS,YPOS,0,0,0,0,2); }
  907. void  LEDA_PANEL::close() 
  908. { LEDA_WINDOW::close();
  909.   win = 0;
  910.  }
  911. LEDA_PANEL::~LEDA_PANEL() 
  912. { delete header; 
  913.   for(int i = 0; i<item_count; i++)
  914.   { if (label_str[i]) delete label_str[i];
  915.     if (data_str[i]) delete data_str[i];
  916.     if (kind[i] == String_Menu_Item || 
  917.         kind[i] == Choice_Item || 
  918.         kind[i] == Bool_Item    )
  919.       { for(int j = 0; j < dat1[i]; j++) delete choices[i][j];
  920.         delete choices[i];
  921.        }
  922.    }
  923.   for(int j = 0; j<but_count; j++) delete button_str[j];
  924. }