/**
 *  File ge_graph.c 
 *   Copyright (c) 2010 P. Vincent.    See GNU GPL ../LICENCE
 *  Replace part of Grace graphappwin.c
 *   Home page: http://plasma-gate.weizmann.ac.il/Grace/
 *   Copyright (c) 1991-1995 Paul J Turner, Portland, OR
 *   Copyright (c) 1996-2003 Grace Development Team
 */
#include <string.h>

#include <gtk/gtk.h>

#include "globals.h"

#include "defines.h"
#include "utils.h"
#include "noxprotos.h"

#include "gw_pannel.h"
#include "gw_choice.h"
#include "gw_list.h"

#include "gg_gutil.h"
#include "gg_gtkinc.h"
#include "gg_protos.h"

#include "ge_tree.h"
#include "ge_protos.h"
#include "ng_objects.h"
#include "wu.h"
#include "nn_cmd.h"

static gint popup_width = 200 ,list_height = 230; //  ,popup_height = 700

extern GdkColor  bleuciel ,wheat;
static GdkColor  rouge;

/* From ge.c */
extern Ge_tree *get_getree (void);

static GtkWidget *vbox = NULL;
static GtkWidget *titre_item = NULL;
static GtkWidget *w_graph_notb;

/************************************************************/
static int menu_finalized 	= FALSE;
static int block_instant_update = FALSE;

/************************************************************/
/*  Widgets for graph struct elements (see graphs.h 158)     */
/************************************************************/
static GtkWidget *w_type;
static GtkWidget *w_stacked;
static GtkWidget *w_bargap;
static GtkWidget *w_znorm;
/* graph.view */
static Wu wu_x1    ,wu_y1;
static Wu wu_x2    ,wu_y2;
/* graph.labels */
static Wu title_color;
static Wu title_font;
static Wu title_size;
static Wu title_just;
static Wu title_layer;
static spin2Struct w_title_xy;
static Wu stitle_color;
static Wu stitle_font;
static Wu stitle_size;
static Wu stitle_just;
static Wu stitle_layer;
static spin2Struct w_stitle_xy;
static GtkWidget *w_stitle_s;
/* graph.framep */
static Wu f_type;
static Wu f_pen_color;
static Wu f_pen_pattern;
static Wu f_lines;
static Wu f_linew;
static Wu f_fillpen_color;
static Wu f_fillpen_pattern;
static Wu f_layer;
/**************************************************************/
/*  Widgets for QDobject struct  elements (see defines.h 483) */
static Wu layer;
/**************************************************************/
GtkWidget *w_layers_collapse; /* button to homogeneize frame, title and stitle layers */
static void ge_graph_collapse_layers_CB (GtkWidget *w ,gpointer p);


static GtkWidget *sets_list = NULL;
static SetsMenu3Struct *sets_menu3 = NULL;




static GtkWidget *graph_hidden;


static void ge_graph_set_cset_CB    (GtkTreeSelection *sel ,Gw_list *w);
static void ge_graph_sets_CB  	    (GtkWidget *w ,gpointer pact);

typedef enum {
  SETAPP_STRIP_LEGENDS  = 0
  , SETAPP_LOAD_COMMENTS
  , SETAPP_ALL_COLORS   
  , SETAPP_ALL_SYMBOLS  
  , SETAPP_ALL_LINEW    
  , SETAPP_ALL_LINES    
  , SETAPP_ALL_BW       
  , SETAPP_DUP_LEGENDS  
  , SETAPP_COLOR_SYNC
  , SETAPP_KILL
} SETAPP_actions;

#define cg get_cg()
static int cset = 0;            /* the current set from the symbols panel */

static int rpane_gno = -2;

static gint current_page = -1;
static gulong handler_id;

void ge_graph_page_block (void)
{
  g_signal_handler_block (w_graph_notb ,handler_id);  
}
void ge_graph_page_unblock (void)
{
  g_signal_handler_unblock (w_graph_notb ,handler_id);  
}
static void ge_graph_store_page_CB (GtkNotebook     *notebook,
 				    GtkNotebookPage *page,
 				    guint            page_num,
 				    gpointer         user_data)
{
  if (current_page >= 0) current_page = page_num;
}

void ge_graph_set_page (void)
{
  gtk_notebook_set_current_page (GTK_NOTEBOOK (w_graph_notb) ,current_page);
}


/**
 *  Create rpane contextual menu for Q_Graph
 */
GtkWidget *ge_graph_create_menu (GtkWidget *parent)
{
  GtkWidget *vbox1 ,*vb1 ,*rc ,*rc1 ,*rc2 ,*ta  ,*hb;

  rouge.red   = 65535;
  rouge.green = 0;
  rouge.blue  = 0;

  if (titre_item == NULL) {
    vbox = gg_CreateVContainer (parent);
    titre_item = gg_label_new (vbox ,"Graph");
    gg_frame_connect (ge_graph_apply_CB);

    vb1 = gg_frame (vbox  ,"Subtitle" ,&wheat ,0 ,1);
    w_stitle_s = gg_string_new (vb1 ,"Subtitle: : " ,30);

    /* Notebook */
    w_graph_notb = gtk_notebook_new ();

    /* ------------ Main tab -------------- */
    rc = gg_CreateTabPage (w_graph_notb ,"Main");

    hb = gg_frame (rc  ,"Presentation" ,&wheat ,1 ,0);    
    w_type = gg_combo_new (hb ,"Type:" ,7
			   ,"XY graph"            /* GRAPH_XY    */
			   ,"XY chart"            /* GRAPH_CHART */
			   ,"Polar graph"         /* GRAPH_POLAR */
			   ,"Smith chart (N/I)"   /* GRAPH_SMITH */
			   ,"Fixed"               /* GRAPH_FIXED */
			   ,"Pie chart"           /* GRAPH_PIE   */
			   ,NULL);
    w_stacked = gg_check_new (hb ," Stacked chart");

    ta = gg_frame (rc  ,"Viewport" ,&wheat ,2 ,2);
    wu_x1.w = gg_entry_new (ta ,"Xmin:" ,8);
    wu_x2.w = gg_entry_new (ta ,"Xmax:" ,8);
    wu_y1.w = gg_entry_new (ta ,"Ymin:" ,8);
    wu_y2.w = gg_entry_new (ta ,"Ymax:" ,8);

    ta = gg_frame (rc  ,"2D+ graphs" ,&wheat ,0 ,1);
    w_znorm = gg_entry_new (ta ,"Z normalization" ,10);

    ta = gg_frame (rc  ,"XY charts" ,&wheat ,0 ,1);
    w_bargap = gg_spin_new (ta ,"Bar gap:" ,-1.0  ,1.0  ,0.005);

    ta = gg_frame (rc ,"Collapse branch in one layer" ,&bleuciel ,1 ,0);
    layer.w 	      = gg_layer_new  (ta ,"Layer");
    w_layers_collapse = gg_button_new (ta ,"Collapse");

    /* ------------ Titles tab -------------- */
    rc = gg_CreateTabPage (w_graph_notb ,"Titles");

    rc2 = gg_frame (rc  ,"Title" ,&bleuciel ,2 ,2);
    title_color.w = gg_color_new    (rc2 ,"Color:");
    title_font.w  = gg_font_new     (rc2 ,"Font:");
    title_size.w  = gg_charsize_new (rc2 ,"Size");
    title_just.w  = gg_just_new     (rc2 ,"Justification:");
    rc2 = gg_frame (rc  ,"Title offset" ,&bleuciel ,0 ,1);
    gg_spin2d (rc2 ,&w_title_xy ,-0.8 ,0.8 ,0.01);

    rc2 = gg_frame (rc  ,"Subtitle" ,&wheat ,2 ,2);
    stitle_color.w = gg_color_new    (rc2 ,"Color:");
    stitle_font.w  = gg_font_new     (rc2 ,"Font:");
    stitle_size.w  = gg_charsize_new (rc2 ,"Size");
    stitle_just.w  = gg_just_new     (rc2 ,"Justification:");
    rc2 = gg_frame (rc  ,"Subtitle offset" ,&wheat ,0 ,1);
    gg_spin2d (rc2 ,&w_stitle_xy ,-0.8 ,0.8 ,0.01);

    rc2 = gg_CreateHContainer (rc);
    title_layer.w  = gg_layer_new  (rc2 ,"Title layer");
    stitle_layer.w = gg_layer_new  (rc2 ,"Subtitle Layer");

    /* ------------ Frame tab -------------- */
    rc = gg_CreateTabPage (w_graph_notb ,"Frame");

    rc1 = gg_frame (rc  ,"Frame box" ,&wheat ,0 ,1);
    f_type.w = gg_combo_new (rc1 ,"Frame type:",
			     7,
			     "Closed",
			     "Half open",
			     "Break top",
			     "Break bottom",
			     "Break left",
			     "Break right",
			     NULL);

    rc2 = gg_CreateHContainer(rc1);
    f_pen_color.w   = gg_color_new (rc2 ,"Color:");
    f_pen_pattern.w = gg_pattern_new (rc2 ,"Pattern:");
	
    rc2 = gg_CreateHContainer (rc1);
    f_linew.w = gg_spin_new (rc2 ,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    f_lines.w = gg_lines_new (rc2 ,"Style:");

    rc1 = gg_frame (rc ,"Frame fill" ,&bleuciel ,0 ,1);
    f_fillpen_color.w   = gg_color_new (rc1 ,"Color:");
    f_fillpen_pattern.w = gg_pattern_new (rc1 ,"Pattern:");

    f_layer.w           = gg_layer_new   (rc ,"Frame layer");
    
    /* ------------ Sets tab -------------- */
    rc = gg_CreateTabPage (w_graph_notb ,"Sets");
    /* Create sets_list */
    sets_list = gg_CreateSetChoice ("SELECT SET(S) IN THE LIST BELOW" ,GTK_SELECTION_MULTIPLE
				    ,popup_width ,list_height
				    ,ge_graph_set_cset_CB
				    ,&sets_menu3
				    ,NULL);
    gtk_box_pack_start_defaults (GTK_BOX (rc) ,sets_list);

    rc1 = gg_frame (rc  ,"Set different" ,&bleuciel ,2 ,2);
    gg_CreateListButton (rc1 ,"colors"      ,'c' ,sets_list ,ge_graph_sets_CB ,SETAPP_ALL_COLORS);
    gg_CreateListButton (rc1 ,"symbols"     ,'s' ,sets_list ,ge_graph_sets_CB ,SETAPP_ALL_SYMBOLS);
    gg_CreateListButton (rc1 ,"line widths" ,'w' ,sets_list ,ge_graph_sets_CB ,SETAPP_ALL_LINEW);
    gg_CreateListButton (rc1 ,"line styles" ,'y' ,sets_list ,ge_graph_sets_CB ,SETAPP_ALL_LINES);

    gg_CreateListButton (rc ,"Set black & white" ,'B' ,sets_list ,ge_graph_sets_CB ,SETAPP_ALL_BW);
 
    rc1 = gg_frame (rc  ,"Legend and comment" ,&wheat ,2 ,2);
    gg_CreateListButton (rc1 ,"Load comments"      ,'c' ,sets_list ,ge_graph_sets_CB ,SETAPP_LOAD_COMMENTS);
    gg_CreateListButton (rc1 ,"Strip legends"      ,'c' ,sets_list ,ge_graph_sets_CB ,SETAPP_STRIP_LEGENDS);
    
    /* --------------- Bottom widgets  ------------------ */
    vbox1 = gtk_vbox_new (FALSE ,3);
    gtk_box_pack_end (GTK_BOX (vbox) ,vbox1  ,FALSE ,TRUE ,1); 
    graph_hidden      = gg_check_new  (vbox1 ,"hide");
    

    gtk_box_pack_start (GTK_BOX (vbox) ,w_graph_notb ,FALSE ,TRUE ,0);

    handler_id = g_signal_connect (w_graph_notb      ,"switch-page" ,G_CALLBACK (ge_graph_store_page_CB) ,NULL);
    g_signal_connect 		  (w_layers_collapse ,"clicked"     ,G_CALLBACK (ge_graph_collapse_layers_CB) ,NULL);
    menu_finalized = TRUE;
    gg_frame_connect (NULL);
    current_page = 0;
  }
  return vbox;
}

void ge_graph_update_xy (int gno)
{
  view v;
  char buf[32];
  get_graph_viewport (gno ,&v);
  gg_setstr_d (wu_x1.w ,"%.9g" ,v.xv1 ,buf);
  gg_setstr_d (wu_x2.w ,"%.9g" ,v.xv2 ,buf);
  gg_setstr_d (wu_y1.w ,"%.9g" ,v.yv1 ,buf);
  gg_setstr_d (wu_y2.w ,"%.9g" ,v.yv2 ,buf);
}


void ge_graph_update (int gno)
{
  framep f;
  labels labs;
  char buf[32];
  gboolean ghide;
  int num;

  if (gno == -2) gno = rpane_gno;
  
  if (is_valid_gno(gno) != TRUE) return;
  if (titre_item == NULL)  return;
  block_instant_update = TRUE;

  sprintf (buf ,"  Graph %d" ,gno);
  gtk_label_set_text (GTK_LABEL (titre_item) ,buf);
  
  gg_set_int (w_type ,get_graph_type (gno));
  ge_graph_update_xy (gno);
  get_graph_framep (gno ,&f);
  gg_set_int  (f_type.w   ,f.type);
  gg_set_int  (f_pen_color.w       ,f.pen.color);
  gg_set_int  (f_pen_pattern.w     ,f.pen.pattern);
  gg_set_dble (f_linew.w       	   ,f.linew); 
  gg_set_int  (f_lines.w       	   ,f.lines);
  gg_set_int  (f_fillpen_color.w   ,f.fillpen.color);
  gg_set_int  (f_fillpen_pattern.w ,f.fillpen.pattern);
  gg_set_int  (f_layer.w           ,f.layer);
  
  get_graph_labels (gno ,&labs);

  gg_set_int    (w_bargap       ,get_graph_bargap(gno));
  gg_set_int    (w_stacked      ,is_graph_stacked(gno));
  gg_setstr_d   (w_znorm  ,"%g" ,get_graph_znorm(gno) ,buf);

  gg_set_int    (title_color.w  ,labs.title.color);
  gg_set_int 	(title_font.w   ,labs.title.font);
  gg_set_dble 	(title_size.w   ,labs.title.charsize);
  gg_set_int    (title_just.w   ,labs.title.just);
  gg_set_int    (title_layer.w  ,labs.title.layer);
  gg_spin2d_set (&w_title_xy ,"X1=" ,labs.title.x1 ,"Y1=" ,labs.title.y1);

  gg_set_utf8   (w_stitle_s 	,labs.stitle.s);
  gg_set_int    (stitle_color.w ,labs.stitle.color);
  gg_set_int 	(stitle_font.w 	,labs.stitle.font);
  gg_set_dble 	(stitle_size.w  ,labs.stitle.charsize);
  gg_set_int    (stitle_just.w  ,labs.stitle.just);
  gg_set_int    (stitle_layer.w ,labs.stitle.layer);
  gg_spin2d_set (&w_stitle_xy ,"X1=" ,labs.stitle.x1 ,"Y1=" ,labs.stitle.y1);

  ghide = is_graph_hidden (gno);
  gg_set_int           (graph_hidden             ,ghide);
  gtk_widget_set_sensitive (w_graph_notb ,ghide == FALSE);

  num = obj_tid_get_graph_num (gno);
  gg_set_int (layer.w ,objs[num].layer);

  rpane_gno = gno;
  block_instant_update = FALSE;
}

void ge_graph_apply (int gno)
{
  view v;
  labels labs;
  framep f;
  int graphtype;
  int stacked;
  double bargap;
  double znorm;
  gboolean ghide;
  graph *old;
  int num;
  const gchar *s_utf8;

  if (titre_item != NULL) {
    /* Store old values for the follow me mode */
    old = copy_graph_params (gno);

    num = obj_tid_get_graph_num (gno);
    objs[num].layer = gg_get_int (layer.w);

    graphtype = gg_get_int (w_type);
    set_graph_type (gno ,graphtype);

    gg_evalexpr (wu_x1.w ,&v.xv1);  
    gg_evalexpr (wu_x2.w ,&v.xv2);  
    gg_evalexpr (wu_y1.w ,&v.yv1);  
    gg_evalexpr (wu_y2.w ,&v.yv2);  
    if (isvalid_viewport(v) == FALSE) {
      errmsg("Invalid viewport coordinates");
      return;
    }
    set_graph_viewport (gno ,v);

    obj_get_template (Q_String ,&labs.title);
    labs.title.s        = copy_string (labs.title.s ,get_current_label ());
    labs.title.color    = gg_get_int  (title_color.w);
    labs.title.font     = gg_get_int  (title_font.w);
    labs.title.just     = gg_get_int  (title_just.w);
    labs.title.layer    = gg_get_int  (title_layer.w);
    labs.title.x1       = gg_get_dble (w_title_xy.spin1);
    labs.title.y1       = gg_get_dble (w_title_xy.spin2);
    labs.title.charsize = gg_get_dble (title_size.w);
 
    obj_get_template (Q_String ,&labs.stitle);
    s_utf8 		 = gtk_entry_get_text (GTK_ENTRY (w_stitle_s));
    labs.stitle.s 	 = g_convert   (s_utf8 ,-1 ,"ISO-8859-1" ,"UTF-8" ,NULL ,NULL ,NULL);
    labs.stitle.color    = gg_get_int  (stitle_color.w);
    labs.stitle.font     = gg_get_int  (stitle_font.w);
    labs.stitle.just     = gg_get_int  (stitle_just.w);
    labs.stitle.layer    = gg_get_int  (stitle_layer.w);
    labs.stitle.x1       = gg_get_dble (w_stitle_xy.spin1);
    labs.stitle.y1       = gg_get_dble (w_stitle_xy.spin2);
    labs.stitle.charsize = gg_get_dble (stitle_size.w);
    set_graph_labels   (gno ,&labs);
     
    f.type               = gg_get_int  (f_type.w);
    f.pen.color       	 = gg_get_int  (f_pen_color.w);
    f.pen.pattern     	 = gg_get_int  (f_pen_pattern.w);    
    f.linew           	 = gg_get_dble (f_linew.w);
    f.lines           	 = gg_get_int  (f_lines.w);
    f.fillpen.color   	 = gg_get_int  (f_fillpen_color.w);
    f.fillpen.pattern 	 = gg_get_int  (f_fillpen_pattern.w);
    f.layer           	 = gg_get_int  (f_layer.w);

    stacked = gg_get_int  (w_stacked); 
    bargap  = gg_get_dble (w_bargap);
    
    gg_evalexpr (w_znorm ,&znorm);
    set_graph_stacked  (gno ,stacked);
    set_graph_bargap   (gno ,bargap);
    set_graph_znorm    (gno ,znorm);
    set_graph_framep   (gno ,&f);

    ghide = gg_get_int (graph_hidden);
    set_graph_hidden (gno ,ghide);
    gg_graph_update_all_lists ();
    gtk_widget_set_sensitive (w_graph_notb ,ghide == FALSE);

    gg_update_layers_hbox ();
    gg_drawgraph();

    /* undo/redo and follow_me_on */
    nn_cmd_graph (gno ,old ,FALSE ,TRUE ,TRUE);

    current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (w_graph_notb));
    rpane_gno = gno;
    free_graph_params (old);
  }
}

/**************** C A L L B A C K S ****************/

void ge_graph_apply_CB (GtkWidget *w ,gpointer p)
{
  int gno;
  if (instant_update && menu_finalized && 
      block_instant_update == FALSE && obj_tid_is_valid (Q_Graph ,cur_obj_id)) {
    gno = cur_obj_id;
    if (is_valid_gno (gno)) {
      ge_graph_apply (gno);
    }
  }
}


/**
 * Called when a collective update in the "sets" tab is done
 * Replace setapp_data_proc   setappwin.c  661
 * and gg_setapp_CB
 */
static void ge_graph_sets_CB  (GtkWidget *w ,gpointer pact)
{
  gint action = GPOINTER_TO_INT (pact);
  Gw_list *liste;
  GtkTreeModel *model;
  GtkTreeIter iter;
  GtkTreeSelection *select;
  gint setno ,i ,n;
  plotarr p;
  int c = 0 ,bg = getbgcolor();
  char message[32];
  
  liste = GW_LIST(w);
  model = GTK_TREE_MODEL(liste->model);
  select = gtk_tree_view_get_selection (GTK_TREE_VIEW (GW_LIST(w)->view));
  n = gtk_tree_selection_count_selected_rows (select);
  if (gtk_tree_model_get_iter_first (model ,&iter)) {
    i = 0;
    do {
      if (gtk_tree_selection_iter_is_selected (select ,&iter)) {
	gtk_tree_model_get (model ,&iter ,GW_LIST_NUM_COL  ,&setno ,-1);
	switch (action) {
	case SETAPP_STRIP_LEGENDS:
	  set_legend_string (cg ,setno,
			     mybasename (get_legend_string(cg ,setno)));
	  break;
	case SETAPP_LOAD_COMMENTS:
	  load_comments_to_legend (cg ,setno);
	  break;
	case SETAPP_ALL_COLORS:
	  while (c == bg || get_colortype(c) != COLOR_MAIN) {
	    c++;
	    c %= number_of_colors();
	  }
	  set_set_colors(cg ,setno ,c);
	  c++;
	  break;
	case SETAPP_ALL_SYMBOLS:
	  get_graph_plotarr(cg ,setno ,&p);
	  p.sym = (i % (MAXSYM - 2)) + 1;
	  set_graph_plotarr(cg ,setno ,&p);
	  break;
	case SETAPP_ALL_LINEW:
	  get_graph_plotarr(cg ,setno ,&p);
	  p.linew = ((i % (2*((int) MAX_LINEWIDTH) - 1)) + 1)/2.0;
	  set_graph_plotarr(cg ,setno ,&p);
	  break;
	case SETAPP_ALL_LINES:
	  get_graph_plotarr(cg ,setno ,&p);
	  p.lines = (i % (number_of_linestyles() - 1)) + 1;
	  set_graph_plotarr(cg ,setno ,&p);
	  break;
	case SETAPP_ALL_BW:
	  set_set_colors(cg ,setno ,1);
	  break;
	case SETAPP_KILL:
	  sprintf (message ,"Kill set %d in graph %d?" ,setno ,cg);
	  if (yesno (message) == TRUE) {
	    killset     (cg ,setno);
	    ge_kill_set (cg ,setno);
	  }
	  break;
	}
	i++;
      }
    } while (gtk_tree_model_iter_next (model ,&iter));
  }
  if (action == SETAPP_KILL) {
    gg_update_all ();    
  }
  cset = gw_list_get_first_selected_row_num (GW_LIST(w));
  if (is_valid_setno (cg ,cset) != TRUE)  return;
  ge_graph_update (cg);
  set_dirtystate  ();
  gg_drawgraph    ();
}

/**
 *  Replace set_cset_proc     setappwin.c 639
 *  Je pense que ce CB      NE SERT A RIEN
 */
static void ge_graph_set_cset_CB (GtkTreeSelection *sel ,Gw_list *w)
{
  int gno;

  if (sets_list != NULL) {
    cset = gw_list_get_first_selected_row_num (GW_LIST(sets_list));
    if (is_valid_setno (cg ,cset) != TRUE)  return;
    gno = get_cg();
  }
}

static void ge_graph_collapse_layers_CB (GtkWidget *w ,gpointer p)
{
  Ge_tree *getree;
  Qtype typ ,father_typ;
  gint  gno ,father_id;
  gboolean hidden;
  gchar *b1 ,*b2;
  int num;
  int frame_layer ,title_layer ,stitle_layer;
  int la = gg_get_int (layer.w);
  getree = get_getree ();
  if (ge_tree_get_selected (getree ,&typ ,&gno
			    ,&father_typ ,&father_id
			    ,&b1 ,&b2 ,&hidden)
      ) {
    if (typ != Q_Graph) {
      errmsg ("Selected row is not a Graph");
      return;
    }
    num = obj_tid_get_graph_num (gno);
    nn_cmd_undo_start     (TRUE ,gno);                    /*  undo/redo */
    nn_cmd_prefix ("@   ");
    if (get_graph_layers (gno ,&frame_layer ,&title_layer ,&stitle_layer) == RETURN_SUCCESS) {
      nn_cmd_i (&frame_layer  ,la ,"%s frame layer %d\n");
      nn_cmd_i (&title_layer  ,la ,"%s title layer %d\n");
      nn_cmd_i (&stitle_layer ,la ,"%s subtitle layer %d\n");
      set_graph_layers (gno ,la ,la ,la);
    } else {
      errmsg ("ge_graph_collapse_layers_CB: error in get_graph_layers");
      return;
    }
    obj_collapse_layers (objs[num].child ,la);
    nn_cmd_undo_end (TRUE ,gno);   
    gg_update_layers_hbox ();
    objs[num].layer = la;
    set_dirtystate    ();
    ge_graph_update (-2);
    gg_drawgraph      ();
  } else {
    errmsg ("Only one row must be selected to collapse layers ");
  }
}

/************* Button 3 menu **********/

static GtkWidget *u_graphs_dialog = NULL;
static GtkWidget *title_offset_x;
static GtkWidget *title_offset_y;
static GtkWidget *stitle_offset_x;
static GtkWidget *stitle_offset_y;


static GtkWidget *ge_graphs_u_new (void);
static void  	  ge_graphs_u_AAC_CB (GtkWidget *widget ,gint reponse);

/**
 *  Called by ge_tree_CB via gg_graph_popup_menu3
 *  Compare to gg_graph_menu3_CB
 */
void ge_graph_menu3_CB  (GtkWidget *w ,gpointer pact)
{
  gint action = GPOINTER_TO_INT (pact);
  GtkTreeIter iter;
  GtkTreeSelection *select;
  GList *lpath = NULL;
  int n ,id ,j;
  Ge_tree *getree;
  switch (action) {
  case MenuGraphsUpdate:
    ge_graphs_u_new ();
    break;
  default:
    getree = get_getree ();
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (getree->view));
    n      = gtk_tree_selection_count_selected_rows (select);
    lpath  = gtk_tree_selection_get_selected_rows (select ,&(getree->model));
    /* the list must be traversed un reverse order */
    lpath = g_list_last (lpath);
    j = 0;
    while (lpath != NULL) {
      if (gtk_tree_model_get_iter (getree->model ,&iter ,lpath->data)) {
	gtk_tree_model_get (getree->model ,&iter ,GE_TREE_ID ,&id ,-1);
	gg_graph_menu3_actions (action ,n ,id ,j);
	lpath = g_list_previous (lpath);
	j++;
      }
    }
    gg_update_all ();
    gg_drawgraph  ();
  }
}

/************** COLLECTIVE and SELECTIVE UPDATE of GRAPHS *******************/

#define U_GRAPHS_RESET 1001

static GtkWidget *ge_graphs_u_new (void)
{
  GtkWidget *vb ,*ta;
  if (u_graphs_dialog == NULL) {
    u_graphs_dialog = gg_CreateAACDialog ("Update params." ,ge_graphs_u_AAC_CB ,0 ,0 ,&vb);
    gtk_dialog_add_buttons (GTK_DIALOG (u_graphs_dialog) ,"Reset" ,U_GRAPHS_RESET ,NULL);
    gg_label_new (vb ,"Choose items to update in the selected graphs");

    ta 	      	    	 = gg_frame     (vb ,"Graph viewport"  	  ,&wheat ,2,2);
    wu_x1.u   	    	 = gg_check_new (ta ,"Xmin");
    wu_x2.u   	    	 = gg_check_new (ta ,"Xmax");
    wu_y1.u   	    	 = gg_check_new (ta ,"Ymin");
    wu_y2.u   	    	 = gg_check_new (ta ,"Ymax");

    ta 	      	    	 = gg_frame     (vb ,"Graph title"  	  ,&bleuciel ,4,2);
    title_color.u   	 = gg_check_new (ta ,"Color");
    title_font.u   	 = gg_check_new (ta ,"Font");
    title_size.u   	 = gg_check_new (ta ,"Size");
    title_just.u   	 = gg_check_new (ta ,"Justification");
    title_offset_x       = gg_check_new (ta ,"Offset X");
    title_offset_y       = gg_check_new (ta ,"Offset Y");

    ta 	      	    	 = gg_frame     (vb ,"Graph subtitle"  	  ,&wheat ,4,2);
    stitle_color.u   	 = gg_check_new (ta ,"Color");
    stitle_font.u   	 = gg_check_new (ta ,"Font");
    stitle_size.u   	 = gg_check_new (ta ,"Size");
    stitle_just.u   	 = gg_check_new (ta ,"Justification");
    stitle_offset_x      = gg_check_new (ta ,"Offset X");
    stitle_offset_y      = gg_check_new (ta ,"Offset y");

    ta 	      	    	 = gg_frame     (vb ,"Frame box"  	  ,&bleuciel ,4,2);
    f_type.u   	 	 = gg_check_new (ta ,"Frame type");
    f_pen_color.u   	 = gg_check_new (ta ,"Color");
    f_pen_pattern.u   	 = gg_check_new (ta ,"Pattern");
    f_linew.u   	 = gg_check_new (ta ,"Width");
    f_lines.u   	 = gg_check_new (ta ,"Style");
    f_fillpen_color.u    = gg_check_new (ta ,"Fill color");
    f_fillpen_pattern.u  = gg_check_new (ta ,"Fill pattern");

    ta 	      	    	 = gg_frame     (vb ,"Layers"  	  ,&wheat ,4,1);
    title_layer.u        = gg_check_new (ta ,"Title layer");
    stitle_layer.u       = gg_check_new (ta ,"Subtitle layer");
    f_layer.u   	 = gg_check_new (ta ,"Frame layer");
  }
  gtk_widget_show_all (u_graphs_dialog);
  return u_graphs_dialog;
}

static int ge_graphs_u_apply (int gno)
{
  graph *gr;
  int num;
  gr = copy_graph_params (gno);
  if (wu_evalexpr (wu_x1 ,&(gr->v.xv1))  == RETURN_FAILURE) {
    errmsg ("Error reading viewport Xmin");
    free_graph_params (gr);
    return RETURN_FAILURE;
  }
  if (wu_evalexpr (wu_y1 ,&(gr->v.yv1))  == RETURN_FAILURE) {
    errmsg ("Error reading viewport Ymin");
    free_graph_params (gr);
    return RETURN_FAILURE;
  }
  if (wu_evalexpr (wu_x2 ,&(gr->v.xv2))  == RETURN_FAILURE) {
    errmsg ("Error reading viewport Xmax");
    free_graph_params (gr);
    return RETURN_FAILURE;
  }
  if (wu_evalexpr (wu_y2 ,&(gr->v.yv2))  == RETURN_FAILURE) {
    errmsg ("Error reading viewport Ymax");
    free_graph_params (gr);
    return RETURN_FAILURE;
  }
  set_graph_viewport (gno ,gr->v);

  wu_get_int  (title_color ,&(gr->labs.title.color));
  wu_get_int  (title_font  ,&(gr->labs.title.font));
  wu_get_dble (title_size  ,&(gr->labs.title.charsize));
  wu_get_int  (title_just  ,&(gr->labs.title.just));
  wu_get_int  (title_layer ,&(gr->labs.title.layer));
  if (gg_get_int (title_offset_x)) gr->labs.title.x1 = gg_get_dble (w_title_xy.spin1);
  if (gg_get_int (title_offset_y)) gr->labs.title.y1 = gg_get_dble (w_title_xy.spin2);

  wu_get_int  (stitle_color ,&(gr->labs.stitle.color));
  wu_get_int  (stitle_font  ,&(gr->labs.stitle.font));
  wu_get_dble (stitle_size  ,&(gr->labs.stitle.charsize));
  wu_get_int  (stitle_just  ,&(gr->labs.stitle.just));
  wu_get_int  (stitle_layer ,&(gr->labs.stitle.layer));
  if (gg_get_int (stitle_offset_x)) gr->labs.stitle.x1 = gg_get_dble (w_stitle_xy.spin1);
  if (gg_get_int (stitle_offset_y)) gr->labs.stitle.y1 = gg_get_dble (w_stitle_xy.spin2);
  set_graph_labels (gno ,&(gr->labs));

  wu_get_int  (f_type 		 ,&(gr->f.type));
  wu_get_int  (f_pen_color 	 ,&(gr->f.pen.color));
  wu_get_int  (f_pen_pattern 	 ,&(gr->f.pen.pattern));
  wu_get_dble (f_linew 		 ,&(gr->f.linew));
  wu_get_int  (f_lines 		 ,&(gr->f.lines));
  wu_get_int  (f_fillpen_color 	 ,&(gr->f.fillpen.color));
  wu_get_int  (f_fillpen_pattern ,&(gr->f.fillpen.pattern));
  wu_get_int  (f_layer 		 ,&(gr->f.layer));
  set_graph_framep (gno ,&(gr->f));

  num = obj_tid_get_graph_num (gno);
  wu_get_int  (layer ,&(objs[num].layer));

  free_graph_params (gr);
  return RETURN_SUCCESS;
}

static void ge_graphs_u_AAC_CB (GtkWidget *widget ,gint reponse)
{
  if (reponse == U_GRAPHS_RESET) {
    wu_reset_u (wu_x1);
    wu_reset_u (wu_x2);
    wu_reset_u (wu_y1);
    wu_reset_u (wu_y2);
    wu_reset_u (title_color);
    wu_reset_u (title_font);
    wu_reset_u (title_size);
    wu_reset_u (title_just);
    wu_reset_u (title_layer);
    gg_set_int (title_offset_x ,FALSE);
    gg_set_int (title_offset_y ,FALSE);
    wu_reset_u (stitle_color);
    wu_reset_u (stitle_font);
    wu_reset_u (stitle_size);
    wu_reset_u (stitle_just);
    wu_reset_u (stitle_layer);
    gg_set_int (stitle_offset_x ,FALSE);
    gg_set_int (stitle_offset_y ,FALSE);
    wu_reset_u (f_type);
    wu_reset_u (f_pen_color);
    wu_reset_u (f_pen_pattern);
    wu_reset_u (f_lines);
    wu_reset_u (f_linew);
    wu_reset_u (f_fillpen_color);
    wu_reset_u (f_fillpen_pattern);
    wu_reset_u (f_layer);
  } else if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY) {
    int gno;
    Qtype typ;
    GtkTreeIter iter;
    GtkTreeSelection *select;
    GList *lpath = NULL;
    Ge_tree *getree;
    getree = get_getree ();
    int n = ge_selection_is_homogeneous (&typ);
    if (n < 1 || typ != Q_Graph) {
      errmsg ("Selection must have one or several graphs only");
      return;
    }
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (getree->view));
    lpath  = gtk_tree_selection_get_selected_rows (select ,&(getree->model));
    while (lpath != NULL) {
      if (gtk_tree_model_get_iter (getree->model ,&iter ,lpath->data)) {
	gtk_tree_model_get (getree->model ,&iter
			    ,GE_TREE_ID        ,&gno
			    ,-1);
 	if (ge_graphs_u_apply (gno) == RETURN_FAILURE) return;
	lpath = g_list_next (lpath);
      }
    }
    set_dirtystate ();
    gg_drawgraph  ();
  }




  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_CLOSE) {
    gtk_widget_hide (u_graphs_dialog);
  }
  wu_update_on (FALSE);

}

/******************** GRACE-5 COMPATIBILITY ********************/

void ge_graph_g5compat_CB (GtkWidget *w ,gpointer p)
{
  int gno = get_cg ();
  int num = obj_tid_get_graph_num (gno);
  ge_explorer_popup ();
  ge_unselect_all   ();
  if (obj_is_active (num)) {
    obj_make_current (num);
    current_page = 0;
    ge_select_current ();
  } else {                   /* should not happen */

    printf ("ge_graph_g5compat_CB: should not happe\n");

    ge_project_set_page ();
  }
}
