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