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