1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gui/graph_displayer_canvas-event.cc Fri Jun 24 07:58:18 2005 +0000
1.3 @@ -0,0 +1,492 @@
1.4 +#include <graph_displayer_canvas.h>
1.5 +#include <broken_edge.h>
1.6 +#include <math.h>
1.7 +
1.8 +
1.9 +bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
1.10 +{
1.11 + Gnome::Canvas::CanvasAA::on_expose_event(event);
1.12 + //usleep(10000);
1.13 + //rezoom();
1.14 + return true;
1.15 +}
1.16 +
1.17 +void GraphDisplayerCanvas::changeEditorialTool(int newtool)
1.18 +{
1.19 + actual_handler.disconnect();
1.20 +
1.21 + if(actual_tool==CREATE_EDGE)
1.22 + {
1.23 + GdkEvent * generated=new GdkEvent();
1.24 + generated->type=GDK_BUTTON_RELEASE;
1.25 + generated->button.button=3;
1.26 + create_edge_event_handler(generated);
1.27 + }
1.28 +
1.29 + actual_tool=newtool;
1.30 +
1.31 + switch(newtool)
1.32 + {
1.33 + case MOVE:
1.34 + actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
1.35 + break;
1.36 +
1.37 + //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
1.38 + case CREATE_NODE:
1.39 + actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
1.40 + break;
1.41 +
1.42 + case CREATE_EDGE:
1.43 + actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
1.44 + break;
1.45 +
1.46 + case ERASER:
1.47 + actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraser_event_handler), false);
1.48 + break;
1.49 +
1.50 + default:
1.51 + break;
1.52 + }
1.53 +}
1.54 +
1.55 +int GraphDisplayerCanvas::get_actual_tool()
1.56 +{
1.57 + return actual_tool;
1.58 +}
1.59 +
1.60 +bool GraphDisplayerCanvas::move_event_handler(GdkEvent* e)
1.61 +{
1.62 + switch(e->type)
1.63 + {
1.64 + case GDK_BUTTON_PRESS:
1.65 + //we mark the location of the event to be able to calculate parameters of dragging
1.66 + clicked_x=e->button.x;
1.67 + clicked_y=e->button.y;
1.68 + active_item=(get_item_at(e->button.x, e->button.y));
1.69 + active_node=INVALID;
1.70 + for (NodeIt i(g); i!=INVALID; ++i)
1.71 + {
1.72 + if(nodesmap[i]==active_item)
1.73 + {
1.74 + active_node=i;
1.75 + }
1.76 + }
1.77 + switch(e->button.button)
1.78 + {
1.79 + case 3:
1.80 + isbutton=3;
1.81 + break;
1.82 + default:
1.83 + isbutton=1;
1.84 + break;
1.85 + }
1.86 + break;
1.87 + case GDK_BUTTON_RELEASE:
1.88 + isbutton=0;
1.89 + active_item=NULL;
1.90 + active_node=INVALID;
1.91 + updateScrollRegion();
1.92 + break;
1.93 + case GDK_MOTION_NOTIFY:
1.94 + //we only have to do sg. if the mouse button is pressed AND the click was on a node that was found in the set of nodes
1.95 + if(active_node!=INVALID)
1.96 + {
1.97 + //new coordinates will be the old values,
1.98 + //because the item will be moved to the
1.99 + //new coordinate therefore the new movement
1.100 + //has to be calculated from here
1.101 +
1.102 + double dx=e->motion.x-clicked_x;
1.103 + double dy=e->motion.y-clicked_y;
1.104 +
1.105 + active_item->move(dx, dy);
1.106 +
1.107 + clicked_x=e->motion.x;
1.108 + clicked_y=e->motion.y;
1.109 +
1.110 + //all the edges connected to the moved point has to be redrawn
1.111 + EdgeIt ei;
1.112 +
1.113 + g.firstOut(ei,active_node);
1.114 +
1.115 + for(;ei!=INVALID;g.nextOut(ei))
1.116 + {
1.117 + Gnome::Canvas::Points coos;
1.118 + double x1, x2, y1, y2;
1.119 +
1.120 + nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
1.121 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.122 +
1.123 + nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
1.124 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.125 +
1.126 + if(isbutton==3)
1.127 + {
1.128 + edgesmap[ei]->set_points(coos);
1.129 + }
1.130 + else
1.131 + {
1.132 + edgesmap[ei]->set_points(coos,true);
1.133 + }
1.134 +
1.135 + xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
1.136 + text_pos+=(xy<double>(10,10));
1.137 + edgetextmap[ei]->property_x().set_value(text_pos.x);
1.138 + edgetextmap[ei]->property_y().set_value(text_pos.y);
1.139 + }
1.140 +
1.141 + g.firstIn(ei,active_node);
1.142 + for(;ei!=INVALID;g.nextIn(ei))
1.143 + {
1.144 + Gnome::Canvas::Points coos;
1.145 + double x1, x2, y1, y2;
1.146 +
1.147 + nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
1.148 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.149 +
1.150 + nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
1.151 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.152 +
1.153 + if(isbutton==3)
1.154 + {
1.155 + edgesmap[ei]->set_points(coos);
1.156 + }
1.157 + else
1.158 + {
1.159 + edgesmap[ei]->set_points(coos,true);
1.160 + }
1.161 +
1.162 + xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
1.163 + text_pos+=(xy<double>(10,10));
1.164 + edgetextmap[ei]->property_x().set_value(text_pos.x);
1.165 + edgetextmap[ei]->property_y().set_value(text_pos.y);
1.166 + }
1.167 + }
1.168 + default: break;
1.169 + }
1.170 +
1.171 + return true;
1.172 +}
1.173 +
1.174 +bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
1.175 +{
1.176 + switch(e->type)
1.177 + {
1.178 +
1.179 + //draw the new node in red at the clicked place
1.180 + case GDK_BUTTON_PRESS:
1.181 + isbutton=1;
1.182 +
1.183 + active_node=NodeIt(g,g.addNode());
1.184 +
1.185 + //initiating values corresponding to new node in maps
1.186 +
1.187 +
1.188 + window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
1.189 +
1.190 + nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
1.191 + active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
1.192 + *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
1.193 + *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
1.194 + (nodesmap[active_node])->show();
1.195 + break;
1.196 +
1.197 + //move the new node
1.198 + case GDK_MOTION_NOTIFY:
1.199 + {
1.200 + double world_motion_x, world_motion_y;
1.201 + GdkEvent * generated=new GdkEvent();
1.202 + window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
1.203 + generated->motion.x=world_motion_x;
1.204 + generated->motion.y=world_motion_y;
1.205 + generated->type=GDK_MOTION_NOTIFY;
1.206 + move_event_handler(generated);
1.207 + break;
1.208 + }
1.209 +
1.210 + //finalize the new node
1.211 + case GDK_BUTTON_RELEASE:
1.212 + isbutton=0;
1.213 + *active_item << Gnome::Canvas::Properties::fill_color("blue");
1.214 + active_item=NULL;
1.215 + active_node=INVALID;
1.216 + updateScrollRegion();
1.217 + break;
1.218 + default:
1.219 + break;
1.220 + }
1.221 + return false;
1.222 +}
1.223 +
1.224 +bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
1.225 +{
1.226 + switch(e->type)
1.227 + {
1.228 + case GDK_BUTTON_PRESS:
1.229 + //in edge creation right button has special meaning
1.230 + if(e->button.button!=3)
1.231 + {
1.232 + //there is not yet selected node
1.233 + if(active_node==INVALID)
1.234 + {
1.235 + //we mark the location of the event to be able to calculate parameters of dragging
1.236 + clicked_x=e->button.x;
1.237 + clicked_y=e->button.y;
1.238 + active_item=(get_item_at(e->button.x, e->button.y));
1.239 + active_node=INVALID;
1.240 + for (NodeIt i(g); i!=INVALID; ++i)
1.241 + {
1.242 + if(nodesmap[i]==active_item)
1.243 + {
1.244 + active_node=i;
1.245 + }
1.246 + }
1.247 + //the clicked item is really a node
1.248 + if(active_node!=INVALID)
1.249 + {
1.250 + *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
1.251 + isbutton=1;
1.252 + }
1.253 + //clicked item was not a node. It could be e.g. edge.
1.254 + else
1.255 + {
1.256 + active_item=NULL;
1.257 + }
1.258 + }
1.259 + //we only have to do sg. if the mouse button
1.260 + // is pressed already once AND the click was
1.261 + // on a node that was found in the set of
1.262 + //nodes, and now we only search for the second
1.263 + //node
1.264 + else
1.265 + {
1.266 + target_item=(get_item_at(e->button.x, e->button.y));
1.267 + Graph::NodeIt target_node=INVALID;
1.268 + for (NodeIt i(g); i!=INVALID; ++i)
1.269 + {
1.270 + if(nodesmap[i]==target_item)
1.271 + {
1.272 + target_node=i;
1.273 + }
1.274 + }
1.275 + //the clicked item is a node, the edge can be drawn
1.276 + if(target_node!=INVALID)
1.277 + {
1.278 + *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
1.279 +
1.280 + //creating new edge
1.281 + active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
1.282 +
1.283 + //initiating values corresponding to new edge in maps
1.284 + mapstorage.init_maps_for_edge(active_edge);
1.285 +
1.286 + //calculating coordinates of new edge
1.287 + Gnome::Canvas::Points coos;
1.288 + double x1, x2, y1, y2;
1.289 +
1.290 + active_item->get_bounds(x1, y1, x2, y2);
1.291 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.292 +
1.293 + target_item->get_bounds(x1, y1, x2, y2);
1.294 + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
1.295 +
1.296 + //drawing new edge
1.297 + edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
1.298 + *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
1.299 + edgesmap[active_edge]->property_width_pixels().set_value(10);
1.300 +
1.301 + //redraw nodes to blank terminations of the new edge
1.302 + target_item->raise_to_top();
1.303 + active_item->raise_to_top();
1.304 +
1.305 + //initializing edge-text as well, to empty string
1.306 + xy<double> text_pos=edgesmap[active_edge]->get_arrow_pos();
1.307 + text_pos+=(xy<double>(10,10));
1.308 +
1.309 + edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
1.310 + edgetextmap[active_edge]->property_fill_color().set_value("black");
1.311 + }
1.312 + //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
1.313 + else
1.314 + {
1.315 + target_item=NULL;
1.316 + }
1.317 + }
1.318 + }
1.319 + break;
1.320 + case GDK_BUTTON_RELEASE:
1.321 + isbutton=0;
1.322 + //we clear settings in two cases
1.323 + //1: the edge is ready (target_item has valid value)
1.324 + //2: the edge creation is cancelled with right button
1.325 + if((target_item)||(e->button.button==3))
1.326 + {
1.327 + if(active_item)
1.328 + {
1.329 + *active_item << Gnome::Canvas::Properties::fill_color("blue");
1.330 + active_item=NULL;
1.331 + }
1.332 + if(target_item)
1.333 + {
1.334 + *target_item << Gnome::Canvas::Properties::fill_color("blue");
1.335 + target_item=NULL;
1.336 + }
1.337 + active_node=INVALID;
1.338 + active_edge=INVALID;
1.339 + }
1.340 + break;
1.341 + default:
1.342 + break;
1.343 + }
1.344 + return false;
1.345 +}
1.346 +
1.347 +bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
1.348 +{
1.349 + switch(e->type)
1.350 + {
1.351 + case GDK_BUTTON_PRESS:
1.352 + active_item=(get_item_at(e->button.x, e->button.y));
1.353 + active_node=INVALID;
1.354 + active_edge=INVALID;
1.355 + for (NodeIt i(g); i!=INVALID; ++i)
1.356 + {
1.357 + if(nodesmap[i]==active_item)
1.358 + {
1.359 + active_node=i;
1.360 + }
1.361 + }
1.362 + if(active_node==INVALID)
1.363 + {
1.364 + for (EdgeIt i(g); i!=INVALID; ++i)
1.365 + {
1.366 + if(edgesmap[i]==active_item)
1.367 + {
1.368 + active_edge=i;
1.369 + }
1.370 + }
1.371 + }
1.372 + *active_item << Gnome::Canvas::Properties::fill_color("red");
1.373 + break;
1.374 +
1.375 + case GDK_BUTTON_RELEASE:
1.376 + if(active_item==(get_item_at(e->button.x, e->button.y)))
1.377 + {
1.378 + if(active_node!=INVALID)
1.379 + {
1.380 +
1.381 + //collecting edges to delete
1.382 + EdgeIt e;
1.383 + std::set<Graph::Edge> edges_to_delete;
1.384 +
1.385 + g.firstOut(e,active_node);
1.386 + for(;e!=INVALID;g.nextOut(e))
1.387 + {
1.388 + edges_to_delete.insert(e);
1.389 + }
1.390 +
1.391 + g.firstIn(e,active_node);
1.392 + for(;e!=INVALID;g.nextIn(e))
1.393 + {
1.394 + edges_to_delete.insert(e);
1.395 + }
1.396 +
1.397 + //deleting collected edges
1.398 + for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
1.399 + {
1.400 + delete_item(*edge_set_it);
1.401 + }
1.402 + delete_item(active_node);
1.403 + }
1.404 + //a simple edge was chosen
1.405 + else
1.406 + {
1.407 + delete_item(active_edge);
1.408 + }
1.409 +
1.410 +
1.411 + }
1.412 + //pointer was moved, deletion is cancelled
1.413 + else
1.414 + {
1.415 + if(active_node!=INVALID)
1.416 + {
1.417 + *active_item << Gnome::Canvas::Properties::fill_color("blue");
1.418 + }
1.419 + else
1.420 + {
1.421 + *active_item << Gnome::Canvas::Properties::fill_color("green");
1.422 + }
1.423 + }
1.424 + //reseting datas
1.425 + active_item=NULL;
1.426 + active_edge=INVALID;
1.427 + active_node=INVALID;
1.428 + break;
1.429 +
1.430 + case GDK_MOTION_NOTIFY:
1.431 + break;
1.432 +
1.433 + default:
1.434 + break;
1.435 + }
1.436 + return true;
1.437 +}
1.438 +
1.439 +void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
1.440 +{
1.441 + delete(nodesmap[node_to_delete]);
1.442 + g.erase(node_to_delete);
1.443 +}
1.444 +
1.445 +void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
1.446 +{
1.447 + delete(edgesmap[edge_to_delete]);
1.448 + g.erase(edge_to_delete);
1.449 +}
1.450 +
1.451 +void GraphDisplayerCanvas::delete_item(Graph::Edge edge_to_delete)
1.452 +{
1.453 + delete(edgesmap[edge_to_delete]);
1.454 + g.erase(edge_to_delete);
1.455 +}
1.456 +
1.457 +void GraphDisplayerCanvas::text_reposition(xy<double> new_place)
1.458 +{
1.459 + new_place+=(xy<double>(10,10));
1.460 + edgetextmap[active_edge]->property_x().set_value(new_place.x);
1.461 + edgetextmap[active_edge]->property_y().set_value(new_place.y);
1.462 +}
1.463 +
1.464 +void GraphDisplayerCanvas::toggle_edge_activity(BrokenEdge* active_bre, bool on)
1.465 +{
1.466 + if(on)
1.467 + {
1.468 + if(active_edge!=INVALID)
1.469 + {
1.470 + std::cout << "ERROR!!!! Valid edge found!" << std::endl;
1.471 + }
1.472 + else
1.473 + {
1.474 + for (EdgeIt i(g); i!=INVALID; ++i)
1.475 + {
1.476 + if(edgesmap[i]==active_bre)
1.477 + {
1.478 + active_edge=i;
1.479 + }
1.480 + }
1.481 + }
1.482 + }
1.483 + else
1.484 + {
1.485 + if(active_edge!=INVALID)
1.486 + {
1.487 + active_edge=INVALID;
1.488 + }
1.489 + else
1.490 + {
1.491 + std::cout << "ERROR!!!! Invalid edge found!" << std::endl;
1.492 + }
1.493 + }
1.494 +
1.495 +}