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