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