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