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