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