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