#include "graph_displayer_canvas.h" #include GraphDisplayerCanvas::EdgeBase::EdgeBase(Gnome::Canvas::Group& _group, Edge _edge, GraphDisplayerCanvas& _canvas) : Gnome::Canvas::Group(_group), edge(_edge), canvas(_canvas), arrow(*this) { arrow.property_fill_color().set_value("red"); arrow.lower_to_bottom(); } GraphDisplayerCanvas::EdgeBase::~EdgeBase() { } void GraphDisplayerCanvas::EdgeBase::drawArrow(XY unit_vector_in_dir) { MapStorage& ms = canvas.mytab.mapstorage; XY center(ms.arrow_pos[edge]); XY unit_norm_vector(0-unit_vector_in_dir.y, unit_vector_in_dir.x); // /\ // top // / \ // // - - // c(enter)l(eft), ccl, ccr, cr // || // // || // b(ottom)l, br double size=3; XY bl (center - unit_vector_in_dir * 3 * size + unit_norm_vector * size ); XY br (center - unit_vector_in_dir * 3 * size - unit_norm_vector * size ); XY ccl(center + unit_vector_in_dir * size + unit_norm_vector * size ); XY ccr(center + unit_vector_in_dir * size - unit_norm_vector * size ); XY cl (center + unit_vector_in_dir * size + unit_norm_vector * 2 * size ); XY cr (center + unit_vector_in_dir * size - unit_norm_vector * 2 * size ); XY top(center + unit_vector_in_dir * 3 * size); Gnome::Canvas::Points arrow_points; arrow_points.push_back(Gnome::Art::Point( bl.x , bl.y ) ); arrow_points.push_back(Gnome::Art::Point( br.x , br.y ) ); arrow_points.push_back(Gnome::Art::Point( ccr.x, ccr.y ) ); arrow_points.push_back(Gnome::Art::Point( cr.x , cr.y ) ); arrow_points.push_back(Gnome::Art::Point( top.x, top.y ) ); arrow_points.push_back(Gnome::Art::Point( cl.x , cl.y ) ); arrow_points.push_back(Gnome::Art::Point( ccl.x, ccl.y ) ); arrow.property_points().set_value(arrow_points); } GraphDisplayerCanvas::BrokenEdge::BrokenEdge(Gnome::Canvas::Group & g, Edge _edge, GraphDisplayerCanvas & gc) : EdgeBase(g, _edge, gc), isbutton(false), line(*this) { arrow.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler)); line.property_fill_color().set_value("green"); line.property_width_units().set_value(10); line.lower_to_bottom(); draw(); } GraphDisplayerCanvas::BrokenEdge::~BrokenEdge() { } void GraphDisplayerCanvas::BrokenEdge::draw() { MapStorage& ms = canvas.mytab.mapstorage; //calculating coordinates of the direction indicator arrow XY head(ms.coords[ms.graph.target(edge)]); XY center(ms.arrow_pos[edge]); XY unit_vector_in_dir(head-center); double length=sqrt( unit_vector_in_dir.normSquare() ); unit_vector_in_dir/=length; // update the arrow drawArrow(unit_vector_in_dir); // update the edge Gnome::Canvas::Points points; Node source = ms.graph.source(edge); Node target = ms.graph.target(edge); points.push_back(Gnome::Art::Point(ms.coords[source].x, ms.coords[source].y)); points.push_back(Gnome::Art::Point(ms.arrow_pos[edge].x, ms.arrow_pos[edge].y)); points.push_back(Gnome::Art::Point(ms.coords[target].x, ms.coords[target].y)); line.property_points().set_value(points); } bool GraphDisplayerCanvas::BrokenEdge::edgeFormerEventHandler(GdkEvent* e) { switch(e->type) { case GDK_BUTTON_PRESS: //we mark the location of the event to be able to calculate parameters //of dragging if(canvas.getActualTool()!=CREATE_NODE) { canvas.toggleEdgeActivity(this, true); clicked_x=e->button.x; clicked_y=e->button.y; isbutton=true; } break; case GDK_BUTTON_RELEASE: if(canvas.getActualTool()!=CREATE_NODE) { canvas.toggleEdgeActivity(this, false); isbutton=false; } break; case GDK_MOTION_NOTIFY: //we only have to do sg. if the mouse button is pressed if(isbutton) { //new coordinates will be the old values, //because the item will be moved to the //new coordinate therefore the new movement //has to be calculated from here double dx=e->motion.x-clicked_x; double dy=e->motion.y-clicked_y; Gnome::Canvas::Points points_new; canvas.mytab.mapstorage.arrow_pos.set(edge, canvas.mytab.mapstorage.arrow_pos[edge] + XY(dx, dy)); draw(); canvas.textReposition(canvas.mytab.mapstorage.arrow_pos[edge]); clicked_x=e->motion.x; clicked_y=e->motion.y; } default: break; } return true; } void GraphDisplayerCanvas::BrokenEdge::setLineWidth(int w) { line.property_width_units().set_value(w); } void GraphDisplayerCanvas::BrokenEdge::setFillColor(Gdk::Color c) { line.property_fill_color_gdk().set_value(c); } GraphDisplayerCanvas::LoopEdge::LoopEdge(Gnome::Canvas::Group& _group, Edge _edge, GraphDisplayerCanvas& _canvas) : EdgeBase(_group, _edge, _canvas), line(*this) { line.property_fill_color().set_value("green"); line.property_width_units().set_value(10); line.lower_to_bottom(); draw(); } GraphDisplayerCanvas::LoopEdge::~LoopEdge() { } void GraphDisplayerCanvas::LoopEdge::draw() { MapStorage& ms = canvas.mytab.mapstorage; Node node = ms.graph.source(edge); XY center = (ms.coords[node] + ms.arrow_pos[edge]) / 2.0; XY unit_vector_in_dir(rot90(center - ms.arrow_pos[edge])); double length = sqrt(unit_vector_in_dir.normSquare()); unit_vector_in_dir /= length; drawArrow(unit_vector_in_dir); double radius = sqrt((ms.arrow_pos[edge] - ms.coords[node]).normSquare()) / 2.0; XY p1 = center + XY(-radius, radius); XY p2 = center + XY( radius, -radius); line.property_x1().set_value(p1.x); line.property_y1().set_value(p1.y); line.property_x2().set_value(p2.x); line.property_y2().set_value(p2.y); } void GraphDisplayerCanvas::LoopEdge::setLineWidth(int w) { line.property_width_units().set_value(w); } void GraphDisplayerCanvas::LoopEdge::setFillColor(Gdk::Color c) { line.property_fill_color_gdk().set_value(c); }