diff -r 0e4f009eab8b -r 67188bd752db gdc-broken_edge.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gdc-broken_edge.cc Mon Jul 07 08:10:39 2008 -0500 @@ -0,0 +1,260 @@ +/* -*- 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; +}