gdc-broken_edge.cc
author ladanyi
Mon, 25 Sep 2006 07:54:00 +0000
changeset 151 72f1c33f89d4
parent 147 10ef59f6633c
child 152 d99e115d0d26
permissions -rw-r--r--
LoopEdge improvements.
     1 #include "graph_displayer_canvas.h"
     2 #include <cmath>
     3 
     4 GraphDisplayerCanvas::EdgeBase::EdgeBase(Gnome::Canvas::Group& _group, Edge _edge, GraphDisplayerCanvas& _canvas) : 
     5   Gnome::Canvas::Group(_group), edge(_edge), canvas(_canvas), arrow(*this)
     6 {
     7   arrow.property_fill_color().set_value("red");
     8   arrow.lower_to_bottom();
     9 }
    10 
    11 GraphDisplayerCanvas::EdgeBase::~EdgeBase()
    12 {
    13 }
    14 
    15 void GraphDisplayerCanvas::EdgeBase::drawArrow(XY unit_vector_in_dir)
    16 {
    17   MapStorage& ms = canvas.mytab.mapstorage;
    18   XY center(ms.arrow_pos[edge]);
    19   XY unit_norm_vector(0-unit_vector_in_dir.y, unit_vector_in_dir.x);
    20 
    21   //       /\       // top
    22   //      /  \      //
    23   //      -  -      // c(enter)l(eft), ccl, ccr, cr
    24   //       ||       //
    25   //       ||       // b(ottom)l, br
    26 
    27   double size=3;
    28 
    29   XY bl (center - unit_vector_in_dir * 3 * size + unit_norm_vector * size );
    30   XY br (center - unit_vector_in_dir * 3 * size - unit_norm_vector * size );
    31   XY ccl(center + unit_vector_in_dir *  size + unit_norm_vector * size );
    32   XY ccr(center + unit_vector_in_dir *  size - unit_norm_vector * size );
    33   XY cl (center + unit_vector_in_dir *  size + unit_norm_vector * 2 * size );
    34   XY cr (center + unit_vector_in_dir *  size - unit_norm_vector * 2 * size );
    35   XY top(center + unit_vector_in_dir * 3 * size);
    36 
    37   Gnome::Canvas::Points arrow_points;
    38   arrow_points.push_back(Gnome::Art::Point( bl.x , bl.y  ) );
    39   arrow_points.push_back(Gnome::Art::Point( br.x , br.y  ) );
    40   arrow_points.push_back(Gnome::Art::Point( ccr.x, ccr.y ) );
    41   arrow_points.push_back(Gnome::Art::Point( cr.x , cr.y  ) );
    42   arrow_points.push_back(Gnome::Art::Point( top.x, top.y ) );
    43   arrow_points.push_back(Gnome::Art::Point( cl.x , cl.y  ) );
    44   arrow_points.push_back(Gnome::Art::Point( ccl.x, ccl.y ) );
    45 
    46   arrow.property_points().set_value(arrow_points);
    47 }
    48 
    49 GraphDisplayerCanvas::BrokenEdge::BrokenEdge(Gnome::Canvas::Group & g,
    50     Edge _edge, GraphDisplayerCanvas & gc) : EdgeBase(g, _edge, gc),
    51   isbutton(false), line(*this)
    52 {
    53   arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler));
    54 
    55   line.property_fill_color().set_value("green");
    56   line.property_width_units().set_value(10);    
    57   line.lower_to_bottom();
    58 
    59   draw();
    60 }
    61 
    62 GraphDisplayerCanvas::BrokenEdge::~BrokenEdge()
    63 {
    64 }
    65 
    66 void GraphDisplayerCanvas::BrokenEdge::draw()
    67 {
    68   MapStorage& ms = canvas.mytab.mapstorage;
    69 
    70   //calculating coordinates of the direction indicator arrow
    71   XY head(ms.coords[ms.graph.target(edge)]);
    72   XY center(ms.arrow_pos[edge]);
    73 
    74   XY unit_vector_in_dir(head-center);
    75   double length=sqrt( unit_vector_in_dir.normSquare() );
    76 
    77   unit_vector_in_dir/=length;
    78 
    79   // update the arrow
    80   drawArrow(unit_vector_in_dir);
    81 
    82   // update the edge
    83   Gnome::Canvas::Points points;
    84   Node source = ms.graph.source(edge);
    85   Node target = ms.graph.target(edge);
    86   points.push_back(Gnome::Art::Point(ms.coords[source].x,
    87         ms.coords[source].y));
    88   points.push_back(Gnome::Art::Point(ms.arrow_pos[edge].x,
    89         ms.arrow_pos[edge].y));
    90   points.push_back(Gnome::Art::Point(ms.coords[target].x,
    91         ms.coords[target].y));
    92   line.property_points().set_value(points);
    93 }
    94 
    95 bool GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler(GdkEvent* e)
    96 {
    97   switch(e->type)
    98   {
    99     case GDK_BUTTON_PRESS:
   100       //we mark the location of the event to be able to calculate parameters
   101       //of dragging
   102       if(canvas.getActualTool()!=CREATE_NODE)
   103       {
   104         canvas.toggleEdgeActivity(this, true);
   105         clicked_x=e->button.x;
   106         clicked_y=e->button.y;
   107         isbutton=true;
   108       }
   109       break;
   110     case GDK_BUTTON_RELEASE:
   111       if(canvas.getActualTool()!=CREATE_NODE)
   112       {
   113         canvas.toggleEdgeActivity(this, false);
   114         isbutton=false;
   115       }
   116       break;
   117     case GDK_MOTION_NOTIFY:
   118       //we only have to do sg. if the mouse button is pressed
   119       if(isbutton)
   120       {
   121         //new coordinates will be the old values,
   122         //because the item will be moved to the
   123         //new coordinate therefore the new movement
   124         //has to be calculated from here
   125 
   126         double dx=e->motion.x-clicked_x;
   127         double dy=e->motion.y-clicked_y;
   128 
   129         Gnome::Canvas::Points points_new;
   130 
   131         canvas.mytab.mapstorage.arrow_pos.set(edge, canvas.mytab.mapstorage.arrow_pos[edge] + XY(dx, dy));
   132 
   133         draw();
   134         canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
   135 
   136         clicked_x=e->motion.x;
   137         clicked_y=e->motion.y;
   138 
   139       }
   140     default: break;
   141   }
   142 
   143   return true;
   144 }
   145 
   146 void GraphDisplayerCanvas::BrokenEdge::setLineWidth(int w)
   147 {
   148   line.property_width_units().set_value(w);
   149 }
   150 
   151 void GraphDisplayerCanvas::BrokenEdge::setFillColor(Gdk::Color c)
   152 {
   153   line.property_fill_color_gdk().set_value(c);
   154 }
   155 
   156 GraphDisplayerCanvas::LoopEdge::LoopEdge(Gnome::Canvas::Group& _group,
   157     Edge _edge, GraphDisplayerCanvas& _canvas) :
   158   EdgeBase(_group, _edge, _canvas), line(*this), isbutton(false)
   159 {
   160   arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler));
   161 
   162   line.property_outline_color().set_value("green");
   163   line.property_width_units().set_value(10);
   164   line.lower_to_bottom();
   165 
   166   draw();
   167 }
   168 
   169 GraphDisplayerCanvas::LoopEdge::~LoopEdge()
   170 {
   171 }
   172 
   173 void GraphDisplayerCanvas::LoopEdge::draw()
   174 {
   175   MapStorage& ms = canvas.mytab.mapstorage;
   176 
   177   Node node = ms.graph.source(edge);
   178   XY center = (ms.coords[node] + ms.arrow_pos[edge]) / 2.0;
   179 
   180   XY unit_vector_in_dir(rot90(center - ms.arrow_pos[edge]));
   181   double length = sqrt(unit_vector_in_dir.normSquare());
   182   unit_vector_in_dir /= length;
   183 
   184   drawArrow(unit_vector_in_dir);
   185 
   186   double radius =
   187     sqrt((ms.arrow_pos[edge] - ms.coords[node]).normSquare()) / 2.0;
   188 
   189   XY p1 = center + XY(-radius,  radius);
   190   XY p2 = center + XY( radius, -radius);
   191   line.property_x1().set_value(p1.x);
   192   line.property_y1().set_value(p1.y);
   193   line.property_x2().set_value(p2.x);
   194   line.property_y2().set_value(p2.y);
   195 }
   196 
   197 void GraphDisplayerCanvas::LoopEdge::setLineWidth(int w)
   198 {
   199   line.property_width_units().set_value(w);
   200 }
   201 
   202 void GraphDisplayerCanvas::LoopEdge::setFillColor(Gdk::Color c)
   203 {
   204   line.property_outline_color_gdk().set_value(c);
   205 }
   206 
   207 bool GraphDisplayerCanvas::LoopEdge::edgeFormerEventHandler(GdkEvent* e)
   208 {
   209   switch(e->type)
   210   {
   211     case GDK_BUTTON_PRESS:
   212       if(canvas.getActualTool()!=CREATE_NODE)
   213       {
   214         canvas.toggleEdgeActivity(this, true);
   215         isbutton=true;
   216       }
   217       break;
   218     case GDK_BUTTON_RELEASE:
   219       if(canvas.getActualTool()!=CREATE_NODE)
   220       {
   221         canvas.toggleEdgeActivity(this, false);
   222         isbutton=false;
   223       }
   224       break;
   225     case GDK_MOTION_NOTIFY:
   226       if(isbutton)
   227       {
   228         canvas.mytab.mapstorage.arrow_pos.set(edge, XY(e->motion.x, e->motion.y));
   229 
   230         draw();
   231         canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]);
   232       }
   233     default: break;
   234   }
   235   return true;
   236 }