graph_displayer_canvas-event.cc
author hegyi
Thu, 01 Mar 2007 16:28:13 +0000
changeset 198 d6cc0579b94b
parent 187 b465e2c34f23
child 200 c7ae8642a8d8
permissions -rwxr-xr-x
Shape feature of EPS can be used.
alpar@174
     1
/* -*- C++ -*-
alpar@174
     2
 *
alpar@174
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@174
     4
 *
alpar@174
     5
 * Copyright (C) 2003-2006
alpar@174
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@174
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@174
     8
 *
alpar@174
     9
 * Permission to use, modify and distribute this software is granted
alpar@174
    10
 * provided that this copyright notice appears in all copies. For
alpar@174
    11
 * precise terms see the accompanying LICENSE file.
alpar@174
    12
 *
alpar@174
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@174
    14
 * express or implied, and with no claim as to its suitability for any
alpar@174
    15
 * purpose.
alpar@174
    16
 *
alpar@174
    17
 */
alpar@174
    18
hegyi@194
    19
#include <graph_displayer_canvas.h>
hegyi@194
    20
#include <mapstorage.h>
hegyi@194
    21
#include <nbtab.h>
alpar@59
    22
#include <cmath>
hegyi@27
    23
hegyi@27
    24
hegyi@27
    25
bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
hegyi@27
    26
{
hegyi@27
    27
  Gnome::Canvas::CanvasAA::on_expose_event(event);
hegyi@27
    28
  //usleep(10000);
hegyi@27
    29
  //rezoom();
hegyi@27
    30
  return true;
hegyi@27
    31
}
hegyi@27
    32
hegyi@27
    33
void GraphDisplayerCanvas::changeEditorialTool(int newtool)
hegyi@27
    34
{
hegyi@34
    35
  if(actual_tool!=newtool)
hegyi@34
    36
    {
hegyi@27
    37
hegyi@34
    38
      actual_handler.disconnect();
hegyi@27
    39
hegyi@34
    40
      switch(actual_tool)
hegyi@34
    41
	{
hegyi@34
    42
	case CREATE_EDGE:
hegyi@34
    43
	  {
hegyi@34
    44
	    GdkEvent * generated=new GdkEvent();
hegyi@34
    45
	    generated->type=GDK_BUTTON_RELEASE;
hegyi@34
    46
	    generated->button.button=3;
hegyi@34
    47
	    createEdgeEventHandler(generated);      
hegyi@34
    48
	    break;
hegyi@34
    49
	  }
hegyi@149
    50
	case MAP_EDIT:
hegyi@35
    51
	  {
hegyi@35
    52
	    break;
hegyi@35
    53
	  }
hegyi@34
    54
	default:
hegyi@34
    55
	  break;
hegyi@34
    56
	}
hegyi@27
    57
hegyi@34
    58
      active_item=NULL; 
hegyi@34
    59
      target_item=NULL; 
hegyi@34
    60
      active_edge=INVALID;	
hegyi@34
    61
      active_node=INVALID;	
hegyi@33
    62
hegyi@27
    63
hegyi@34
    64
      actual_tool=newtool;
hegyi@34
    65
  
hegyi@34
    66
      switch(newtool)
hegyi@34
    67
	{
hegyi@34
    68
	case MOVE:
hegyi@34
    69
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
hegyi@34
    70
	  break;
hegyi@27
    71
hegyi@34
    72
	case CREATE_NODE:
hegyi@34
    73
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
hegyi@34
    74
	  break;
hegyi@27
    75
hegyi@34
    76
	case CREATE_EDGE:
hegyi@34
    77
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
hegyi@34
    78
	  break;
hegyi@27
    79
hegyi@34
    80
	case ERASER:
hegyi@34
    81
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
hegyi@34
    82
	  break;
hegyi@32
    83
hegyi@149
    84
	case MAP_EDIT:
hegyi@34
    85
	  grab_focus();
hegyi@149
    86
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
hegyi@34
    87
	  break;
hegyi@34
    88
hegyi@34
    89
	default:
hegyi@34
    90
	  break;
hegyi@34
    91
	}
hegyi@27
    92
    }
hegyi@27
    93
}
hegyi@27
    94
hegyi@30
    95
int GraphDisplayerCanvas::getActualTool()
hegyi@27
    96
{
hegyi@27
    97
  return actual_tool;
hegyi@27
    98
}
hegyi@27
    99
hegyi@187
   100
bool GraphDisplayerCanvas::scrollEventHandler(GdkEvent* e)
hegyi@187
   101
{
hegyi@187
   102
  bool handled=false;
hegyi@187
   103
  if(e->type==GDK_SCROLL)
hegyi@187
   104
    {
hegyi@187
   105
hegyi@187
   106
      //pointer shows this win point before zoom
hegyi@187
   107
      XY win_coord(((GdkEventScroll*)e)->x, ((GdkEventScroll*)e)->y);
hegyi@187
   108
hegyi@187
   109
      //the original scroll settings
hegyi@187
   110
      int scroll_offset_x, scroll_offset_y;
hegyi@187
   111
      get_scroll_offsets(scroll_offset_x, scroll_offset_y);
hegyi@187
   112
hegyi@187
   113
      //pointer shows this canvas point before zoom
hegyi@187
   114
      XY canvas_coord;
hegyi@187
   115
      window_to_world(win_coord.x, win_coord.y, canvas_coord.x, canvas_coord.y);
hegyi@187
   116
hegyi@187
   117
      if(((GdkEventScroll*)e)->direction) //IN
hegyi@187
   118
	{
hegyi@187
   119
	  zoomIn();
hegyi@187
   120
	}
hegyi@187
   121
      else
hegyi@187
   122
	{
hegyi@187
   123
	  zoomOut();
hegyi@187
   124
	}
hegyi@187
   125
hegyi@187
   126
      //pointer shows this window point after zoom
hegyi@187
   127
      XY post_win_coord;
hegyi@187
   128
      world_to_window(canvas_coord.x, canvas_coord.y, post_win_coord.x, post_win_coord.y);
hegyi@187
   129
hegyi@187
   130
      //we have to add the difference between new and old window point to original scroll offset
hegyi@187
   131
      scroll_to(scroll_offset_x+(int)(post_win_coord.x-win_coord.x),scroll_offset_y+(int)(post_win_coord.y-win_coord.y));
hegyi@187
   132
      
hegyi@187
   133
      //no other eventhandler is needed
hegyi@187
   134
      handled=true;
hegyi@187
   135
    }
hegyi@187
   136
  return handled;
hegyi@187
   137
}
hegyi@187
   138
hegyi@30
   139
bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
hegyi@27
   140
{
ladanyi@70
   141
  static Gnome::Canvas::Text *coord_text = 0;
hegyi@27
   142
  switch(e->type)
hegyi@160
   143
    {
hegyi@27
   144
    case GDK_BUTTON_PRESS:
hegyi@27
   145
      //we mark the location of the event to be able to calculate parameters of dragging
hegyi@31
   146
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@160
   147
      
hegyi@31
   148
      active_item=(get_item_at(clicked_x, clicked_y));
hegyi@27
   149
      active_node=INVALID;
hegyi@194
   150
      for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@27
   151
	{
hegyi@27
   152
	  if(nodesmap[i]==active_item)
hegyi@27
   153
	    {
hegyi@27
   154
	      active_node=i;
hegyi@27
   155
	    }
hegyi@27
   156
	}
hegyi@148
   157
      isbutton=e->button.button;
hegyi@27
   158
      break;
hegyi@27
   159
    case GDK_BUTTON_RELEASE:
ladanyi@70
   160
      if (coord_text)
hegyi@160
   161
	{
hegyi@160
   162
	  delete coord_text;
hegyi@160
   163
	  coord_text = 0;
hegyi@160
   164
	}
hegyi@27
   165
      isbutton=0;
hegyi@27
   166
      active_item=NULL;
hegyi@27
   167
      active_node=INVALID;
hegyi@27
   168
      break;
hegyi@27
   169
    case GDK_MOTION_NOTIFY:
hegyi@27
   170
      //we only have to do sg. if the mouse button is pressed AND the click was on a node that was found in the set of nodes
hegyi@27
   171
      if(active_node!=INVALID)
hegyi@160
   172
	{
hegyi@194
   173
	  (mytab.mapstorage)->modified = true;
hegyi@160
   174
	  
hegyi@160
   175
	  //new coordinates will be the old values,
hegyi@160
   176
	  //because the item will be moved to the
hegyi@160
   177
	  //new coordinate therefore the new movement
hegyi@160
   178
	  //has to be calculated from here
hegyi@160
   179
	  
hegyi@160
   180
	  double new_x, new_y;
hegyi@160
   181
	  
hegyi@160
   182
	  window_to_world (e->motion.x, e->motion.y, new_x, new_y);
hegyi@160
   183
	  
hegyi@160
   184
	  double dx=new_x-clicked_x;
hegyi@160
   185
	  double dy=new_y-clicked_y;
hegyi@160
   186
	  
hegyi@160
   187
	  moveNode(dx, dy);
ladanyi@70
   188
hegyi@160
   189
	  clicked_x=new_x;
hegyi@160
   190
	  clicked_y=new_y;
hegyi@27
   191
hegyi@160
   192
	  // reposition the coordinates text
hegyi@160
   193
	  std::ostringstream ostr;
hegyi@160
   194
	  ostr << "(" <<
hegyi@194
   195
	    (mytab.mapstorage)->coords[active_node].x << ", " <<
hegyi@194
   196
	    (mytab.mapstorage)->coords[active_node].y << ")";
hegyi@160
   197
	  double radius =
hegyi@160
   198
	    (nodesmap[active_node]->property_x2().get_value() -
hegyi@160
   199
	     nodesmap[active_node]->property_x1().get_value()) / 2.0;
hegyi@160
   200
	  if (coord_text)
hegyi@160
   201
	    {
hegyi@160
   202
	      coord_text->property_text().set_value(ostr.str());
hegyi@194
   203
	      coord_text->property_x().set_value((mytab.mapstorage)->coords[active_node].x +
hegyi@160
   204
						 radius);
hegyi@194
   205
	      coord_text->property_y().set_value((mytab.mapstorage)->coords[active_node].y -
hegyi@160
   206
						 radius);
hegyi@160
   207
	    }
hegyi@160
   208
	  else
hegyi@160
   209
	    {
hegyi@160
   210
	      coord_text = new Gnome::Canvas::Text(
hegyi@160
   211
						   displayed_graph,
hegyi@194
   212
						   (mytab.mapstorage)->coords[active_node].x + radius,
hegyi@194
   213
						   (mytab.mapstorage)->coords[active_node].y - radius,
hegyi@160
   214
						   ostr.str());
hegyi@160
   215
	      coord_text->property_fill_color().set_value("black");
hegyi@160
   216
	      coord_text->property_anchor().set_value(Gtk::ANCHOR_SOUTH_WEST);
hegyi@160
   217
	    }
hegyi@31
   218
hegyi@31
   219
hegyi@160
   220
	}
hegyi@160
   221
    default: break;
hegyi@160
   222
    }
hegyi@27
   223
hegyi@160
   224
return false;
hegyi@27
   225
}
hegyi@27
   226
hegyi@148
   227
XY GraphDisplayerCanvas::calcArrowPos(XY moved_node_1, XY moved_node_2, XY fix_node, XY old_arrow_pos, int move_code)
ladanyi@98
   228
{
hegyi@148
   229
  switch(move_code)
hegyi@148
   230
    {
hegyi@148
   231
    case 1:
hegyi@148
   232
      return XY((moved_node_2.x + fix_node.x) / 2.0, (moved_node_2.y + fix_node.y) / 2.0);
hegyi@148
   233
      break;
hegyi@148
   234
    case 2:
hegyi@148
   235
      return old_arrow_pos;
hegyi@148
   236
      break;
hegyi@148
   237
    case 3:
hegyi@148
   238
      {
hegyi@148
   239
	//////////////////////////////////////////////////////////////////////////////////////////////////////
hegyi@148
   240
	/////////// keeps shape-with scalar multiplication - version 2.
hegyi@148
   241
	//////////////////////////////////////////////////////////////////////////////////////////////////////
ladanyi@98
   242
hegyi@148
   243
	//old vector from one to the other node - a
hegyi@150
   244
	XY a_v(moved_node_1.x-fix_node.x,moved_node_1.y-fix_node.y);
hegyi@148
   245
	//new vector from one to the other node - b
hegyi@150
   246
	XY b_v(moved_node_2.x-fix_node.x,moved_node_2.y-fix_node.y);
ladanyi@98
   247
hegyi@148
   248
	double absa=sqrt(a_v.normSquare());
hegyi@148
   249
	double absb=sqrt(b_v.normSquare());
ladanyi@98
   250
hegyi@148
   251
	if ((absa == 0.0) || (absb == 0.0))
hegyi@148
   252
	  {
hegyi@148
   253
	    return old_arrow_pos;
hegyi@148
   254
	  }
hegyi@148
   255
	else
hegyi@148
   256
	  {
hegyi@148
   257
	    //old vector from one node to the breakpoint - c
hegyi@150
   258
	    XY c_v(old_arrow_pos.x-fix_node.x,old_arrow_pos.y-fix_node.y);
hegyi@148
   259
hegyi@148
   260
	    //unit vector with the same direction to a_v
hegyi@150
   261
	    XY a_v_u(a_v.x/absa,a_v.y/absa);
hegyi@148
   262
hegyi@148
   263
	    //normal vector of unit vector with the same direction to a_v
hegyi@150
   264
	    XY a_v_u_n(((-1)*a_v_u.y),a_v_u.x);
hegyi@148
   265
hegyi@148
   266
	    //unit vector with the same direction to b_v
hegyi@150
   267
	    XY b_v_u(b_v.x/absb,b_v.y/absb);
hegyi@148
   268
hegyi@148
   269
	    //normal vector of unit vector with the same direction to b_v
hegyi@150
   270
	    XY b_v_u_n(((-1)*b_v_u.y),b_v_u.x);
hegyi@148
   271
hegyi@148
   272
	    //vector c in a_v_u and a_v_u_n co-ordinate system
hegyi@150
   273
	    XY c_a(c_v*a_v_u,c_v*a_v_u_n);
hegyi@148
   274
hegyi@148
   275
	    //new vector from one node to the breakpoint - d - we have to calculate this one
hegyi@150
   276
	    XY d_v=absb/absa*(c_a.x*b_v_u+c_a.y*b_v_u_n);
hegyi@148
   277
hegyi@148
   278
	    return XY(d_v.x+fix_node.x,d_v.y+fix_node.y);
hegyi@148
   279
	  }
hegyi@148
   280
	break;
hegyi@148
   281
      }
hegyi@148
   282
    default:
hegyi@148
   283
      break;
ladanyi@98
   284
    }
hegyi@148
   285
}
ladanyi@98
   286
ladanyi@98
   287
hegyi@30
   288
bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
hegyi@27
   289
{
hegyi@27
   290
  switch(e->type)
ladanyi@63
   291
  {
ladanyi@63
   292
    //move the new node
ladanyi@63
   293
    case GDK_MOTION_NOTIFY:
ladanyi@63
   294
      {
ladanyi@63
   295
        GdkEvent * generated=new GdkEvent();
ladanyi@63
   296
        generated->motion.x=e->motion.x;
ladanyi@63
   297
        generated->motion.y=e->motion.y;
ladanyi@63
   298
        generated->type=GDK_MOTION_NOTIFY;
ladanyi@63
   299
        moveEventHandler(generated);      
ladanyi@63
   300
        break;
ladanyi@63
   301
      }
hegyi@27
   302
ladanyi@63
   303
    case GDK_BUTTON_RELEASE:
hegyi@194
   304
      (mytab.mapstorage)->modified = true;
ladanyi@53
   305
hegyi@178
   306
      is_drawn=true;
hegyi@178
   307
hegyi@27
   308
      isbutton=1;
hegyi@27
   309
hegyi@194
   310
      active_node=(mytab.mapstorage)->graph.addNode();
hegyi@27
   311
hegyi@27
   312
      //initiating values corresponding to new node in maps
hegyi@27
   313
hegyi@27
   314
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@27
   315
ladanyi@63
   316
      // update coordinates
hegyi@194
   317
      (mytab.mapstorage)->coords.set(active_node, XY(clicked_x, clicked_y));
ladanyi@63
   318
ladanyi@63
   319
      // update all other maps
ladanyi@63
   320
      for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
hegyi@194
   321
          (mytab.mapstorage)->nodemap_storage.begin(); it !=
hegyi@194
   322
          (mytab.mapstorage)->nodemap_storage.end(); ++it)
ladanyi@63
   323
      {
ladanyi@64
   324
        if ((it->first != "coordinates_x") &&
ladanyi@64
   325
            (it->first != "coordinates_y"))
ladanyi@63
   326
        {
ladanyi@63
   327
          (*(it->second))[active_node] =
hegyi@194
   328
            (mytab.mapstorage)->nodemap_default[it->first];
ladanyi@63
   329
        }
ladanyi@63
   330
      }
ladanyi@64
   331
      // increment the id map's default value
hegyi@194
   332
      (mytab.mapstorage)->nodemap_default["label"] += 1.0;
ladanyi@63
   333
ladanyi@53
   334
      nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph,
ladanyi@63
   335
          clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
hegyi@27
   336
      active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
ladanyi@63
   337
      *(nodesmap[active_node]) <<
ladanyi@63
   338
        Gnome::Canvas::Properties::fill_color("blue");
ladanyi@63
   339
      *(nodesmap[active_node]) <<
ladanyi@63
   340
        Gnome::Canvas::Properties::outline_color("black");
ladanyi@63
   341
      active_item->raise_to_top();
ladanyi@63
   342
hegyi@27
   343
      (nodesmap[active_node])->show();
hegyi@28
   344
ladanyi@53
   345
      nodetextmap[active_node]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@63
   346
          clicked_x+node_property_defaults[N_RADIUS]+5,
ladanyi@63
   347
          clicked_y+node_property_defaults[N_RADIUS]+5, "");
hegyi@28
   348
      nodetextmap[active_node]->property_fill_color().set_value("darkblue");
ladanyi@63
   349
      nodetextmap[active_node]->raise_to_top();
hegyi@28
   350
hegyi@94
   351
//       mapwin.updateNode(active_node);
hegyi@94
   352
      propertyUpdate(active_node);
hegyi@28
   353
hegyi@27
   354
      isbutton=0;
hegyi@31
   355
      target_item=NULL;
hegyi@27
   356
      active_item=NULL;
hegyi@27
   357
      active_node=INVALID;
hegyi@27
   358
      break;
hegyi@27
   359
    default:
hegyi@27
   360
      break;
ladanyi@63
   361
  }
hegyi@27
   362
  return false;
hegyi@27
   363
}
hegyi@27
   364
hegyi@30
   365
bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
hegyi@27
   366
{
hegyi@27
   367
  switch(e->type)
ladanyi@63
   368
  {
hegyi@27
   369
    case GDK_BUTTON_PRESS:
hegyi@27
   370
      //in edge creation right button has special meaning
hegyi@27
   371
      if(e->button.button!=3)
ladanyi@63
   372
      {
ladanyi@63
   373
        //there is not yet selected node
ladanyi@63
   374
        if(active_node==INVALID)
ladanyi@63
   375
        {
ladanyi@63
   376
          //we mark the location of the event to be able to calculate parameters of dragging
hegyi@31
   377
ladanyi@63
   378
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@31
   379
ladanyi@63
   380
          active_item=(get_item_at(clicked_x, clicked_y));
ladanyi@63
   381
          active_node=INVALID;
hegyi@194
   382
          for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
ladanyi@63
   383
          {
ladanyi@63
   384
            if(nodesmap[i]==active_item)
ladanyi@63
   385
            {
ladanyi@63
   386
              active_node=i;
ladanyi@63
   387
            }
ladanyi@63
   388
          }
ladanyi@63
   389
          //the clicked item is really a node
ladanyi@63
   390
          if(active_node!=INVALID)
ladanyi@63
   391
          {
ladanyi@63
   392
            *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
ladanyi@63
   393
            isbutton=1;
ladanyi@63
   394
          }
ladanyi@63
   395
          //clicked item was not a node. It could be e.g. edge.
ladanyi@63
   396
          else
ladanyi@63
   397
          {
ladanyi@63
   398
            active_item=NULL;
ladanyi@63
   399
          }
ladanyi@63
   400
        }
ladanyi@63
   401
        //we only have to do sg. if the mouse button
ladanyi@63
   402
        // is pressed already once AND the click was
ladanyi@63
   403
        // on a node that was found in the set of 
ladanyi@63
   404
        //nodes, and now we only search for the second 
ladanyi@63
   405
        //node
ladanyi@63
   406
        else
ladanyi@63
   407
        {
ladanyi@63
   408
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
ladanyi@63
   409
          target_item=(get_item_at(clicked_x, clicked_y));
ladanyi@63
   410
          Node target_node=INVALID;
hegyi@194
   411
          for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
ladanyi@63
   412
          {
ladanyi@63
   413
            if(nodesmap[i]==target_item)
ladanyi@63
   414
            {
ladanyi@63
   415
              target_node=i;
ladanyi@63
   416
            }
ladanyi@63
   417
          }
ladanyi@63
   418
          //the clicked item is a node, the edge can be drawn
ladanyi@63
   419
          if(target_node!=INVALID)
ladanyi@63
   420
          {
hegyi@194
   421
            (mytab.mapstorage)->modified = true;
ladanyi@151
   422
ladanyi@151
   423
            *(nodesmap[target_node]) <<
ladanyi@151
   424
              Gnome::Canvas::Properties::fill_color("red");
ladanyi@151
   425
ladanyi@151
   426
            //creating new edge
hegyi@194
   427
            active_edge=(mytab.mapstorage)->graph.addEdge(active_node,
ladanyi@151
   428
                target_node);
ladanyi@151
   429
ladanyi@151
   430
            // update maps
ladanyi@151
   431
            for (std::map<std::string,
ladanyi@151
   432
                Graph::EdgeMap<double>*>::const_iterator it =
hegyi@194
   433
                (mytab.mapstorage)->edgemap_storage.begin(); it !=
hegyi@194
   434
                (mytab.mapstorage)->edgemap_storage.end(); ++it)
ladanyi@151
   435
            {
ladanyi@151
   436
              (*(it->second))[active_edge] =
hegyi@194
   437
                (mytab.mapstorage)->edgemap_default[it->first];
ladanyi@151
   438
            }
ladanyi@151
   439
            // increment the id map's default value
hegyi@194
   440
            (mytab.mapstorage)->edgemap_default["label"] += 1.0;
ladanyi@151
   441
ladanyi@63
   442
            if(target_node!=active_node)		
ladanyi@63
   443
            {
ladanyi@113
   444
              // set the coordinates of the arrow on the new edge
hegyi@194
   445
              MapStorage& ms = *mytab.mapstorage;
ladanyi@113
   446
              ms.arrow_pos.set(active_edge,
ladanyi@113
   447
                  (ms.coords[ms.graph.source(active_edge)] +
ladanyi@113
   448
                   ms.coords[ms.graph.target(active_edge)])/ 2.0);
ladanyi@113
   449
ladanyi@63
   450
              //drawing new edge
ladanyi@98
   451
              edgesmap[active_edge]=new BrokenEdge(displayed_graph, active_edge,
ladanyi@63
   452
                  *this);
ladanyi@63
   453
            }
ladanyi@63
   454
            else
ladanyi@63
   455
            {
ladanyi@151
   456
              // set the coordinates of the arrow on the new edge
hegyi@194
   457
              MapStorage& ms = *mytab.mapstorage;
ladanyi@151
   458
              ms.arrow_pos.set(active_edge,
ladanyi@151
   459
                  (ms.coords[ms.graph.source(active_edge)] +
ladanyi@151
   460
                   XY(0.0, 80.0)));
ladanyi@151
   461
ladanyi@151
   462
              //drawing new edge
ladanyi@151
   463
              edgesmap[active_edge]=new LoopEdge(displayed_graph, active_edge,
ladanyi@151
   464
                  *this);
ladanyi@63
   465
            }
ladanyi@151
   466
ladanyi@151
   467
            //initializing edge-text as well, to empty string
hegyi@194
   468
            XY text_pos=mytab.mapstorage->arrow_pos[active_edge];
ladanyi@151
   469
            text_pos+=(XY(10,10));
ladanyi@151
   470
ladanyi@151
   471
            edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@151
   472
                text_pos.x, text_pos.y, "");
ladanyi@151
   473
            edgetextmap[active_edge]->property_fill_color().set_value(
ladanyi@151
   474
                "darkgreen");
ladanyi@151
   475
            edgetextmap[active_edge]->raise_to_top();
ladanyi@151
   476
ladanyi@151
   477
            propertyUpdate(active_edge);
ladanyi@63
   478
          }
ladanyi@63
   479
          //clicked item was not a node. it could be an e.g. edge. we do not
ladanyi@63
   480
          //deal with it furthermore.
ladanyi@63
   481
          else
ladanyi@63
   482
          {
ladanyi@63
   483
            target_item=NULL;
ladanyi@63
   484
          }
ladanyi@63
   485
        }
ladanyi@63
   486
      }
hegyi@27
   487
      break;
hegyi@27
   488
    case GDK_BUTTON_RELEASE:
hegyi@27
   489
      isbutton=0;
hegyi@27
   490
      //we clear settings in two cases
hegyi@27
   491
      //1: the edge is ready (target_item has valid value)
hegyi@27
   492
      //2: the edge creation is cancelled with right button
hegyi@27
   493
      if((target_item)||(e->button.button==3))
ladanyi@63
   494
      {
ladanyi@63
   495
        if(active_item)
ladanyi@63
   496
        {
hegyi@179
   497
	  propertyUpdate(active_node,N_COLOR);
ladanyi@63
   498
          active_item=NULL;
ladanyi@63
   499
        }
ladanyi@63
   500
        if(target_item)
ladanyi@63
   501
        {
hegyi@194
   502
	  propertyUpdate((mytab.mapstorage)->graph.target(active_edge),N_COLOR);
ladanyi@63
   503
          target_item=NULL;
ladanyi@63
   504
        }
ladanyi@63
   505
        active_node=INVALID;
ladanyi@63
   506
        active_edge=INVALID;
ladanyi@63
   507
      }
hegyi@27
   508
      break;
hegyi@27
   509
    default:
hegyi@27
   510
      break;
ladanyi@63
   511
  }
hegyi@27
   512
  return false;
hegyi@27
   513
}
hegyi@27
   514
hegyi@30
   515
bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
hegyi@27
   516
{
hegyi@27
   517
  switch(e->type)
hegyi@27
   518
    {
hegyi@27
   519
    case GDK_BUTTON_PRESS:
hegyi@43
   520
      //finding the clicked items
hegyi@31
   521
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@31
   522
      active_item=(get_item_at(clicked_x, clicked_y));
hegyi@27
   523
      active_node=INVALID;
hegyi@27
   524
      active_edge=INVALID;
hegyi@43
   525
      //was it a node?
hegyi@194
   526
      for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@27
   527
	{
hegyi@27
   528
	  if(nodesmap[i]==active_item)
hegyi@27
   529
	    {
hegyi@27
   530
	      active_node=i;
hegyi@27
   531
	    }
hegyi@27
   532
	}
hegyi@43
   533
      //or was it an edge?
hegyi@27
   534
      if(active_node==INVALID)
hegyi@27
   535
	{
hegyi@194
   536
	  for (EdgeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@27
   537
	    {
ladanyi@153
   538
	      if(edgesmap[i]->getLine()==active_item)
hegyi@27
   539
		{
hegyi@27
   540
		  active_edge=i;
hegyi@27
   541
		}
hegyi@27
   542
	    }
hegyi@27
   543
	}
hegyi@43
   544
ladanyi@129
   545
      // return if the clicked object is neither an edge nor a node
ladanyi@129
   546
      if (active_edge == INVALID) return false;
ladanyi@129
   547
      
hegyi@43
   548
      //recolor activated item
hegyi@31
   549
      if(active_item)
hegyi@31
   550
	{
hegyi@31
   551
	  *active_item << Gnome::Canvas::Properties::fill_color("red");
hegyi@31
   552
	}
hegyi@27
   553
      break;
hegyi@27
   554
hegyi@27
   555
    case GDK_BUTTON_RELEASE:
hegyi@31
   556
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@31
   557
      if(active_item)
hegyi@27
   558
	{
hegyi@43
   559
	  //the cursor was not moved since pressing it
hegyi@31
   560
	  if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
hegyi@27
   561
	    {
hegyi@43
   562
	      //a node was found
hegyi@31
   563
	      if(active_node!=INVALID)
hegyi@31
   564
		{
hegyi@194
   565
                  (mytab.mapstorage)->modified = true;
hegyi@27
   566
hegyi@31
   567
		  std::set<Graph::Edge> edges_to_delete;
hegyi@27
   568
hegyi@194
   569
		  for(OutEdgeIt e((mytab.mapstorage)->graph,active_node);e!=INVALID;++e)
hegyi@31
   570
		    {
hegyi@31
   571
		      edges_to_delete.insert(e);
hegyi@31
   572
		    }
alpar@69
   573
		  
hegyi@194
   574
		  for(InEdgeIt e((mytab.mapstorage)->graph,active_node);e!=INVALID;++e)
hegyi@31
   575
		    {
hegyi@31
   576
		      edges_to_delete.insert(e);
hegyi@31
   577
		    }
alpar@69
   578
		  
hegyi@31
   579
		  //deleting collected edges
alpar@69
   580
		  for(std::set<Graph::Edge>::iterator
alpar@69
   581
			edge_set_it=edges_to_delete.begin();
alpar@69
   582
		      edge_set_it!=edges_to_delete.end();
alpar@69
   583
		      ++edge_set_it)
hegyi@31
   584
		    {
hegyi@31
   585
		      deleteItem(*edge_set_it);
hegyi@31
   586
		    }
hegyi@31
   587
		  deleteItem(active_node);
hegyi@31
   588
		}
hegyi@31
   589
	      //a simple edge was chosen
ladanyi@129
   590
	      else if (active_edge != INVALID)
hegyi@27
   591
		{
hegyi@31
   592
		  deleteItem(active_edge);
hegyi@27
   593
		}
hegyi@27
   594
	    }
hegyi@31
   595
	  //pointer was moved, deletion is cancelled
hegyi@27
   596
	  else
hegyi@27
   597
	    {
hegyi@31
   598
	      if(active_node!=INVALID)
hegyi@31
   599
		{
hegyi@31
   600
		  *active_item << Gnome::Canvas::Properties::fill_color("blue");
hegyi@31
   601
		}
ladanyi@129
   602
	      else if (active_edge != INVALID)
hegyi@31
   603
		{
hegyi@31
   604
		  *active_item << Gnome::Canvas::Properties::fill_color("green");
hegyi@31
   605
		}
hegyi@27
   606
	    }
hegyi@27
   607
	}
hegyi@27
   608
      //reseting datas
hegyi@27
   609
      active_item=NULL;
hegyi@27
   610
      active_edge=INVALID;
hegyi@27
   611
      active_node=INVALID;
hegyi@27
   612
      break;
hegyi@27
   613
hegyi@27
   614
    case GDK_MOTION_NOTIFY:
hegyi@27
   615
      break;
hegyi@27
   616
hegyi@27
   617
    default:
hegyi@27
   618
      break;
hegyi@27
   619
    }
hegyi@31
   620
  return false;
hegyi@27
   621
}
hegyi@27
   622
hegyi@149
   623
bool GraphDisplayerCanvas::mapEditEventHandler(GdkEvent* e)
hegyi@32
   624
{
hegyi@149
   625
  if(actual_tool==MAP_EDIT)
hegyi@32
   626
    {
hegyi@149
   627
      switch(e->type)
hegyi@149
   628
	{
hegyi@149
   629
	case GDK_BUTTON_PRESS:
hegyi@149
   630
	  {
hegyi@149
   631
	    //for determine, whether it was an edge
hegyi@149
   632
	    Edge clicked_edge=INVALID;
hegyi@149
   633
	    //for determine, whether it was a node
hegyi@149
   634
	    Node clicked_node=INVALID;
hegyi@43
   635
hegyi@149
   636
	    window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@149
   637
	    active_item=(get_item_at(clicked_x, clicked_y));
hegyi@48
   638
hegyi@149
   639
	    //find the activated item between text of nodes
hegyi@194
   640
	    for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@149
   641
	      {
hegyi@149
   642
		//at the same time only one can be active
hegyi@149
   643
		if(nodetextmap[i]==active_item)
hegyi@149
   644
		  {
hegyi@149
   645
		    clicked_node=i;
hegyi@149
   646
		  }
hegyi@149
   647
	      }
ladanyi@65
   648
hegyi@149
   649
	    //if there was not, search for it between nodes
hegyi@149
   650
	    if(clicked_node==INVALID)
hegyi@149
   651
	      {
hegyi@194
   652
		for (NodeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@149
   653
		  {
hegyi@149
   654
		    //at the same time only one can be active
hegyi@149
   655
		    if(nodesmap[i]==active_item)
hegyi@149
   656
		      {
hegyi@149
   657
			clicked_node=i;
hegyi@149
   658
		      }
hegyi@149
   659
		  }
hegyi@149
   660
	      }
hegyi@48
   661
hegyi@149
   662
	    if(clicked_node==INVALID)
hegyi@149
   663
	      {
hegyi@149
   664
		//find the activated item between texts
hegyi@194
   665
		for (EdgeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@149
   666
		  {
hegyi@149
   667
		    //at the same time only one can be active
hegyi@149
   668
		    if(edgetextmap[i]==active_item)
hegyi@149
   669
		      {
hegyi@149
   670
			clicked_edge=i;
hegyi@149
   671
		      }
hegyi@149
   672
		  }
hegyi@48
   673
hegyi@149
   674
		//if it was not between texts, search for it between edges
hegyi@149
   675
		if(clicked_edge==INVALID)
hegyi@149
   676
		  {
hegyi@194
   677
		    for (EdgeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
hegyi@149
   678
		      {
hegyi@149
   679
			//at the same time only one can be active
hegyi@149
   680
			if((edgesmap[i]->getLine())==active_item)
hegyi@149
   681
			  {
hegyi@149
   682
			    clicked_edge=i;
hegyi@149
   683
			  }
hegyi@149
   684
		      }
hegyi@149
   685
		  }
hegyi@149
   686
	      }
hegyi@149
   687
hegyi@149
   688
	    //if it was really a node...
hegyi@149
   689
	    if(clicked_node!=INVALID)
hegyi@149
   690
	      {
hegyi@149
   691
		// the id map is not editable
hegyi@149
   692
		if (nodemap_to_edit == "label") return 0;
hegyi@149
   693
hegyi@149
   694
		//and there is activated map
hegyi@149
   695
		if(nodetextmap[clicked_node]->property_text().get_value()!="")
hegyi@149
   696
		  {
hegyi@149
   697
		    //activate the general variable for it
hegyi@149
   698
		    active_node=clicked_node;
hegyi@149
   699
hegyi@149
   700
		    //create a dialog
hegyi@149
   701
		    Gtk::Dialog dialog("Edit value", true);
hegyi@149
   702
		    dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
hegyi@149
   703
		    dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
hegyi@149
   704
		    Gtk::VBox* vbox = dialog.get_vbox();
hegyi@149
   705
		    Gtk::SpinButton spin(0.0, 4);
hegyi@149
   706
		    spin.set_increments(1.0, 10.0);
hegyi@149
   707
		    spin.set_range(-1000000.0, 1000000.0);
hegyi@149
   708
		    spin.set_numeric(true);
hegyi@149
   709
		    spin.set_value(atof(nodetextmap[active_node]->property_text().get_value().c_str()));
hegyi@149
   710
		    vbox->add(spin);
hegyi@149
   711
		    spin.show();
hegyi@149
   712
		    switch (dialog.run())
hegyi@149
   713
		      {
hegyi@149
   714
		      case Gtk::RESPONSE_NONE:
hegyi@149
   715
		      case Gtk::RESPONSE_CANCEL:
hegyi@149
   716
			break;
hegyi@149
   717
		      case Gtk::RESPONSE_ACCEPT:
hegyi@149
   718
			double new_value = spin.get_value();
hegyi@194
   719
			(*(mytab.mapstorage)->nodemap_storage[nodemap_to_edit])[active_node] =
hegyi@149
   720
			  new_value;
hegyi@149
   721
			std::ostringstream ostr;
hegyi@149
   722
			ostr << new_value;
hegyi@149
   723
			nodetextmap[active_node]->property_text().set_value(ostr.str());
hegyi@149
   724
			//mapwin.updateNode(active_node);
hegyi@149
   725
			//mapwin.updateNode(Node(INVALID));
hegyi@149
   726
			propertyUpdate(Node(INVALID));
hegyi@149
   727
		      }
hegyi@149
   728
		  }
hegyi@149
   729
	      }
hegyi@149
   730
	    else
hegyi@149
   731
	      //if it was really an edge...
hegyi@149
   732
	      if(clicked_edge!=INVALID)
hegyi@149
   733
		{
hegyi@149
   734
		  // the id map is not editable
hegyi@149
   735
		  if (edgemap_to_edit == "label") return 0;
hegyi@149
   736
hegyi@149
   737
		  //and there is activated map
hegyi@149
   738
		  if(edgetextmap[clicked_edge]->property_text().get_value()!="")
hegyi@149
   739
		    {
hegyi@149
   740
		      //activate the general variable for it
hegyi@149
   741
		      active_edge=clicked_edge;
hegyi@149
   742
hegyi@149
   743
		      //create a dialog
hegyi@149
   744
		      Gtk::Dialog dialog("Edit value", true);
hegyi@149
   745
		      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
hegyi@149
   746
		      dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
hegyi@149
   747
		      Gtk::VBox* vbox = dialog.get_vbox();
hegyi@149
   748
		      Gtk::SpinButton spin(0.0, 4);
hegyi@149
   749
		      spin.set_increments(1.0, 10.0);
hegyi@149
   750
		      spin.set_range(-1000000.0, 1000000.0);
hegyi@149
   751
		      spin.set_numeric(true);
hegyi@149
   752
		      spin.set_value(atof(edgetextmap[active_edge]->property_text().get_value().c_str()));
hegyi@149
   753
		      vbox->add(spin);
hegyi@149
   754
		      spin.show();
hegyi@149
   755
		      switch (dialog.run())
hegyi@149
   756
			{
hegyi@149
   757
			case Gtk::RESPONSE_NONE:
hegyi@149
   758
			case Gtk::RESPONSE_CANCEL:
hegyi@149
   759
			  break;
hegyi@149
   760
			case Gtk::RESPONSE_ACCEPT:
hegyi@149
   761
			  double new_value = spin.get_value();
hegyi@194
   762
			  (*(mytab.mapstorage)->edgemap_storage[edgemap_to_edit])[active_edge] =
hegyi@149
   763
			    new_value;
hegyi@149
   764
			  std::ostringstream ostr;
hegyi@149
   765
			  ostr << new_value;
hegyi@149
   766
			  edgetextmap[active_edge]->property_text().set_value(
hegyi@149
   767
									      ostr.str());
hegyi@149
   768
			  //mapwin.updateEdge(active_edge);
hegyi@149
   769
			  //                   mapwin.updateEdge(Edge(INVALID));
hegyi@149
   770
			  propertyUpdate(Edge(INVALID));
hegyi@149
   771
			}
hegyi@149
   772
		    }
hegyi@149
   773
		}
hegyi@149
   774
	    break;
hegyi@149
   775
	  }
hegyi@149
   776
	default:
hegyi@149
   777
	  break;
hegyi@149
   778
	}
hegyi@32
   779
    }
hegyi@35
   780
  return false;  
hegyi@32
   781
}
hegyi@32
   782
alpar@62
   783
void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
hegyi@27
   784
{
hegyi@28
   785
  delete(nodetextmap[node_to_delete]);
hegyi@27
   786
  delete(nodesmap[node_to_delete]);
hegyi@194
   787
  (mytab.mapstorage)->graph.erase(node_to_delete);
hegyi@27
   788
}
hegyi@27
   789
alpar@62
   790
void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
hegyi@27
   791
{
hegyi@28
   792
  delete(edgetextmap[edge_to_delete]);
hegyi@27
   793
  delete(edgesmap[edge_to_delete]);
hegyi@194
   794
  (mytab.mapstorage)->graph.erase(edge_to_delete);
hegyi@27
   795
}
hegyi@27
   796
hegyi@150
   797
void GraphDisplayerCanvas::textReposition(XY new_place)
hegyi@27
   798
{
hegyi@150
   799
  new_place+=(XY(10,10));
hegyi@35
   800
  edgetextmap[forming_edge]->property_x().set_value(new_place.x);
hegyi@35
   801
  edgetextmap[forming_edge]->property_y().set_value(new_place.y);
hegyi@27
   802
}
hegyi@27
   803
ladanyi@147
   804
void GraphDisplayerCanvas::toggleEdgeActivity(EdgeBase* active_bre, bool on)
hegyi@27
   805
{
hegyi@27
   806
  if(on)
ladanyi@147
   807
  {
ladanyi@147
   808
    if(forming_edge!=INVALID)
hegyi@27
   809
    {
ladanyi@147
   810
      std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
hegyi@27
   811
    }
ladanyi@147
   812
    else
ladanyi@147
   813
    {
hegyi@194
   814
      for (EdgeIt i((mytab.mapstorage)->graph); i!=INVALID; ++i)
ladanyi@147
   815
      {
ladanyi@147
   816
        if(edgesmap[i]==active_bre)
ladanyi@147
   817
        {
ladanyi@147
   818
          forming_edge=i;
ladanyi@147
   819
        }
ladanyi@147
   820
      }
ladanyi@147
   821
    }
ladanyi@147
   822
  }
hegyi@27
   823
  else
hegyi@27
   824
    {
hegyi@160
   825
      if(forming_edge!=INVALID)
hegyi@160
   826
	{
hegyi@160
   827
	  forming_edge=INVALID;
hegyi@160
   828
	}
hegyi@160
   829
      else
hegyi@160
   830
	{
hegyi@160
   831
	  std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
hegyi@160
   832
	}
hegyi@27
   833
    }
hegyi@160
   834
}
hegyi@160
   835
hegyi@160
   836
void GraphDisplayerCanvas::moveNode(double dx, double dy, Gnome::Canvas::Item * item, Node node)
hegyi@160
   837
{
hegyi@160
   838
  Gnome::Canvas::Item * moved_item=item;
hegyi@160
   839
  Node moved_node=node;
hegyi@160
   840
hegyi@160
   841
  if(item==NULL && node==INVALID)
ladanyi@147
   842
    {
hegyi@160
   843
      moved_item=active_item;
hegyi@160
   844
      moved_node=active_node;
ladanyi@147
   845
    }
hegyi@160
   846
  else
hegyi@160
   847
    {
hegyi@160
   848
      isbutton=1;
hegyi@160
   849
    }
hegyi@160
   850
hegyi@160
   851
  //repositioning node and its text
hegyi@160
   852
  moved_item->move(dx, dy);
hegyi@160
   853
  nodetextmap[moved_node]->move(dx, dy);
hegyi@160
   854
hegyi@160
   855
  // the new coordinates of the centre of the node 
hegyi@194
   856
  double coord_x = dx + (mytab.mapstorage)->coords[moved_node].x;
hegyi@194
   857
  double coord_y = dy + (mytab.mapstorage)->coords[moved_node].y;
hegyi@160
   858
hegyi@160
   859
  // write back the new coordinates to the coords map
hegyi@194
   860
  (mytab.mapstorage)->coords.set(moved_node, XY(coord_x, coord_y));
hegyi@160
   861
hegyi@160
   862
  //all the edges connected to the moved point has to be redrawn
hegyi@194
   863
  for(OutEdgeIt ei((mytab.mapstorage)->graph,moved_node);ei!=INVALID;++ei)
hegyi@160
   864
    {
hegyi@160
   865
      XY arrow_pos;
hegyi@160
   866
hegyi@194
   867
      if (mytab.mapstorage->graph.source(ei) == mytab.mapstorage->graph.target(ei))
hegyi@160
   868
	{
hegyi@194
   869
	  arrow_pos = mytab.mapstorage->arrow_pos[ei] + XY(dx, dy);
hegyi@160
   870
	}
hegyi@160
   871
      else
hegyi@160
   872
	{
hegyi@160
   873
	  XY moved_node_1(coord_x - dx, coord_y - dy);
hegyi@160
   874
	  XY moved_node_2(coord_x, coord_y);
hegyi@194
   875
	  Node target = mytab.mapstorage->graph.target(ei);
hegyi@194
   876
	  XY fix_node(mytab.mapstorage->coords[target].x,
hegyi@194
   877
		      mytab.mapstorage->coords[target].y);
hegyi@194
   878
	  XY old_arrow_pos(mytab.mapstorage->arrow_pos[ei]);
hegyi@160
   879
hegyi@160
   880
	  arrow_pos = calcArrowPos(moved_node_1, moved_node_2, fix_node, old_arrow_pos, isbutton);
hegyi@160
   881
	}
hegyi@160
   882
hegyi@194
   883
      mytab.mapstorage->arrow_pos.set(ei, arrow_pos);
hegyi@160
   884
      edgesmap[ei]->draw();
hegyi@160
   885
hegyi@160
   886
      //reposition of edgetext
hegyi@194
   887
      XY text_pos=mytab.mapstorage->arrow_pos[ei];
hegyi@160
   888
      text_pos+=(XY(10,10));
hegyi@160
   889
      edgetextmap[ei]->property_x().set_value(text_pos.x);
hegyi@160
   890
      edgetextmap[ei]->property_y().set_value(text_pos.y);
hegyi@160
   891
    }
hegyi@160
   892
hegyi@194
   893
  for(InEdgeIt ei((mytab.mapstorage)->graph,moved_node);ei!=INVALID;++ei)
hegyi@160
   894
    {
hegyi@194
   895
      if (mytab.mapstorage->graph.source(ei) != mytab.mapstorage->graph.target(ei))
hegyi@160
   896
	{
hegyi@160
   897
	  XY moved_node_1(coord_x - dx, coord_y - dy);
hegyi@160
   898
	  XY moved_node_2(coord_x, coord_y);
hegyi@194
   899
	  Node source = mytab.mapstorage->graph.source(ei);
hegyi@194
   900
	  XY fix_node(mytab.mapstorage->coords[source].x,
hegyi@194
   901
		      mytab.mapstorage->coords[source].y);
hegyi@194
   902
	  XY old_arrow_pos(mytab.mapstorage->arrow_pos[ei]);
hegyi@160
   903
hegyi@160
   904
	  XY arrow_pos;
hegyi@160
   905
	  arrow_pos = calcArrowPos(moved_node_1, moved_node_2, fix_node, old_arrow_pos, isbutton);
hegyi@160
   906
hegyi@194
   907
	  mytab.mapstorage->arrow_pos.set(ei, arrow_pos);
hegyi@160
   908
	  edgesmap[ei]->draw();
hegyi@160
   909
hegyi@160
   910
	  //reposition of edgetext
hegyi@194
   911
	  XY text_pos=mytab.mapstorage->arrow_pos[ei];
hegyi@160
   912
	  text_pos+=(XY(10,10));
hegyi@160
   913
	  edgetextmap[ei]->property_x().set_value(text_pos.x);
hegyi@160
   914
	  edgetextmap[ei]->property_y().set_value(text_pos.y);
hegyi@160
   915
	}
hegyi@160
   916
    }
hegyi@27
   917
}
hegyi@179
   918
hegyi@179
   919
Gdk::Color GraphDisplayerCanvas::rainbowColorCounter(double min, double max, double w)
hegyi@179
   920
{
hegyi@179
   921
  Gdk::Color color;
hegyi@179
   922
hegyi@179
   923
  double pos=(w-min)/(max-min);
hegyi@179
   924
  int phase=0;
hegyi@179
   925
hegyi@179
   926
  //rainbow transitions contain 6 phase
hegyi@179
   927
  //in each phase only one color is changed
hegyi@179
   928
  //first we determine the phase, in which
hegyi@179
   929
  //the actual value belongs to
hegyi@179
   930
  for (int i=0;i<=5;i++)
hegyi@179
   931
    {
hegyi@179
   932
      if(((double)i/6<pos)&&(pos<=(double(i+1)/6)))
hegyi@179
   933
	{
hegyi@179
   934
	  phase=i;
hegyi@179
   935
	}
hegyi@179
   936
    }
hegyi@179
   937
  if(phase<6)
hegyi@179
   938
    {
hegyi@179
   939
      //within its 1/6 long phase the relativ position
hegyi@179
   940
      //determines the power of the color changed in
hegyi@179
   941
      //that phase
hegyi@179
   942
      //we normalize that to one, to be able to give percentage
hegyi@179
   943
      //value for the function
hegyi@179
   944
      double rel_pos=(pos-(phase/6))*6;
hegyi@179
   945
hegyi@179
   946
      switch(phase)
hegyi@179
   947
	{
hegyi@179
   948
	case 0:
hegyi@179
   949
	  color.set_rgb_p (1, 0, 1-rel_pos);
hegyi@179
   950
	  break;
hegyi@179
   951
	case 1:
hegyi@179
   952
	  color.set_rgb_p (1, rel_pos, 0);
hegyi@179
   953
	  break;
hegyi@179
   954
	case 2:
hegyi@179
   955
	  color.set_rgb_p (1-rel_pos, 1, 0);
hegyi@179
   956
	  break;
hegyi@179
   957
	case 3:
hegyi@179
   958
	  color.set_rgb_p (0, 1, rel_pos);
hegyi@179
   959
	  break;
hegyi@179
   960
	case 4:
hegyi@179
   961
	  color.set_rgb_p (0, 1-rel_pos, 1);
hegyi@179
   962
	  break;
hegyi@179
   963
	case 5:
hegyi@179
   964
	  color.set_rgb_p ((rel_pos/3), 0, 1);
hegyi@179
   965
	  break;
hegyi@179
   966
	default:
hegyi@179
   967
	  std::cout << "Wrong phase: " << phase << " " << pos << std::endl;
hegyi@179
   968
	}
hegyi@179
   969
    }
hegyi@179
   970
  else
hegyi@179
   971
    {
hegyi@179
   972
      std::cout << "Wrong phase: " << phase << " " << pos << std::endl;
hegyi@179
   973
    }
hegyi@179
   974
  return color;
hegyi@179
   975
}