/*******************************************************************************
+
+  LEDA 3.5
+
+  graphwin.c
+
+  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.
+ 
*******************************************************************************/
#include <LEDA/graphwin.h>
#include "../../src/graphwin/local.h"

//----------------------------------------------------------------------------
// constructors
//----------------------------------------------------------------------------

static char* def_label = "LEDA GraphWin 1.0";


GraphWin::GraphWin(graph& G, window& W) { 
  LEDA::write_log(def_label);
  create_flag=cr_none;
  init(G,W);
}
    
//----------------------------------------------------------------------------

GraphWin::GraphWin(graph& G, const char* win_label) {
  LEDA::write_log(string("GraphWin (%s)",win_label));
  create_flag=cr_win;
  int win_h = (int)(0.95*window::screen_height());
  int win_w = (int)(0.95*win_h);
  if (win_w > DefWinSizeX) win_w = DefWinSizeX;
  if (win_h > DefWinSizeY) win_h = DefWinSizeY;
  init(G,*(new window(win_w,win_h,win_label)));  
}

GraphWin::GraphWin(graph& G) {
  LEDA::write_log(def_label);
  create_flag=cr_win;
  int win_h = (int)(0.95*window::screen_height());
  int win_w = (int)(0.95*win_h);
  if (win_w > DefWinSizeX) win_w = DefWinSizeX;
  if (win_h > DefWinSizeY) win_h = DefWinSizeY;
  init(G,*(new window(win_w,win_h,def_label)));  
}
    
    
//----------------------------------------------------------------------------

GraphWin::GraphWin(graph& G, float w, float h, const char* win_label) {
  LEDA::write_log(string("GraphWin (%s)",win_label));
  create_flag=cr_win;
  init(G,*(new window(w,h,win_label)));  
}

GraphWin::GraphWin(graph& G, float w, float h) {
  LEDA::write_log(def_label);
  create_flag=cr_win;
  init(G,*(new window(w,h,def_label)));  
}
    
//----------------------------------------------------------------------------

GraphWin::GraphWin(window& W) { 
  LEDA::write_log(def_label);
  create_flag=cr_graph;
  init(*(new graph),W);
}
    
//----------------------------------------------------------------------------

GraphWin::GraphWin(const char* win_label) { 
  LEDA::write_log(string("GraphWin (%s)",win_label));
  create_flag=cr_graph | cr_win;
  int win_h = (int)(0.95*window::screen_height());
  int win_w = (int)(0.95*win_h);
  if (win_w > DefWinSizeX) win_w = DefWinSizeX;
  if (win_h > DefWinSizeY) win_h = DefWinSizeY;
  graph*  g = new graph;
  window* w = new window(win_w,win_h,win_label);
  init(*g,*w);
}


GraphWin::GraphWin() { 
  LEDA::write_log(def_label);
  create_flag=cr_graph | cr_win;
  int win_h = (int)(0.95*window::screen_height());
  int win_w = (int)(0.95*win_h);
  if (win_w > DefWinSizeX) win_w = DefWinSizeX;
  if (win_h > DefWinSizeY) win_h = DefWinSizeY;
  graph*  g = new graph;
  window* w = new window(win_w,win_h,def_label);
  init(*g,*w);
}
    
//----------------------------------------------------------------------------

GraphWin::GraphWin(float w, float h, const char* win_label) { 
  LEDA::write_log(string("GraphWin (%s)",win_label));
  create_flag=cr_graph | cr_win;
  init(*(new graph),*(new window(w,h,win_label)));
}

GraphWin::GraphWin(float w, float h) { 
  LEDA::write_log(def_label);
  create_flag=cr_graph | cr_win;
  init(*(new graph),*(new window(w,h,def_label)));
}

    
    
//----------------------------------------------------------------------------

GraphWin::~GraphWin() {

  if (leda_xpm) win_p->del_pixrect(leda_xpm);
 
  if (action) delete action;

  if (sub_menus) {
    int i;
    for(i=0;i<call_entry_counter;i++) delete menu_functions[i];
    for(i=1;i<sub_menu_counter;i++) delete sub_menus[i];
  }

  win_p->set_redraw();
  delete menu_p;

  if (create_flag & cr_graph) delete gr_p;

}

//----------------------------------------------------------------------------

void GraphWin::update_win_bounds() {
  x_min=win_p->xmin();
  x_max=win_p->xmax();
  y_min=win_p->ymin();
  y_max=win_p->ymax();
}

//----------------------------------------------------------------------------

void GraphWin::display() {
  init_window();
  if (!edges_embedded) embed_edges();
  redraw();
}

void GraphWin::display(int x, int y) {
  init_window(x,y);
  if (!edges_embedded) embed_edges();
  redraw();
}
    
//----------------------------------------------------------------------------

int GraphWin::open() {
  display(); 
  return edit();
}

int GraphWin::open(int x, int y) {
  display(x,y); 
  return edit();
}

//----------------------------------------------------------------------------

void GraphWin::close() { 
  win_p->close();
  menu_p->close(); 
}

//----------------------------------------------------------------------------

node GraphWin::new_node(const point& p) {

  node v = gr_p->new_node();

  init_node(v);
  n_info[v].pos=p;

  // clear entries in adj_matrix
  node w;
  forall_nodes(w,*gr_p) { 
    if (adj_matrix_first.defined(v,w)) adj_matrix_first(v,w) = nil;
    if (adj_matrix_first.defined(w,v)) adj_matrix_first(w,v) = nil;
  }

  if (get_flush()) draw_node(v);
  return v;
}

//----------------------------------------------------------------------------

edge GraphWin::new_edge(node v, node w, const list<point>& P) {
  bool old_flush=get_flush();

  edge e=gr_p->new_edge(v,w);
  if (e == nil) return nil;

  // insert e into adjacency matrix

  adj_matrix_succ[e] = adj_matrix_first(v,w);
  adj_matrix_first(v,w) = e;

  init_edge(e);

// if ((v == w) && (P.size() == 0)) {  ... selfloop ...}

  point v_p=get_position(v);
  point w_p=get_position(w);
  list<point>& L=e_info[e].p;
  L=P;
  L.push(v_p);
  L.append(w_p);
  gw_reduce_polygon(L);
  if (L.size() == 1) L.append(w_p);	// (v_p == w_p)

  if (old_flush) {
    embed_edges(v,w);
    redraw();
  }
  else edges_embedded=false;

  return e;
}

//----------------------------------------------------------------------------

edge GraphWin::new_edge(node v, node w) { 
  list<point> P;
  return new_edge(v,w,P);
}

//----------------------------------------------------------------------------

void GraphWin::del_edge(edge e) {

  e_info[e].init=false;		// only because for new edges are NO new
				// infos in map e_info created.

  bool before = edges_embedded;
  node v = source(e);
  node w = target(e);

  bool old_flush=set_flush(false);

  deselect(e);

  // remove e from adjacency matrix

  edge x = adj_matrix_first(v,w);
  edge pred = nil;
  while(x != e) 
  { pred = x;
    x = adj_matrix_succ[x];
   }
  if (pred) 
     adj_matrix_succ[pred] = adj_matrix_succ[x];
  else 
     adj_matrix_first(v,w) = adj_matrix_succ[x];


  gr_p->del_edge(e);
  if (old_flush) {
      embed_edges(v,w);
      redraw();
      edges_embedded=before;
  }
  else edges_embedded=false;
  set_flush(old_flush);
}

//----------------------------------------------------------------------------

void GraphWin::del_node(node v) {

  n_info[v].init=false;		// only because for new nodes are NO new  
				// infos in map n_info created.

  bool old_flush=set_flush(false);		// don't follow del_edge 

  bool before=edges_embedded;			// edges_embedded not changed!!
  edge e;
  if (is_selected(v)) deselect(v);
  forall_inout_edges(e,v) del_edge(e);		// remove all assigned edges

  gr_p->del_node(v);
  edges_embedded=before;
  if (old_flush) redraw();
  set_flush(old_flush);
}

//----------------------------------------------------------------------------


void GraphWin::clear_graph() 
{ gr_p->clear();
  init_graph();
  win_init(DefXMin,DefXMax,DefYMin);
 }

