/* -*- C++ -*- * * This file is a part of LEMON, a generic C++ optimization library * * Copyright (C) 2003-2006 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #include #include #include #include DigraphDisplayerCanvas::ArcBase::ArcBase(Gnome::Canvas::Group& _group, Arc _arc, DigraphDisplayerCanvas& _canvas) : Gnome::Canvas::Group(_group), arc(_arc), canvas(_canvas), arrow(*this) { arrow.property_fill_color().set_value("red"); arrow.lower_to_bottom(); lower_to_bottom(); } DigraphDisplayerCanvas::ArcBase::~ArcBase() { } void DigraphDisplayerCanvas::ArcBase::drawArrow(XY unit_vector_in_dir) { MapStorage& ms = *canvas.mytab.mapstorage; XY center(ms.getArrowCoords(arc)); 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); } DigraphDisplayerCanvas::BrokenArc::BrokenArc(Gnome::Canvas::Group & g, Arc _arc, DigraphDisplayerCanvas & gc) : ArcBase(g, _arc, gc), isbutton(false), line(*this) { arrow.signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::BrokenArc::arcFormerEventHandler)); line.property_fill_color().set_value("green"); line.property_width_units().set_value(10); line.lower_to_bottom(); draw(); } DigraphDisplayerCanvas::BrokenArc::~BrokenArc() { } void DigraphDisplayerCanvas::BrokenArc::draw() { MapStorage& ms = *canvas.mytab.mapstorage; //calculating coordinates of the direction indicator arrow XY head(ms.getNodeCoords(ms.digraph.target(arc))); XY center(ms.getArrowCoords(arc)); XY unit_vector_in_dir(head-center); double length=sqrt( unit_vector_in_dir.normSquare() ); if(length!=0) { unit_vector_in_dir/=length; } // update the arrow drawArrow(unit_vector_in_dir); // update the arc Gnome::Canvas::Points points; Node source = ms.digraph.source(arc); Node target = ms.digraph.target(arc); points.push_back(Gnome::Art::Point(ms.getNodeCoords(source).x, ms.getNodeCoords(source).y)); points.push_back(Gnome::Art::Point(ms.getArrowCoords(arc).x, ms.getArrowCoords(arc).y)); points.push_back(Gnome::Art::Point(ms.getNodeCoords(target).x, ms.getNodeCoords(target).y)); line.property_points().set_value(points); } bool DigraphDisplayerCanvas::BrokenArc::arcFormerEventHandler(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.toggleArcActivity(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.toggleArcActivity(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->setArrowCoords(arc, canvas.mytab.mapstorage->getArrowCoords(arc) + XY(dx, dy)); draw(); canvas.textReposition(canvas.mytab.mapstorage->getArrowCoords(arc)); clicked_x=e->motion.x; clicked_y=e->motion.y; } default: break; } return true; } void DigraphDisplayerCanvas::BrokenArc::setLineWidth(int w) { line.property_width_units().set_value(w); } void DigraphDisplayerCanvas::BrokenArc::setFillColor(Gdk::Color c) { line.property_fill_color_gdk().set_value(c); } DigraphDisplayerCanvas::LoopArc::LoopArc(Gnome::Canvas::Group& _group, Arc _arc, DigraphDisplayerCanvas& _canvas) : ArcBase(_group, _arc, _canvas), line(*this), isbutton(false) { arrow.signal_event().connect(sigc::mem_fun(*this, &DigraphDisplayerCanvas::LoopArc::arcFormerEventHandler)); line.property_outline_color().set_value("green"); line.property_width_units().set_value(10); line.lower_to_bottom(); draw(); } DigraphDisplayerCanvas::LoopArc::~LoopArc() { } void DigraphDisplayerCanvas::LoopArc::draw() { MapStorage& ms = *canvas.mytab.mapstorage; Node node = ms.digraph.source(arc); XY center = (ms.getNodeCoords(node) + ms.getArrowCoords(arc)) / 2.0; XY unit_vector_in_dir(rot90(center - ms.getArrowCoords(arc))); double length = sqrt(unit_vector_in_dir.normSquare()); unit_vector_in_dir /= length; drawArrow(unit_vector_in_dir); double radius = sqrt((ms.getArrowCoords(arc) - ms.getNodeCoords(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 DigraphDisplayerCanvas::LoopArc::setLineWidth(int w) { line.property_width_units().set_value(w); } void DigraphDisplayerCanvas::LoopArc::setFillColor(Gdk::Color c) { line.property_outline_color_gdk().set_value(c); } bool DigraphDisplayerCanvas::LoopArc::arcFormerEventHandler(GdkEvent* e) { switch(e->type) { case GDK_BUTTON_PRESS: if(canvas.getActualTool()!=CREATE_NODE) { canvas.toggleArcActivity(this, true); isbutton=true; } break; case GDK_BUTTON_RELEASE: if(canvas.getActualTool()!=CREATE_NODE) { canvas.toggleArcActivity(this, false); isbutton=false; } break; case GDK_MOTION_NOTIFY: if(isbutton) { canvas.mytab.mapstorage->setArrowCoords(arc, XY(e->motion.x, e->motion.y)); draw(); canvas.textReposition(canvas.mytab.mapstorage->getArrowCoords(arc)); } default: break; } return true; }