hegyi@1289: // This example was started by Guillaume Laurent. hegyi@1289: // It has become a place to dump code that tests parts of the hegyi@1289: // gnomemm canvas code. Little thought has been given to the hegyi@1289: // actual on-screen output. hegyi@1289: hegyi@1289: #include hegyi@1289: #include hegyi@1289: hegyi@1289: #include hegyi@1289: #include hegyi@1289: hegyi@1289: #include hegyi@1289: #include hegyi@1289: #include hegyi@1289: #include hegyi@1289: #include hegyi@1289: #include hegyi@1289: hegyi@1289: using namespace lemon; hegyi@1289: hegyi@1289: typedef xy Coordinates; hegyi@1289: typedef ListGraph Graph; hegyi@1289: typedef Graph::NodeMap CoordinatesMap; hegyi@1289: typedef Graph::Node Node; hegyi@1289: typedef Graph::EdgeIt EdgeIt; hegyi@1289: typedef Graph::NodeIt NodeIt; hegyi@1289: hegyi@1289: class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA hegyi@1289: { hegyi@1289: typedef Gnome::Canvas::CanvasAA Parent; hegyi@1289: hegyi@1289: public: hegyi@1289: GraphDisplayerCanvas(Graph &, CoordinatesMap &); hegyi@1289: virtual ~GraphDisplayerCanvas(); hegyi@1289: hegyi@1289: private: hegyi@1289: hegyi@1289: ///Event handler function that handles dragging nodes of displayed_graph hegyi@1289: bool event_handler(GdkEvent* e, int b); hegyi@1289: hegyi@1289: ///Event handler function that handles dragging displayed_graph hegyi@1289: bool tri_mover(GdkEvent* e); hegyi@1289: hegyi@1289: ///Coordinates of Weight Point of tirangle hegyi@1289: Gnome::Art::Point * wp; hegyi@1289: ///Array of nodes of planefigure hegyi@1289: Gnome::Canvas::Ellipse ** nodes; hegyi@1289: ///Sides of planefigure hegyi@1289: Gnome::Canvas::Polygon * sides; hegyi@1289: ///Group of graphical elements of displayed_graph hegyi@1289: Gnome::Canvas::Group displayed_graph; hegyi@1289: hegyi@1289: ///Indicates whether the button of mouse is pressed or not hegyi@1289: bool isbutton; hegyi@1289: hegyi@1289: ///Number Of Elements - the number of nodes hegyi@1289: int noe; hegyi@1289: hegyi@1289: ///Array of coordinates hegyi@1289: double * coordinates; hegyi@1289: hegyi@1289: ///At this location was the mousebutton pressed. hegyi@1289: ///It helps to calculate the distance of dragging. hegyi@1289: double clicked_x, clicked_y; hegyi@1289: hegyi@1289: ///Remembers which Gnome::Canvas::Item was pressed. hegyi@1289: ///this variable is needed, because hegyi@1289: ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault hegyi@1289: ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution hegyi@1289: Gnome::Canvas::Item * active_item; hegyi@1289: hegyi@1289: hegyi@1289: }; hegyi@1289: hegyi@1289: ///When we click on the weight point we can drag the whole planefigure. This function resolves it. hegyi@1289: bool GraphDisplayerCanvas::tri_mover(GdkEvent* e) hegyi@1289: { hegyi@1289: switch(e->type) hegyi@1289: { hegyi@1289: case GDK_BUTTON_PRESS: hegyi@1289: clicked_x=e->button.x; hegyi@1289: clicked_y=e->button.y; hegyi@1289: isbutton=true; hegyi@1289: break; hegyi@1289: case GDK_BUTTON_RELEASE: hegyi@1289: isbutton=false; hegyi@1289: active_item=NULL; hegyi@1289: break; hegyi@1289: case GDK_MOTION_NOTIFY: hegyi@1289: if(isbutton) hegyi@1289: { hegyi@1289: double dx=e->motion.x-clicked_x; hegyi@1289: double dy=e->motion.y-clicked_y; hegyi@1289: hegyi@1289: Gnome::Canvas::Points coos; hegyi@1289: hegyi@1289: for(int i=0;i<=noe;i++) hegyi@1289: { hegyi@1289: nodes[i]->move(dx,dy); hegyi@1289: hegyi@1289: double x=(coordinates[2*i]+=dx); hegyi@1289: double y=(coordinates[2*i+1]+=dy); hegyi@1289: hegyi@1289: if(i!=noe)coos.push_back(Gnome::Art::Point(x,y)); hegyi@1289: hegyi@1289: } hegyi@1289: hegyi@1289: clicked_x=e->motion.x; hegyi@1289: clicked_y=e->motion.y; hegyi@1289: hegyi@1289: sides->property_points().set_value(coos); hegyi@1289: } hegyi@1289: default: break; hegyi@1289: } hegyi@1289: return true; hegyi@1289: } hegyi@1289: hegyi@1289: ///This function moves only one node of displayed_graph, hegyi@1289: ///but recalculate the location of weight point, hegyi@1289: ///and also redraw the sides of the planefigure. hegyi@1289: bool GraphDisplayerCanvas::event_handler(GdkEvent* e, int b) hegyi@1289: { hegyi@1289: switch(e->type) hegyi@1289: { hegyi@1289: case GDK_BUTTON_PRESS: hegyi@1289: clicked_x=e->button.x; hegyi@1289: clicked_y=e->button.y; hegyi@1289: active_item=(get_item_at(e->button.x, e->button.y)); hegyi@1289: isbutton=true; hegyi@1289: break; hegyi@1289: case GDK_BUTTON_RELEASE: hegyi@1289: isbutton=false; hegyi@1289: active_item=NULL; hegyi@1289: break; hegyi@1289: case GDK_MOTION_NOTIFY: hegyi@1289: if(isbutton) hegyi@1289: { hegyi@1289: //double x1, y1, x2, y2; hegyi@1289: //(get_item_at(e->motion.x, e->motion.y))->get_bounds(x1, y1, x2, y2); hegyi@1289: //printf("Item coos: %d %d %d %d\n", (int)x1, (int)y1, (int)x2, (int)y2); hegyi@1289: //printf("Mouse is moved! %d %d\n",(int)e->motion.x,(int)e->motion.y); hegyi@1289: double dx=e->motion.x-clicked_x; hegyi@1289: double dy=e->motion.y-clicked_y; hegyi@1289: active_item->move(dx, dy); hegyi@1289: hegyi@1289: coordinates[2*b]+=dx; hegyi@1289: coordinates[2*b+1]+=dy; hegyi@1289: hegyi@1289: Gnome::Canvas::Points coos; hegyi@1289: hegyi@1289: double x_wp=0; hegyi@1289: double y_wp=0; hegyi@1289: hegyi@1289: for(int i=0;iproperty_points().set_value(coos); hegyi@1289: hegyi@1289: x_wp/=noe; hegyi@1289: y_wp/=noe; hegyi@1289: hegyi@1289: dx=x_wp-coordinates[noe*2]; hegyi@1289: dy=y_wp-coordinates[noe*2+1]; hegyi@1289: nodes[noe]->move(dx, dy); hegyi@1289: hegyi@1289: coordinates[noe*2]+=dx; hegyi@1289: coordinates[noe*2+1]+=dy; hegyi@1289: hegyi@1289: clicked_x=e->motion.x; hegyi@1289: clicked_y=e->motion.y; hegyi@1289: } hegyi@1289: default: break; hegyi@1289: } hegyi@1289: return true; hegyi@1289: } hegyi@1289: hegyi@1289: GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & g, CoordinatesMap & cm):displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL) hegyi@1289: { hegyi@1289: nodes=new Gnome::Canvas::Ellipse* [countNodes(g)]; hegyi@1289: int sorszam=0; hegyi@1289: hegyi@1289: for (NodeIt i(g); i!=INVALID; ++i) hegyi@1289: { hegyi@1289: nodes[sorszam]= new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20); hegyi@1289: *(nodes[sorszam]) << Gnome::Canvas::Properties::fill_color("blue"); hegyi@1289: *(nodes[sorszam]) << Gnome::Canvas::Properties::outline_color("black"); hegyi@1289: (nodes[sorszam])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),sorszam)); hegyi@1289: sorszam++; hegyi@1289: } hegyi@1289: hegyi@1289: for (EdgeIt i(g); i!=INVALID; ++i) hegyi@1289: { hegyi@1289: } hegyi@1289: hegyi@1289: hegyi@1289: } hegyi@1289: hegyi@1289: GraphDisplayerCanvas::~GraphDisplayerCanvas() hegyi@1289: { hegyi@1289: } hegyi@1289: hegyi@1289: //MainWin: hegyi@1289: hegyi@1289: class MainWin : public Gtk::Window hegyi@1289: { hegyi@1289: public: hegyi@1289: MainWin(const std::string& title, Graph &, CoordinatesMap &); hegyi@1289: hegyi@1289: protected: hegyi@1289: //Member widgets: hegyi@1289: GraphDisplayerCanvas gd_canvas; hegyi@1289: }; hegyi@1289: hegyi@1289: MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm) hegyi@1289: { hegyi@1289: set_title (title); hegyi@1289: add(gd_canvas); hegyi@1289: set_default_size(900,600); hegyi@1289: hegyi@1289: show_all(); hegyi@1289: } hegyi@1289: hegyi@1289: hegyi@1289: ///This class is responsible for being able hegyi@1289: ///to read xy datastructure from file. It is hegyi@1289: ///based on BaseMap. The set method sets the hegyi@1289: ///appropriate value in the final xy NodeMap hegyi@1289: ///that was given to the constructor. hegyi@1289: class CoordReaderMap: public MapBase hegyi@1289: { hegyi@1289: CoordinatesMap & cm; hegyi@1289: char xoy; hegyi@1289: hegyi@1289: public: hegyi@1289: CoordReaderMap(char xory, CoordinatesMap & coordmap); hegyi@1289: void set(Node node, double coord); hegyi@1289: }; hegyi@1289: hegyi@1289: ///The constructor expects for an xy NodeMap, hegyi@1289: ///and we have to tell it, for which value hegyi@1289: ///of the xy vector is responsible the actual hegyi@1289: ///copy. hegyi@1289: CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap) hegyi@1289: { hegyi@1289: switch(xory) hegyi@1289: { hegyi@1289: case 'x': hegyi@1289: case 'y': hegyi@1289: xoy=xory; hegyi@1289: break; hegyi@1289: default: hegyi@1289: throw UninitializedParameter() ; hegyi@1289: } hegyi@1289: } hegyi@1289: hegyi@1289: ///set method sets the appropriate value in the hegyi@1289: ///xy type NodeMap that is under construction hegyi@1289: void CoordReaderMap::set(Node node, double coord) hegyi@1289: { hegyi@1289: switch(xoy) hegyi@1289: { hegyi@1289: case 'x': hegyi@1289: cm[node].x=coord; hegyi@1289: break; hegyi@1289: case 'y': hegyi@1289: cm[node].y=coord; hegyi@1289: break; hegyi@1289: default: hegyi@1289: throw UninitializedParameter() ; hegyi@1289: } hegyi@1289: } hegyi@1289: hegyi@1289: //main(): hegyi@1289: hegyi@1289: int main(int argc, char *argv[]) hegyi@1289: { hegyi@1290: if(argc<2) hegyi@1290: { hegyi@1290: std::cerr << "USAGE: gd " << endl; hegyi@1290: return 0; hegyi@1290: } hegyi@1289: hegyi@1289: Coordinates coosvector; hegyi@1289: hegyi@1289: Graph g; hegyi@1289: hegyi@1289: CoordinatesMap cm(g); hegyi@1289: hegyi@1289: //we create one object to read x coordinates hegyi@1289: //and one to read y coordinate of nodes and write them to cm NodeMap. hegyi@1289: CoordReaderMap xreader('x',cm); hegyi@1289: CoordReaderMap yreader('y',cm); hegyi@1289: hegyi@1290: std::ifstream is(argv[1]); hegyi@1289: hegyi@1289: GraphReader reader(is, g); hegyi@1289: reader.addNodeMap("coordinates_x", xreader); hegyi@1289: reader.addNodeMap("coordinates_y", yreader); hegyi@1289: reader.run(); hegyi@1289: hegyi@1289: for (NodeIt i(g); i!=INVALID; ++i) hegyi@1289: std::cout << " " << g.id(i) << " " << cm[i]; hegyi@1289: std::cout << std::endl; hegyi@1289: hegyi@1289: Gnome::Canvas::init(); hegyi@1289: Gtk::Main app(argc, argv); hegyi@1289: hegyi@1289: MainWin mainwin("Displayed Graph", g, cm); hegyi@1289: app.run(mainwin); hegyi@1289: hegyi@1289: return 0; hegyi@1289: }