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