graph_displayer_canvas-event.cc
author hegyi
Mon, 18 Sep 2006 16:02:20 +0000
changeset 148 5adf29662354
parent 147 10ef59f6633c
child 149 930e838ad5b6
permissions -rwxr-xr-x
When moving nodes with midbutton little red arrows keep their position.
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@34
    30
	case EDGE_MAP_EDIT:
hegyi@35
    31
	  //has to do the same thing as in the case of NODE_MAP_EDIT
hegyi@35
    32
	case NODE_MAP_EDIT:
hegyi@35
    33
	  {
hegyi@35
    34
	    break;
hegyi@35
    35
	  }
hegyi@34
    36
	default:
hegyi@34
    37
	  break;
hegyi@34
    38
	}
hegyi@27
    39
hegyi@34
    40
      active_item=NULL; 
hegyi@34
    41
      target_item=NULL; 
hegyi@34
    42
      active_edge=INVALID;	
hegyi@34
    43
      active_node=INVALID;	
hegyi@33
    44
hegyi@27
    45
hegyi@34
    46
      actual_tool=newtool;
hegyi@34
    47
  
hegyi@34
    48
      switch(newtool)
hegyi@34
    49
	{
hegyi@34
    50
	case MOVE:
hegyi@34
    51
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
hegyi@34
    52
	  break;
hegyi@27
    53
hegyi@34
    54
	case CREATE_NODE:
hegyi@34
    55
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
hegyi@34
    56
	  break;
hegyi@27
    57
hegyi@34
    58
	case CREATE_EDGE:
hegyi@34
    59
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
hegyi@34
    60
	  break;
hegyi@27
    61
hegyi@34
    62
	case ERASER:
hegyi@34
    63
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
hegyi@34
    64
	  break;
hegyi@32
    65
hegyi@34
    66
	case EDGE_MAP_EDIT:
hegyi@34
    67
	  grab_focus();
hegyi@34
    68
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
hegyi@34
    69
	  break;
hegyi@32
    70
hegyi@34
    71
	case NODE_MAP_EDIT:
hegyi@34
    72
	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
hegyi@34
    73
	  break;
hegyi@34
    74
hegyi@34
    75
	default:
hegyi@34
    76
	  break;
hegyi@34
    77
	}
hegyi@27
    78
    }
hegyi@27
    79
}
hegyi@27
    80
hegyi@30
    81
int GraphDisplayerCanvas::getActualTool()
hegyi@27
    82
{
hegyi@27
    83
  return actual_tool;
hegyi@27
    84
}
hegyi@27
    85
hegyi@30
    86
bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
hegyi@27
    87
{
ladanyi@70
    88
  static Gnome::Canvas::Text *coord_text = 0;
hegyi@27
    89
  switch(e->type)
hegyi@27
    90
  {
hegyi@27
    91
    case GDK_BUTTON_PRESS:
hegyi@27
    92
      //we mark the location of the event to be able to calculate parameters of dragging
hegyi@31
    93
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@31
    94
hegyi@31
    95
      active_item=(get_item_at(clicked_x, clicked_y));
hegyi@27
    96
      active_node=INVALID;
hegyi@96
    97
      for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
hegyi@27
    98
	{
hegyi@27
    99
	  if(nodesmap[i]==active_item)
hegyi@27
   100
	    {
hegyi@27
   101
	      active_node=i;
hegyi@27
   102
	    }
hegyi@27
   103
	}
hegyi@148
   104
      isbutton=e->button.button;
hegyi@27
   105
      break;
hegyi@27
   106
    case GDK_BUTTON_RELEASE:
ladanyi@70
   107
      if (coord_text)
ladanyi@70
   108
      {
ladanyi@70
   109
        delete coord_text;
ladanyi@70
   110
        coord_text = 0;
ladanyi@70
   111
      }
hegyi@27
   112
      isbutton=0;
hegyi@27
   113
      active_item=NULL;
hegyi@27
   114
      active_node=INVALID;
hegyi@27
   115
      break;
hegyi@27
   116
    case GDK_MOTION_NOTIFY:
hegyi@27
   117
      //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
   118
      if(active_node!=INVALID)
hegyi@27
   119
      {
hegyi@96
   120
        (mytab.mapstorage).modified = true;
ladanyi@70
   121
hegyi@27
   122
	//new coordinates will be the old values,
hegyi@27
   123
	//because the item will be moved to the
hegyi@27
   124
	//new coordinate therefore the new movement
hegyi@27
   125
	//has to be calculated from here
hegyi@27
   126
hegyi@31
   127
	double new_x, new_y;
hegyi@31
   128
hegyi@31
   129
	window_to_world (e->motion.x, e->motion.y, new_x, new_y);
hegyi@31
   130
hegyi@31
   131
        double dx=new_x-clicked_x;
hegyi@31
   132
        double dy=new_y-clicked_y;
hegyi@27
   133
hegyi@28
   134
	//repositioning node and its text
hegyi@27
   135
        active_item->move(dx, dy);
hegyi@28
   136
	nodetextmap[active_node]->move(dx, dy);
hegyi@27
   137
ladanyi@70
   138
        // the new coordinates of the centre of the node 
hegyi@96
   139
        double coord_x = new_x - (clicked_x - (mytab.mapstorage).coords[active_node].x);
hegyi@96
   140
        double coord_y = new_y - (clicked_y - (mytab.mapstorage).coords[active_node].y);
ladanyi@70
   141
ladanyi@98
   142
        // write back the new coordinates to the coords map
ladanyi@98
   143
        (mytab.mapstorage).coords.set(active_node, xy<double>(coord_x, coord_y));
ladanyi@98
   144
hegyi@31
   145
        clicked_x=new_x;
hegyi@31
   146
        clicked_y=new_y;
hegyi@27
   147
ladanyi@70
   148
        // reposition the coordinates text
ladanyi@70
   149
        std::ostringstream ostr;
ladanyi@70
   150
        ostr << "(" <<
hegyi@96
   151
          (mytab.mapstorage).coords[active_node].x << ", " <<
hegyi@96
   152
          (mytab.mapstorage).coords[active_node].y << ")";
ladanyi@72
   153
        double radius =
ladanyi@72
   154
          (nodesmap[active_node]->property_x2().get_value() -
ladanyi@72
   155
          nodesmap[active_node]->property_x1().get_value()) / 2.0;
ladanyi@70
   156
        if (coord_text)
ladanyi@70
   157
        {
ladanyi@70
   158
          coord_text->property_text().set_value(ostr.str());
hegyi@96
   159
          coord_text->property_x().set_value((mytab.mapstorage).coords[active_node].x +
ladanyi@72
   160
              radius);
hegyi@96
   161
          coord_text->property_y().set_value((mytab.mapstorage).coords[active_node].y -
ladanyi@72
   162
              radius);
ladanyi@70
   163
        }
ladanyi@70
   164
        else
ladanyi@70
   165
        {
ladanyi@70
   166
          coord_text = new Gnome::Canvas::Text(
ladanyi@70
   167
              displayed_graph,
hegyi@96
   168
              (mytab.mapstorage).coords[active_node].x + radius,
hegyi@96
   169
              (mytab.mapstorage).coords[active_node].y - radius,
ladanyi@70
   170
              ostr.str());
ladanyi@70
   171
          coord_text->property_fill_color().set_value("black");
ladanyi@72
   172
          coord_text->property_anchor().set_value(Gtk::ANCHOR_SOUTH_WEST);
ladanyi@70
   173
        }
ladanyi@70
   174
ladanyi@70
   175
	//all the edges connected to the moved point has to be redrawn
hegyi@96
   176
        for(OutEdgeIt ei((mytab.mapstorage).graph,active_node);ei!=INVALID;++ei)
hegyi@27
   177
        {
ladanyi@98
   178
            XY moved_node_1(coord_x - dx, coord_y - dy);
ladanyi@98
   179
            XY moved_node_2(coord_x, coord_y);
ladanyi@98
   180
            Node target = mytab.mapstorage.graph.target(ei);
ladanyi@98
   181
            XY fix_node(mytab.mapstorage.coords[target].x,
ladanyi@98
   182
                        mytab.mapstorage.coords[target].y);
ladanyi@98
   183
            XY old_arrow_pos(mytab.mapstorage.arrow_pos[ei]);
hegyi@27
   184
ladanyi@98
   185
            XY arrow_pos;
hegyi@148
   186
	    arrow_pos = calcArrowPos(moved_node_1, moved_node_2, fix_node, old_arrow_pos, isbutton);
hegyi@27
   187
ladanyi@98
   188
            mytab.mapstorage.arrow_pos.set(ei, arrow_pos);
ladanyi@98
   189
            edgesmap[ei]->draw();
hegyi@27
   190
hegyi@28
   191
	    //reposition of edgetext
ladanyi@98
   192
	    XY text_pos=mytab.mapstorage.arrow_pos[ei];
ladanyi@98
   193
	    text_pos+=(XY(10,10));
hegyi@27
   194
	    edgetextmap[ei]->property_x().set_value(text_pos.x);
hegyi@27
   195
	    edgetextmap[ei]->property_y().set_value(text_pos.y);
hegyi@27
   196
        }
hegyi@27
   197
hegyi@96
   198
        for(InEdgeIt ei((mytab.mapstorage).graph,active_node);ei!=INVALID;++ei)
hegyi@27
   199
        {
ladanyi@98
   200
            XY moved_node_1(coord_x - dx, coord_y - dy);
ladanyi@98
   201
            XY moved_node_2(coord_x, coord_y);
ladanyi@98
   202
            Node source = mytab.mapstorage.graph.source(ei);
ladanyi@98
   203
            XY fix_node(mytab.mapstorage.coords[source].x,
ladanyi@98
   204
                        mytab.mapstorage.coords[source].y);
ladanyi@98
   205
            XY old_arrow_pos(mytab.mapstorage.arrow_pos[ei]);
hegyi@27
   206
ladanyi@98
   207
            XY arrow_pos;
hegyi@148
   208
	    arrow_pos = calcArrowPos(moved_node_1, moved_node_2, fix_node, old_arrow_pos, isbutton);
hegyi@27
   209
ladanyi@98
   210
            mytab.mapstorage.arrow_pos.set(ei, arrow_pos);
ladanyi@98
   211
            edgesmap[ei]->draw();
hegyi@27
   212
ladanyi@98
   213
	    //reposition of edgetext
ladanyi@98
   214
	    XY text_pos=mytab.mapstorage.arrow_pos[ei];
ladanyi@98
   215
	    text_pos+=(XY(10,10));
hegyi@27
   216
	    edgetextmap[ei]->property_x().set_value(text_pos.x);
hegyi@27
   217
	    edgetextmap[ei]->property_y().set_value(text_pos.y);
hegyi@27
   218
        }
hegyi@27
   219
      }
hegyi@27
   220
    default: break;
hegyi@27
   221
  }
hegyi@27
   222
hegyi@31
   223
  return false;
hegyi@27
   224
}
hegyi@27
   225
hegyi@148
   226
XY GraphDisplayerCanvas::calcArrowPos(XY moved_node_1, XY moved_node_2, XY fix_node, XY old_arrow_pos, int move_code)
ladanyi@98
   227
{
hegyi@148
   228
  switch(move_code)
hegyi@148
   229
    {
hegyi@148
   230
    case 1:
hegyi@148
   231
      return XY((moved_node_2.x + fix_node.x) / 2.0, (moved_node_2.y + fix_node.y) / 2.0);
hegyi@148
   232
      break;
hegyi@148
   233
    case 2:
hegyi@148
   234
      return old_arrow_pos;
hegyi@148
   235
      break;
hegyi@148
   236
    case 3:
hegyi@148
   237
      {
hegyi@148
   238
	//////////////////////////////////////////////////////////////////////////////////////////////////////
hegyi@148
   239
	/////////// keeps shape-with scalar multiplication - version 2.
hegyi@148
   240
	//////////////////////////////////////////////////////////////////////////////////////////////////////
ladanyi@98
   241
hegyi@148
   242
	//old vector from one to the other node - a
hegyi@148
   243
	xy<double> a_v(moved_node_1.x-fix_node.x,moved_node_1.y-fix_node.y);
hegyi@148
   244
	//new vector from one to the other node - b
hegyi@148
   245
	xy<double> b_v(moved_node_2.x-fix_node.x,moved_node_2.y-fix_node.y);
ladanyi@98
   246
hegyi@148
   247
	double absa=sqrt(a_v.normSquare());
hegyi@148
   248
	double absb=sqrt(b_v.normSquare());
ladanyi@98
   249
hegyi@148
   250
	if ((absa == 0.0) || (absb == 0.0))
hegyi@148
   251
	  {
hegyi@148
   252
	    return old_arrow_pos;
hegyi@148
   253
	  }
hegyi@148
   254
	else
hegyi@148
   255
	  {
hegyi@148
   256
	    //old vector from one node to the breakpoint - c
hegyi@148
   257
	    xy<double> c_v(old_arrow_pos.x-fix_node.x,old_arrow_pos.y-fix_node.y);
hegyi@148
   258
hegyi@148
   259
	    //unit vector with the same direction to a_v
hegyi@148
   260
	    xy<double> a_v_u(a_v.x/absa,a_v.y/absa);
hegyi@148
   261
hegyi@148
   262
	    //normal vector of unit vector with the same direction to a_v
hegyi@148
   263
	    xy<double> a_v_u_n(((-1)*a_v_u.y),a_v_u.x);
hegyi@148
   264
hegyi@148
   265
	    //unit vector with the same direction to b_v
hegyi@148
   266
	    xy<double> b_v_u(b_v.x/absb,b_v.y/absb);
hegyi@148
   267
hegyi@148
   268
	    //normal vector of unit vector with the same direction to b_v
hegyi@148
   269
	    xy<double> b_v_u_n(((-1)*b_v_u.y),b_v_u.x);
hegyi@148
   270
hegyi@148
   271
	    //vector c in a_v_u and a_v_u_n co-ordinate system
hegyi@148
   272
	    xy<double> c_a(c_v*a_v_u,c_v*a_v_u_n);
hegyi@148
   273
hegyi@148
   274
	    //new vector from one node to the breakpoint - d - we have to calculate this one
hegyi@148
   275
	    xy<double> d_v=absb/absa*(c_a.x*b_v_u+c_a.y*b_v_u_n);
hegyi@148
   276
hegyi@148
   277
	    return XY(d_v.x+fix_node.x,d_v.y+fix_node.y);
hegyi@148
   278
	  }
hegyi@148
   279
	break;
hegyi@148
   280
      }
hegyi@148
   281
    default:
hegyi@148
   282
      break;
ladanyi@98
   283
    }
hegyi@148
   284
}
ladanyi@98
   285
ladanyi@98
   286
hegyi@30
   287
bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
hegyi@27
   288
{
hegyi@27
   289
  switch(e->type)
ladanyi@63
   290
  {
ladanyi@63
   291
    //move the new node
ladanyi@63
   292
    case GDK_MOTION_NOTIFY:
ladanyi@63
   293
      {
ladanyi@63
   294
        GdkEvent * generated=new GdkEvent();
ladanyi@63
   295
        generated->motion.x=e->motion.x;
ladanyi@63
   296
        generated->motion.y=e->motion.y;
ladanyi@63
   297
        generated->type=GDK_MOTION_NOTIFY;
ladanyi@63
   298
        moveEventHandler(generated);      
ladanyi@63
   299
        break;
ladanyi@63
   300
      }
hegyi@27
   301
ladanyi@63
   302
    case GDK_BUTTON_RELEASE:
hegyi@96
   303
      (mytab.mapstorage).modified = true;
ladanyi@53
   304
hegyi@27
   305
      isbutton=1;
hegyi@27
   306
hegyi@96
   307
      active_node=(mytab.mapstorage).graph.addNode();
hegyi@27
   308
hegyi@27
   309
      //initiating values corresponding to new node in maps
hegyi@27
   310
hegyi@27
   311
      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@27
   312
ladanyi@63
   313
      // update coordinates
hegyi@96
   314
      (mytab.mapstorage).coords.set(active_node, xy<double>(clicked_x, clicked_y));
ladanyi@63
   315
ladanyi@63
   316
      // update all other maps
ladanyi@63
   317
      for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
hegyi@96
   318
          (mytab.mapstorage).nodemap_storage.begin(); it !=
hegyi@96
   319
          (mytab.mapstorage).nodemap_storage.end(); ++it)
ladanyi@63
   320
      {
ladanyi@64
   321
        if ((it->first != "coordinates_x") &&
ladanyi@64
   322
            (it->first != "coordinates_y"))
ladanyi@63
   323
        {
ladanyi@63
   324
          (*(it->second))[active_node] =
hegyi@96
   325
            (mytab.mapstorage).nodemap_default[it->first];
ladanyi@63
   326
        }
ladanyi@63
   327
      }
ladanyi@64
   328
      // increment the id map's default value
ladanyi@134
   329
      (mytab.mapstorage).nodemap_default["label"] += 1.0;
ladanyi@63
   330
ladanyi@53
   331
      nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph,
ladanyi@63
   332
          clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
hegyi@27
   333
      active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
ladanyi@63
   334
      *(nodesmap[active_node]) <<
ladanyi@63
   335
        Gnome::Canvas::Properties::fill_color("blue");
ladanyi@63
   336
      *(nodesmap[active_node]) <<
ladanyi@63
   337
        Gnome::Canvas::Properties::outline_color("black");
ladanyi@63
   338
      active_item->raise_to_top();
ladanyi@63
   339
hegyi@27
   340
      (nodesmap[active_node])->show();
hegyi@28
   341
ladanyi@53
   342
      nodetextmap[active_node]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@63
   343
          clicked_x+node_property_defaults[N_RADIUS]+5,
ladanyi@63
   344
          clicked_y+node_property_defaults[N_RADIUS]+5, "");
hegyi@28
   345
      nodetextmap[active_node]->property_fill_color().set_value("darkblue");
ladanyi@63
   346
      nodetextmap[active_node]->raise_to_top();
hegyi@28
   347
hegyi@94
   348
//       mapwin.updateNode(active_node);
hegyi@94
   349
      propertyUpdate(active_node);
hegyi@28
   350
hegyi@27
   351
      isbutton=0;
hegyi@31
   352
      target_item=NULL;
hegyi@27
   353
      active_item=NULL;
hegyi@27
   354
      active_node=INVALID;
hegyi@27
   355
      break;
hegyi@27
   356
    default:
hegyi@27
   357
      break;
ladanyi@63
   358
  }
hegyi@27
   359
  return false;
hegyi@27
   360
}
hegyi@27
   361
hegyi@30
   362
bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
hegyi@27
   363
{
hegyi@27
   364
  switch(e->type)
ladanyi@63
   365
  {
hegyi@27
   366
    case GDK_BUTTON_PRESS:
hegyi@27
   367
      //in edge creation right button has special meaning
hegyi@27
   368
      if(e->button.button!=3)
ladanyi@63
   369
      {
ladanyi@63
   370
        //there is not yet selected node
ladanyi@63
   371
        if(active_node==INVALID)
ladanyi@63
   372
        {
ladanyi@63
   373
          //we mark the location of the event to be able to calculate parameters of dragging
hegyi@31
   374
ladanyi@63
   375
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
hegyi@31
   376
ladanyi@63
   377
          active_item=(get_item_at(clicked_x, clicked_y));
ladanyi@63
   378
          active_node=INVALID;
hegyi@96
   379
          for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@63
   380
          {
ladanyi@63
   381
            if(nodesmap[i]==active_item)
ladanyi@63
   382
            {
ladanyi@63
   383
              active_node=i;
ladanyi@63
   384
            }
ladanyi@63
   385
          }
ladanyi@63
   386
          //the clicked item is really a node
ladanyi@63
   387
          if(active_node!=INVALID)
ladanyi@63
   388
          {
ladanyi@63
   389
            *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
ladanyi@63
   390
            isbutton=1;
ladanyi@63
   391
          }
ladanyi@63
   392
          //clicked item was not a node. It could be e.g. edge.
ladanyi@63
   393
          else
ladanyi@63
   394
          {
ladanyi@63
   395
            active_item=NULL;
ladanyi@63
   396
          }
ladanyi@63
   397
        }
ladanyi@63
   398
        //we only have to do sg. if the mouse button
ladanyi@63
   399
        // is pressed already once AND the click was
ladanyi@63
   400
        // on a node that was found in the set of 
ladanyi@63
   401
        //nodes, and now we only search for the second 
ladanyi@63
   402
        //node
ladanyi@63
   403
        else
ladanyi@63
   404
        {
ladanyi@63
   405
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
ladanyi@63
   406
          target_item=(get_item_at(clicked_x, clicked_y));
ladanyi@63
   407
          Node target_node=INVALID;
hegyi@96
   408
          for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@63
   409
          {
ladanyi@63
   410
            if(nodesmap[i]==target_item)
ladanyi@63
   411
            {
ladanyi@63
   412
              target_node=i;
ladanyi@63
   413
            }
ladanyi@63
   414
          }
ladanyi@63
   415
          //the clicked item is a node, the edge can be drawn
ladanyi@63
   416
          if(target_node!=INVALID)
ladanyi@63
   417
          {
ladanyi@63
   418
            if(target_node!=active_node)		
ladanyi@63
   419
            {
hegyi@96
   420
              (mytab.mapstorage).modified = true;
ladanyi@53
   421
ladanyi@63
   422
              *(nodesmap[target_node]) <<
ladanyi@63
   423
                Gnome::Canvas::Properties::fill_color("red");
hegyi@27
   424
ladanyi@63
   425
              //creating new edge
hegyi@96
   426
              active_edge=(mytab.mapstorage).graph.addEdge(active_node,
ladanyi@63
   427
                  target_node);
hegyi@27
   428
ladanyi@64
   429
              // update maps
ladanyi@63
   430
              for (std::map<std::string,
ladanyi@63
   431
                  Graph::EdgeMap<double>*>::const_iterator it =
hegyi@96
   432
                  (mytab.mapstorage).edgemap_storage.begin(); it !=
hegyi@96
   433
                  (mytab.mapstorage).edgemap_storage.end(); ++it)
ladanyi@63
   434
              {
ladanyi@64
   435
                (*(it->second))[active_edge] =
hegyi@96
   436
                  (mytab.mapstorage).edgemap_default[it->first];
ladanyi@63
   437
              }
ladanyi@64
   438
              // increment the id map's default value
ladanyi@134
   439
              (mytab.mapstorage).edgemap_default["label"] += 1.0;
hegyi@27
   440
ladanyi@63
   441
              //calculating coordinates of new edge
ladanyi@63
   442
              Gnome::Canvas::Points coos;
ladanyi@63
   443
              double x1, x2, y1, y2;
hegyi@27
   444
ladanyi@63
   445
              active_item->get_bounds(x1, y1, x2, y2);
ladanyi@63
   446
              coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
hegyi@27
   447
ladanyi@63
   448
              target_item->get_bounds(x1, y1, x2, y2);
ladanyi@63
   449
              coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
hegyi@27
   450
ladanyi@113
   451
              // set the coordinates of the arrow on the new edge
ladanyi@113
   452
              MapStorage& ms = mytab.mapstorage;
ladanyi@113
   453
              ms.arrow_pos.set(active_edge,
ladanyi@113
   454
                  (ms.coords[ms.graph.source(active_edge)] +
ladanyi@113
   455
                   ms.coords[ms.graph.target(active_edge)])/ 2.0);
ladanyi@113
   456
ladanyi@63
   457
              //drawing new edge
ladanyi@98
   458
              edgesmap[active_edge]=new BrokenEdge(displayed_graph, active_edge,
ladanyi@63
   459
                  *this);
hegyi@28
   460
ladanyi@63
   461
              //initializing edge-text as well, to empty string
ladanyi@98
   462
              XY text_pos=mytab.mapstorage.arrow_pos[active_edge];
ladanyi@98
   463
              text_pos+=(XY(10,10));
ladanyi@63
   464
ladanyi@63
   465
              edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
ladanyi@63
   466
                  text_pos.x, text_pos.y, "");
ladanyi@63
   467
              edgetextmap[active_edge]->property_fill_color().set_value(
ladanyi@63
   468
                  "darkgreen");
ladanyi@63
   469
              edgetextmap[active_edge]->raise_to_top();
ladanyi@63
   470
ladanyi@63
   471
              //updating its properties
hegyi@94
   472
//               mapwin.updateEdge(active_edge);
hegyi@94
   473
              propertyUpdate(active_edge);
ladanyi@63
   474
            }
ladanyi@63
   475
            else
ladanyi@63
   476
            {
ladanyi@63
   477
              target_node=INVALID;
ladanyi@63
   478
              std::cerr << "Loop edge is not yet implemented!" << std::endl;
ladanyi@63
   479
            }
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
	    {
hegyi@27
   540
	      if(edgesmap[i]==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@32
   625
bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
hegyi@32
   626
{
hegyi@48
   627
  if(actual_tool==EDGE_MAP_EDIT)
ladanyi@66
   628
  {
ladanyi@66
   629
    switch(e->type)
hegyi@32
   630
    {
ladanyi@66
   631
      case GDK_BUTTON_PRESS:
ladanyi@66
   632
        {
ladanyi@66
   633
          //for determine, whether it was an edge
ladanyi@66
   634
          Edge clicked_edge=INVALID;
hegyi@43
   635
ladanyi@66
   636
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
ladanyi@66
   637
          active_item=(get_item_at(clicked_x, clicked_y));
hegyi@48
   638
ladanyi@66
   639
          //find the activated item between texts
hegyi@96
   640
          for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@66
   641
          {
ladanyi@66
   642
            //at the same time only one can be active
ladanyi@66
   643
            if(edgetextmap[i]==active_item)
ladanyi@66
   644
            {
ladanyi@66
   645
              clicked_edge=i;
ladanyi@66
   646
            }
ladanyi@66
   647
          }
ladanyi@65
   648
ladanyi@66
   649
          //if it was not between texts, search for it between edges
ladanyi@66
   650
          if(clicked_edge==INVALID)
ladanyi@66
   651
          {
hegyi@96
   652
            for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@66
   653
            {
ladanyi@66
   654
              //at the same time only one can be active
ladanyi@66
   655
              if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
ladanyi@66
   656
              {
ladanyi@66
   657
                clicked_edge=i;
ladanyi@66
   658
              }
ladanyi@66
   659
            }
ladanyi@66
   660
          }
ladanyi@66
   661
 
ladanyi@66
   662
          //if it was really an edge...
ladanyi@66
   663
          if(clicked_edge!=INVALID)
ladanyi@66
   664
          {
ladanyi@66
   665
            // the id map is not editable
ladanyi@134
   666
            if (edgemap_to_edit == "label") return 0;
hegyi@48
   667
ladanyi@66
   668
            //and there is activated map
ladanyi@66
   669
            if(edgetextmap[clicked_edge]->property_text().get_value()!="")
ladanyi@66
   670
            {
ladanyi@66
   671
              //activate the general variable for it
ladanyi@66
   672
              active_edge=clicked_edge;
hegyi@48
   673
ladanyi@66
   674
              //create a dialog
hegyi@96
   675
              Gtk::Dialog dialog("Edit value", true);
ladanyi@66
   676
              dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
ladanyi@66
   677
              dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
ladanyi@66
   678
              Gtk::VBox* vbox = dialog.get_vbox();
ladanyi@92
   679
              Gtk::SpinButton spin(0.0, 4);
ladanyi@92
   680
              spin.set_increments(1.0, 10.0);
ladanyi@92
   681
              spin.set_range(-1000000.0, 1000000.0);
ladanyi@66
   682
              spin.set_numeric(true);
ladanyi@66
   683
              vbox->add(spin);
ladanyi@66
   684
              spin.show();
ladanyi@66
   685
              switch (dialog.run())
ladanyi@66
   686
              {
ladanyi@66
   687
                case Gtk::RESPONSE_NONE:
ladanyi@66
   688
                case Gtk::RESPONSE_CANCEL:
ladanyi@66
   689
                  break;
ladanyi@66
   690
                case Gtk::RESPONSE_ACCEPT:
ladanyi@66
   691
                  double new_value = spin.get_value();
hegyi@96
   692
                  (*(mytab.mapstorage).edgemap_storage[edgemap_to_edit])[active_edge] =
ladanyi@66
   693
                    new_value;
ladanyi@66
   694
                  std::ostringstream ostr;
ladanyi@66
   695
                  ostr << new_value;
ladanyi@66
   696
                  edgetextmap[active_edge]->property_text().set_value(
ladanyi@66
   697
                      ostr.str());
ladanyi@66
   698
                  //mapwin.updateEdge(active_edge);
hegyi@94
   699
//                   mapwin.updateEdge(Edge(INVALID));
hegyi@94
   700
                  propertyUpdate(Edge(INVALID));
ladanyi@66
   701
              }
ladanyi@66
   702
            }
ladanyi@66
   703
          }
ladanyi@66
   704
          break;
ladanyi@66
   705
        }
ladanyi@66
   706
      default:
ladanyi@66
   707
        break;
hegyi@32
   708
    }
ladanyi@66
   709
  }
hegyi@32
   710
  return false;  
hegyi@32
   711
}
hegyi@32
   712
hegyi@32
   713
bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
hegyi@32
   714
{
hegyi@48
   715
  if(actual_tool==NODE_MAP_EDIT)
ladanyi@66
   716
  {
ladanyi@66
   717
    switch(e->type)
hegyi@35
   718
    {
ladanyi@66
   719
      case GDK_BUTTON_PRESS:
ladanyi@66
   720
        {
ladanyi@66
   721
          //for determine, whether it was a node
ladanyi@66
   722
          Node clicked_node=INVALID;
hegyi@43
   723
ladanyi@66
   724
          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
ladanyi@66
   725
          active_item=(get_item_at(clicked_x, clicked_y));
hegyi@43
   726
ladanyi@66
   727
          //find the activated item between texts
hegyi@96
   728
          for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@66
   729
          {
ladanyi@66
   730
            //at the same time only one can be active
ladanyi@66
   731
            if(nodetextmap[i]==active_item)
ladanyi@66
   732
            {
ladanyi@66
   733
              clicked_node=i;
ladanyi@66
   734
            }
ladanyi@66
   735
          }
hegyi@48
   736
ladanyi@66
   737
          //if there was not, search for it between nodes
ladanyi@66
   738
          if(clicked_node==INVALID)
ladanyi@66
   739
          {
hegyi@96
   740
            for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@66
   741
            {
ladanyi@66
   742
              //at the same time only one can be active
ladanyi@66
   743
              if(nodesmap[i]==active_item)
ladanyi@66
   744
              {
ladanyi@66
   745
                clicked_node=i;
ladanyi@66
   746
              }
ladanyi@66
   747
            }
ladanyi@66
   748
          }
hegyi@48
   749
ladanyi@66
   750
          //if it was really a node...
ladanyi@66
   751
          if(clicked_node!=INVALID)
ladanyi@66
   752
          {
ladanyi@66
   753
            // the id map is not editable
ladanyi@134
   754
            if (nodemap_to_edit == "label") return 0;
hegyi@48
   755
ladanyi@66
   756
            //and there is activated map
ladanyi@66
   757
            if(nodetextmap[clicked_node]->property_text().get_value()!="")
ladanyi@66
   758
            {
ladanyi@66
   759
              //activate the general variable for it
ladanyi@66
   760
              active_node=clicked_node;
hegyi@48
   761
ladanyi@66
   762
              //create a dialog
hegyi@96
   763
              Gtk::Dialog dialog("Edit value", true);
ladanyi@66
   764
              dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
ladanyi@66
   765
              dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
ladanyi@66
   766
              Gtk::VBox* vbox = dialog.get_vbox();
ladanyi@92
   767
              Gtk::SpinButton spin(0.0, 4);
ladanyi@92
   768
              spin.set_increments(1.0, 10.0);
ladanyi@92
   769
              spin.set_range(-1000000.0, 1000000.0);
ladanyi@66
   770
              spin.set_numeric(true);
ladanyi@66
   771
              vbox->add(spin);
ladanyi@66
   772
              spin.show();
ladanyi@66
   773
              switch (dialog.run())
ladanyi@66
   774
              {
ladanyi@66
   775
                case Gtk::RESPONSE_NONE:
ladanyi@66
   776
                case Gtk::RESPONSE_CANCEL:
ladanyi@66
   777
                  break;
ladanyi@66
   778
                case Gtk::RESPONSE_ACCEPT:
ladanyi@66
   779
                  double new_value = spin.get_value();
hegyi@96
   780
                  (*(mytab.mapstorage).nodemap_storage[nodemap_to_edit])[active_node] =
ladanyi@66
   781
                    new_value;
ladanyi@66
   782
                  std::ostringstream ostr;
ladanyi@66
   783
                  ostr << new_value;
ladanyi@66
   784
                  nodetextmap[active_node]->property_text().set_value(
ladanyi@66
   785
                      ostr.str());
ladanyi@66
   786
                  //mapwin.updateNode(active_node);
hegyi@94
   787
//                   mapwin.updateNode(Node(INVALID));
hegyi@94
   788
                  propertyUpdate(Node(INVALID));
ladanyi@66
   789
              }
ladanyi@66
   790
            }
ladanyi@66
   791
          }
ladanyi@66
   792
          break;
ladanyi@66
   793
        }
ladanyi@66
   794
      default:
ladanyi@66
   795
        break;
hegyi@35
   796
    }
ladanyi@66
   797
  }
hegyi@35
   798
  return false;  
hegyi@32
   799
}
hegyi@32
   800
alpar@62
   801
void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
hegyi@27
   802
{
hegyi@28
   803
  delete(nodetextmap[node_to_delete]);
hegyi@27
   804
  delete(nodesmap[node_to_delete]);
hegyi@96
   805
  (mytab.mapstorage).graph.erase(node_to_delete);
hegyi@27
   806
}
hegyi@27
   807
alpar@62
   808
void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
hegyi@27
   809
{
hegyi@28
   810
  delete(edgetextmap[edge_to_delete]);
hegyi@27
   811
  delete(edgesmap[edge_to_delete]);
hegyi@96
   812
  (mytab.mapstorage).graph.erase(edge_to_delete);
hegyi@27
   813
}
hegyi@27
   814
hegyi@30
   815
void GraphDisplayerCanvas::textReposition(xy<double> new_place)
hegyi@27
   816
{
hegyi@27
   817
  new_place+=(xy<double>(10,10));
hegyi@35
   818
  edgetextmap[forming_edge]->property_x().set_value(new_place.x);
hegyi@35
   819
  edgetextmap[forming_edge]->property_y().set_value(new_place.y);
hegyi@27
   820
}
hegyi@27
   821
ladanyi@147
   822
void GraphDisplayerCanvas::toggleEdgeActivity(EdgeBase* active_bre, bool on)
hegyi@27
   823
{
hegyi@27
   824
  if(on)
ladanyi@147
   825
  {
ladanyi@147
   826
    if(forming_edge!=INVALID)
hegyi@27
   827
    {
ladanyi@147
   828
      std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
hegyi@27
   829
    }
ladanyi@147
   830
    else
ladanyi@147
   831
    {
ladanyi@147
   832
      for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
ladanyi@147
   833
      {
ladanyi@147
   834
        if(edgesmap[i]==active_bre)
ladanyi@147
   835
        {
ladanyi@147
   836
          forming_edge=i;
ladanyi@147
   837
        }
ladanyi@147
   838
      }
ladanyi@147
   839
    }
ladanyi@147
   840
  }
hegyi@27
   841
  else
ladanyi@147
   842
  {
ladanyi@147
   843
    if(forming_edge!=INVALID)
hegyi@27
   844
    {
ladanyi@147
   845
      forming_edge=INVALID;
hegyi@27
   846
    }
ladanyi@147
   847
    else
ladanyi@147
   848
    {
ladanyi@147
   849
      std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
ladanyi@147
   850
    }
ladanyi@147
   851
  }
hegyi@27
   852
}