COIN-OR::LEMON - Graph Library

source: glemon-0.x/gdc-broken_edge.cc @ 152:d99e115d0d26

Last change on this file since 152:d99e115d0d26 was 152:d99e115d0d26, checked in by Akos Ladanyi, 18 years ago

Bugfix.

File size: 6.7 KB
Line 
1#include "graph_displayer_canvas.h"
2#include <cmath>
3
4GraphDisplayerCanvas::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
12GraphDisplayerCanvas::EdgeBase::~EdgeBase()
13{
14}
15
16void 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
50GraphDisplayerCanvas::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
63GraphDisplayerCanvas::BrokenEdge::~BrokenEdge()
64{
65}
66
67void 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
96bool 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
147void GraphDisplayerCanvas::BrokenEdge::setLineWidth(int w)
148{
149  line.property_width_units().set_value(w);
150}
151
152void GraphDisplayerCanvas::BrokenEdge::setFillColor(Gdk::Color c)
153{
154  line.property_fill_color_gdk().set_value(c);
155}
156
157GraphDisplayerCanvas::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
170GraphDisplayerCanvas::LoopEdge::~LoopEdge()
171{
172}
173
174void 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
198void GraphDisplayerCanvas::LoopEdge::setLineWidth(int w)
199{
200  line.property_width_units().set_value(w);
201}
202
203void GraphDisplayerCanvas::LoopEdge::setFillColor(Gdk::Color c)
204{
205  line.property_outline_color_gdk().set_value(c);
206}
207
208bool 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}
Note: See TracBrowser for help on using the repository browser.