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

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

node GraphWin::read_node() {
  if (gr_p->number_of_nodes() == 0) return nil;
  point p;
  node v = nil;
  win_p->message("Determine a node!");
  do {
    if (win_p->read_mouse(p) == DEL_BUTTON) break;
    v=find_node(p);
  }
  while (v == nil);
  win_p->del_messages();
  return v;
}

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

edge GraphWin::read_edge() {
  if (gr_p->number_of_edges() == 0) return nil;
  point p;
  edge e = nil;
  win_p->message("Determine an edge!");
  do {
    if (win_p->read_mouse(p) == DEL_BUTTON) break;
    e=find_edge(p);
  }
  while (e == nil);
  win_p->del_messages();
  return e;
}

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

void gw_reduce_polygon(list<point>& P) {
  // removes segments of length zero from P, precond: P is not empty()!
  list_item it=P.first(),it2;
  point p=P[it];
  while ((it=P.succ(it)) != nil) {
    while (P[it] == p) { 
      it=P.succ(it2=it);
      P.del_item(it2);    
      if (it == nil) return;
    }
    if (it == nil) return;
    p=P[it];
  }
}

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

unsigned long GraphWin::read_mouse_rect(double& x0, double& y0, 
                                        double& x1, double& y1, bool pressed) 
{
  drawing_mode old_mode=win_p->set_mode(xor_mode);

  double x_first,y_first;
  double x_last,y_last;
  double x,y;
  unsigned long t0,t1;
  int val,event;
  if (pressed) {
    x_first=x0;
    y_first=y0;
  }
  else {
    win_p->read_mouse(x_first,y_first);
    t0 = win_p->button_press_time();
  }
  x=x_last=x_first;
  y=y_last=y_first;
  win_p->draw_rectangle(x_first,y_first,x,y,black);
  do {
    event = win_p->read_event(val,x,y,t1);
    if ((x_last != x) || (y_last != y)) {
      win_p->draw_rectangle(x_first,y_first,x,y,black);
      win_p->draw_rectangle(x_first,y_first,x_last,y_last,black);
      x_last=x;
      y_last=y;
    }
  }
  while(event != button_release_event);
  win_p->draw_rectangle(x_first,y_first,x,y,black);
  x1=x;
  y1=y;

  win_p->set_mode(old_mode);

  if (pressed) return t1;
  return t1-t0; 
}

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

bool GraphWin::define_area(double& x0, double& y0, 
                           double& x1, double& y1, const char* msg) {
  win_p->message(msg);
  point p,q;
  int but;
  but=win_p->read_mouse(x0,y0);
  if (but == DEL_BUTTON) {
    win_p->del_messages();
    return false;
  }
  read_mouse_rect(x0,y0,x1,y1,true);  
  win_p->del_messages();
  return true;
}


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

list<node> GraphWin::get_nodes_in_area(double x0, double y0, 
                                       double x1, double y1) {
  if (x0 > x1) { double tmp=x0; x0=x1; x1=tmp; }
  if (y0 > y1) { double tmp=y0; y0=y1; y1=tmp; }
  node v;
  double x,y;
  point p;
  list<node> L;
  forall_nodes(v,*gr_p) {
    p=get_position(v);
    x=p.xcoord();
    y=p.ycoord();
    if ((x >= x0) && (x <= x1) && (y >= y0) && (y <= y1)) L.append(v);
  }  
  return L;
}

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


// EMBED_SAVING : save position of v and polygons of all adj. edges 

static list<point> _gw_cc_[2][500];	// not more than 500 inout-edges	

static point _gw_pp_[2];

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

void GraphWin::save_embed(node v, unsigned s) {

  unsigned k=0;
  edge e;

  _gw_pp_[s]=n_info[v].pos;
  
  list<point> *c=_gw_cc_[s];

  forall_adj_edges(e,v) c[k++]=e_info[e].p;
  forall_in_edges(e,v) if (source(e) != v) c[k++]=e_info[e].p;
  
}

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

void GraphWin::restore_embed(node v, unsigned r) {

  unsigned k=0;
  edge e;

  n_info[v].pos=_gw_pp_[r];

  list<point> *c=_gw_cc_[r];

  forall_adj_edges(e,v) e_info[e].p=c[k++];
  forall_in_edges(e,v) if (source(e) != v) e_info[e].p=c[k++];
}

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

void GraphWin::save_and_restore_embed(node v, unsigned s, unsigned r) {

  unsigned k=0;
  edge e;
  
  point &p=n_info[v].pos;

  _gw_pp_[s]=p;
  p=_gw_pp_[r];
  
  list<point> *c_s=_gw_cc_[s];
  list<point> *c_r=_gw_cc_[r];

  forall_adj_edges(e,v) {
    edge_info &e_inf=e_info[e];
    c_s[k]=e_inf.p;
    e_inf.p=c_r[k++];
  }

  forall_in_edges(e,v) {
    if (source(e) != v) {
      edge_info &e_inf=e_info[e];
      c_s[k]=e_inf.p;
      e_inf.p=c_r[k++];
    }
  }
}

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

void GraphWin::acknowledge(string s) {
  win_p->acknowledge(s);
}

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

void GraphWin::open_msg_win() 
{ window& W = get_window();
//int x = (win_p->width() - msg_win->width())/2;
//int y = 5;
  int x = 0;
  int y = W.ypix(W.ymax());
  msg_win->open(W,x,y);
}    

void GraphWin::show_msg(const char* msg)
{ msg_win->clear(ivory);
  if (msg) msg_win->message(msg);
}    

void GraphWin::open_status_win() 
{ window& W = get_window();
  status_win->resize(win_p->width()-2,18);
  status_win->open(W,0,W.ypix(W.ymin())-20);
  status_redraw(status_win);
}    



int GraphWin::wait(unsigned sec, const char* msg) {
  win_p->message(msg);
  int old_done_result=set_done_result(-1);
  while ((sec--) && (get_done_result() == -1)) {
    win_p->get_mouse();
    ::wait(1);
  }   
  win_p->del_messages();
  return set_done_result(old_done_result);
}    
    
//----------------------------------------------------------------------------

int GraphWin::wait(const char* msg) {
  win_p->message(msg);
  int old_done_result=set_done_result(-1);
  window *wp;
  double x,y;
  while(get_done_result() == -1) read_mouse(wp,x,y);
  win_p->del_messages();
  return set_done_result(old_done_result);
}    
    
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

