|
1 // This example was started by Guillaume Laurent. |
|
2 // It has become a place to dump code that tests parts of the |
|
3 // gnomemm canvas code. Little thought has been given to the |
|
4 // actual on-screen output. |
|
5 |
|
6 #include <libgnomecanvasmm.h> |
|
7 #include <libgnomecanvasmm/polygon.h> |
|
8 #include <iostream> |
|
9 #include <lemon/list_graph.h> |
|
10 |
|
11 class CanvasExample : public Gnome::Canvas::CanvasAA |
|
12 { |
|
13 typedef Gnome::Canvas::CanvasAA Parent; |
|
14 |
|
15 public: |
|
16 CanvasExample(double *, int); |
|
17 virtual ~CanvasExample(); |
|
18 |
|
19 private: |
|
20 |
|
21 ///Event handler function that handles dragging nodes of triangle |
|
22 bool event_handler(GdkEvent* e, int b); |
|
23 |
|
24 ///Event handler function that handles dragging triangle |
|
25 bool tri_mover(GdkEvent* e); |
|
26 |
|
27 ///Coordinates of Weight Point of tirangle |
|
28 Gnome::Art::Point * wp; |
|
29 ///Array of nodes of planefigure |
|
30 Gnome::Canvas::Ellipse ** nodes; |
|
31 ///Sides of planefigure |
|
32 Gnome::Canvas::Polygon * sides; |
|
33 ///Group of graphical elements of triangle |
|
34 Gnome::Canvas::Group triangle; |
|
35 |
|
36 ///Indicates whether the button of mouse is pressed or not |
|
37 bool isbutton; |
|
38 |
|
39 ///Number Of Elements - the number of nodes |
|
40 int noe; |
|
41 |
|
42 ///Array of coordinates |
|
43 double * coordinates; |
|
44 |
|
45 ///At this location was the mousebutton pressed. |
|
46 ///It helps to calculate the distance of dragging. |
|
47 double clicked_x, clicked_y; |
|
48 |
|
49 ///Remembers which Gnome::Canvas::Item was pressed. |
|
50 ///this variable is needed, because |
|
51 ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault |
|
52 ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution |
|
53 Gnome::Canvas::Item * active_item; |
|
54 |
|
55 |
|
56 }; |
|
57 |
|
58 ///When we click on the weight point we can drag the whole triangle. This function resolves it. |
|
59 bool CanvasExample::tri_mover(GdkEvent* e) |
|
60 { |
|
61 switch(e->type) |
|
62 { |
|
63 case GDK_BUTTON_PRESS: |
|
64 clicked_x=e->button.x; |
|
65 clicked_y=e->button.y; |
|
66 isbutton=true; |
|
67 break; |
|
68 case GDK_BUTTON_RELEASE: |
|
69 isbutton=false; |
|
70 active_item=NULL; |
|
71 break; |
|
72 case GDK_MOTION_NOTIFY: |
|
73 if(isbutton) |
|
74 { |
|
75 double dx=e->motion.x-clicked_x; |
|
76 double dy=e->motion.y-clicked_y; |
|
77 |
|
78 Gnome::Canvas::Points coos; |
|
79 |
|
80 for(int i=0;i<=noe;i++) |
|
81 { |
|
82 nodes[i]->move(dx,dy); |
|
83 |
|
84 double x=(coordinates[2*i]+=dx); |
|
85 double y=(coordinates[2*i+1]+=dy); |
|
86 |
|
87 if(i!=noe)coos.push_back(Gnome::Art::Point(x,y)); |
|
88 |
|
89 } |
|
90 |
|
91 clicked_x=e->motion.x; |
|
92 clicked_y=e->motion.y; |
|
93 |
|
94 sides->property_points().set_value(coos); |
|
95 } |
|
96 default: break; |
|
97 } |
|
98 return true; |
|
99 } |
|
100 |
|
101 ///This function moves only one node of triangle, |
|
102 ///but recalculate the location of wight point, |
|
103 ///and also redraw the sides of the planefigure. |
|
104 bool CanvasExample::event_handler(GdkEvent* e, int b) |
|
105 { |
|
106 switch(e->type) |
|
107 { |
|
108 case GDK_BUTTON_PRESS: |
|
109 clicked_x=e->button.x; |
|
110 clicked_y=e->button.y; |
|
111 active_item=(get_item_at(e->button.x, e->button.y)); |
|
112 isbutton=true; |
|
113 break; |
|
114 case GDK_BUTTON_RELEASE: |
|
115 isbutton=false; |
|
116 active_item=NULL; |
|
117 break; |
|
118 case GDK_MOTION_NOTIFY: |
|
119 if(isbutton) |
|
120 { |
|
121 //double x1, y1, x2, y2; |
|
122 //(get_item_at(e->motion.x, e->motion.y))->get_bounds(x1, y1, x2, y2); |
|
123 //printf("Item coos: %d %d %d %d\n", (int)x1, (int)y1, (int)x2, (int)y2); |
|
124 //printf("Mouse is moved! %d %d\n",(int)e->motion.x,(int)e->motion.y); |
|
125 double dx=e->motion.x-clicked_x; |
|
126 double dy=e->motion.y-clicked_y; |
|
127 active_item->move(dx, dy); |
|
128 |
|
129 coordinates[2*b]+=dx; |
|
130 coordinates[2*b+1]+=dy; |
|
131 |
|
132 Gnome::Canvas::Points coos; |
|
133 |
|
134 double x_wp=0; |
|
135 double y_wp=0; |
|
136 |
|
137 for(int i=0;i<noe;i++) |
|
138 { |
|
139 coos.push_back(Gnome::Art::Point(coordinates[2*i], coordinates[2*i+1])); |
|
140 |
|
141 x_wp+=coordinates[2*i]; |
|
142 y_wp+=coordinates[2*i+1]; |
|
143 } |
|
144 |
|
145 sides->property_points().set_value(coos); |
|
146 |
|
147 x_wp/=noe; |
|
148 y_wp/=noe; |
|
149 |
|
150 dx=x_wp-coordinates[noe*2]; |
|
151 dy=y_wp-coordinates[noe*2+1]; |
|
152 nodes[noe]->move(dx, dy); |
|
153 |
|
154 coordinates[noe*2]+=dx; |
|
155 coordinates[noe*2+1]+=dy; |
|
156 |
|
157 clicked_x=e->motion.x; |
|
158 clicked_y=e->motion.y; |
|
159 } |
|
160 default: break; |
|
161 } |
|
162 return true; |
|
163 } |
|
164 |
|
165 CanvasExample::CanvasExample(double * coosarray, int numofcoos):triangle(*(root()), 0, 0),isbutton(false),active_item(NULL) |
|
166 { |
|
167 noe=numofcoos/2; |
|
168 |
|
169 coordinates=new double [numofcoos+2]; |
|
170 |
|
171 double x_wp=0; |
|
172 double y_wp=0; |
|
173 |
|
174 Gnome::Canvas::Points coos; |
|
175 for(int i=0;i<numofcoos;i+=2) |
|
176 { |
|
177 coordinates[i]=coosarray[i]; |
|
178 coordinates[i+1]=coosarray[i+1]; |
|
179 coos.push_back(Gnome::Art::Point(coordinates[i], |
|
180 coordinates[i+1])); |
|
181 |
|
182 x_wp+=coordinates[i]; |
|
183 y_wp+=coordinates[i+1]; |
|
184 |
|
185 } |
|
186 |
|
187 sides=new Gnome::Canvas::Polygon(triangle, coos); |
|
188 *sides << Gnome::Canvas::Properties::outline_color("green"); |
|
189 sides->property_width_pixels().set_value(10); |
|
190 |
|
191 nodes=new Gnome::Canvas::Ellipse* [noe+1]; |
|
192 |
|
193 for(int i=0; i<noe;i++) |
|
194 { |
|
195 nodes[i]= new Gnome::Canvas::Ellipse(triangle, coos[i].get_x()-20, coos[i].get_y()-20, coos[i].get_x()+20, coos[i].get_y()+20); |
|
196 *(nodes[i]) << Gnome::Canvas::Properties::fill_color("blue"); |
|
197 *(nodes[i]) << Gnome::Canvas::Properties::outline_color("black"); |
|
198 (nodes[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &CanvasExample::event_handler),i)); |
|
199 } |
|
200 |
|
201 coordinates[numofcoos]=x_wp/noe; |
|
202 coordinates[numofcoos+1]=y_wp/noe; |
|
203 |
|
204 wp=new Gnome::Art::Point(coordinates[numofcoos],coordinates[numofcoos+1]); |
|
205 |
|
206 nodes[noe]= new Gnome::Canvas::Ellipse |
|
207 ( |
|
208 triangle, |
|
209 coordinates[numofcoos]-20, |
|
210 coordinates[numofcoos+1]-20, |
|
211 coordinates[numofcoos]+20, |
|
212 coordinates[numofcoos+1]+20 |
|
213 ); |
|
214 *(nodes[noe]) << Gnome::Canvas::Properties::fill_color("blue"); |
|
215 *(nodes[noe]) << Gnome::Canvas::Properties::outline_color("black"); |
|
216 (nodes[noe])->signal_event().connect(sigc::mem_fun(*this, &CanvasExample::tri_mover)); |
|
217 |
|
218 |
|
219 |
|
220 } |
|
221 |
|
222 CanvasExample::~CanvasExample() |
|
223 { |
|
224 } |
|
225 |
|
226 //MainWin: |
|
227 |
|
228 class MainWin : public Gtk::Window |
|
229 { |
|
230 public: |
|
231 MainWin(const std::string& title, double *, int); |
|
232 |
|
233 protected: |
|
234 //Member widgets: |
|
235 CanvasExample m_canvas; |
|
236 }; |
|
237 |
|
238 MainWin::MainWin(const std::string& title, double * coosarray, int noc):m_canvas(coosarray, noc) |
|
239 { |
|
240 set_title (title); |
|
241 add(m_canvas); |
|
242 set_default_size(900,600); |
|
243 |
|
244 show_all(); |
|
245 } |
|
246 |
|
247 //main(): |
|
248 |
|
249 int main(int argc, char *argv[]) |
|
250 { |
|
251 if((argc>=7)&& (argc%2) ) |
|
252 { |
|
253 double * coosarray=new double[argc]; |
|
254 |
|
255 for(int i=1;i<argc;i++) |
|
256 { |
|
257 coosarray[i-1]=atof(argv[i]); |
|
258 printf("%g%c",coosarray[i-1],i%2?' ':'\n'); |
|
259 } |
|
260 |
|
261 Gnome::Canvas::init(); |
|
262 Gtk::Main app(argc, argv); |
|
263 |
|
264 MainWin mainwin("Magic Triangle",coosarray,argc-1); |
|
265 app.run(mainwin); |
|
266 } |
|
267 |
|
268 return 0; |
|
269 } |