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