ladanyi@1442: // -*- C++ -*- // ladanyi@1442: ladanyi@1442: #ifndef GRAPH_DISPLAYER_CANVAS_H ladanyi@1442: #define GRAPH_DISPLAYER_CANVAS_H ladanyi@1442: hegyi@1501: class GraphDisplayerCanvas; hegyi@1501: ladanyi@1606: #include "all_include.h" hegyi@1849: #include "nbtab.h" ladanyi@1442: #include ladanyi@1442: #include hegyi@1819: #include ladanyi@1442: ladanyi@1442: ///This class is the canvas, on which the graph can be drawn. ladanyi@1442: class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA ladanyi@1442: { ladanyi@1860: friend class BrokenEdge; ladanyi@1860: hegyi@1888: ///Edge displayer class hegyi@1888: hegyi@1888: ///This class is responsible for displaying edges in graph. hegyi@1888: ///The displayed edge is broken in the middle. The hegyi@1888: ///aim of this is to be able to indicate direction of edges hegyi@1888: ///and to be able to display more then one edges between the hegyi@1888: ///same source and target hegyi@1819: class BrokenEdge : public Gnome::Canvas::Line hegyi@1819: { hegyi@1888: ///The edge that the class displays. hegyi@1888: hegyi@1888: ///It is needed, because some datas needed from hegyi@1888: ///graph can be accessed by this or should be sent hegyi@1888: ///as parameter, but it would be complicated ladanyi@1860: Edge edge; hegyi@1888: hegyi@1888: ///Reference to the canvas, on which the graph is drawn. hegyi@1888: hegyi@1888: ///It is needed, because some datas needed from hegyi@1888: ///graph can be accessed by this or should be sent hegyi@1888: ///as parameter, but it would be complicated hegyi@1819: GraphDisplayerCanvas & gdc; hegyi@1888: hegyi@1888: ///An arrow that indicates the direction of the edges hegyi@1888: hegyi@1888: ///in case of directional graph direction can be indicated hegyi@1888: ///by this polygon. The polygon formulates a red arrow. hegyi@1819: Gnome::Canvas::Polygon * arrow; hegyi@1819: hegyi@1888: ///Indicates whether the button of mouse is pressed or not at the moment. hegyi@1819: bool isbutton; hegyi@1819: hegyi@1888: ///At this location was the mousebutton pressed. Horizontal component. hegyi@1819: hegyi@1888: ///It helps to calculate the hegyi@1888: ///distance of dragging. hegyi@1888: double clicked_x; hegyi@1888: hegyi@1888: ///At this location was the mousebutton pressed. Vertical component. hegyi@1888: hegyi@1888: ///It helps to calculate the hegyi@1888: ///distance of dragging. hegyi@1888: double clicked_y; hegyi@1888: hegyi@1888: ///event handler for forming broken edges hegyi@1888: hegyi@1888: ///\param event the hegyi@1888: ///event to handle hegyi@1888: bool edgeFormerEventHandler(GdkEvent* event); hegyi@1819: public: hegyi@1888: hegyi@1888: ///Constructor of broken edge class. hegyi@1888: hegyi@1888: ///\param g the group to which the edge belongs hegyi@1888: ///\param _edge the represented edge hegyi@1888: ///\param gc the canvas hegyi@1888: BrokenEdge(Gnome::Canvas::Group & g, Edge _edge, GraphDisplayerCanvas & gc); hegyi@1888: hegyi@1888: ///Destructor of broken edge class hegyi@1888: hegyi@1888: ///Frees up hegyi@1888: ///reserved memory hegyi@1819: ~BrokenEdge(); hegyi@1888: hegyi@1888: ///The function that draws the edge based on collected data ladanyi@1860: void draw(); hegyi@1819: }; hegyi@1888: hegyi@1888: ///Type of canvas, on which the graph is drawn ladanyi@1442: typedef Gnome::Canvas::CanvasAA Parent; ladanyi@1442: ladanyi@1442: public: hegyi@1888: ///Constructor hegyi@1888: hegyi@1888: ///\param nbt the tab of the window, in which the graph is displayed hegyi@1888: GraphDisplayerCanvas(NoteBookTab & nbt); hegyi@1888: hegyi@1888: ///destructor of the class ladanyi@1442: virtual ~GraphDisplayerCanvas(); ladanyi@1442: hegyi@1888: ///Changes the width of edge(s) according to the given map. hegyi@1888: hegyi@1888: ///\param mapname is the name of the map which contains the values to be set hegyi@1888: ///\param edge if it is given, only the width of the given edge will be set, instead of all of them. hegyi@1888: int changeEdgeWidth (std::string mapname, Edge edge=INVALID); hegyi@1888: hegyi@1888: ///Resets width of edge(s) to the default value hegyi@1888: hegyi@1888: ///\param edge if it is given, only the width of the hegyi@1888: ///given edge will be reset, instead of all of them. hegyi@1888: int resetEdgeWidth (Edge edge=INVALID); hegyi@1888: hegyi@1888: ///Changes the color of edge(s) according to the given map. hegyi@1888: ladanyi@1442: ///\param mapname is the name of the map which contains the new values hegyi@1888: ///\param edge if it is given, only the color of the given edge will be set, instead of all of them. hegyi@1888: int changeEdgeColor (std::string mapname, Edge edge=INVALID); ladanyi@1442: hegyi@1888: ///Resets color of edge(s) to the default value hegyi@1888: hegyi@1888: ///\param edge if it is given, only the color of the hegyi@1888: ///given edge will be reset, instead of all of them. hegyi@1888: int resetEdgeColor (Edge edge=INVALID); hegyi@1888: hegyi@1888: ///Changes the label of edge(s) according to the given map. hegyi@1888: ladanyi@1442: ///\param mapname is the name of the map which contains the new values hegyi@1888: ///\param edge if it is given, only the label of the given edge will be set, instead of all of them. hegyi@1888: int changeEdgeText (std::string mapname, Edge edge=INVALID); ladanyi@1442: hegyi@1888: ///Resets label of edge(s) to the default value hegyi@1888: hegyi@1888: ///\param edge if it is given, only the color of the hegyi@1888: ///given edge will be reset, instead of all of them. hegyi@1888: int resetEdgeText (Edge edge=INVALID); hegyi@1888: hegyi@1888: ///Changes the radius of node(s) according to the given map. hegyi@1888: ladanyi@1442: ///\param mapname is the name of the map which contains the new values hegyi@1888: ///\param node if it is given, only the radius of the given node will be set, instead of all of them. hegyi@1888: int changeNodeRadius (std::string mapname, Node node=INVALID); hegyi@1512: hegyi@1888: ///Resets radius of node(s) to the default value hegyi@1888: hegyi@1888: ///\param node if it is given, only the radius of the hegyi@1888: ///given node will be reset, instead of all of them. hegyi@1888: int resetNodeRadius (Node node=INVALID); hegyi@1888: hegyi@1888: ///Changes the color of node(s) according to the given map. hegyi@1888: hegyi@1512: ///\param mapname is the name of the map which contains the new values hegyi@1888: ///\param node if it is given, only the color of the given node will be set, instead of all of them. hegyi@1888: int changeNodeColor (std::string mapname, Node node=INVALID); hegyi@1512: hegyi@1888: ///Resets color of node(s) to the default value hegyi@1888: hegyi@1888: ///\param node if it is given, only the color of the hegyi@1888: ///given node will be reset, instead of all of them. hegyi@1888: int resetNodeColor (Node node=INVALID); hegyi@1888: hegyi@1888: ///Changes the label of node(s) according to the given map. hegyi@1888: hegyi@1512: ///\param mapname is the name of the map which contains the new values hegyi@1888: ///\param node if it is given, only the label of the given node will be set, instead of all of them. hegyi@1888: int changeNodeText (std::string mapname, Node node=INVALID); hegyi@1512: hegyi@1888: ///Resets label of node(s) to the default value ladanyi@1442: hegyi@1888: ///\param node if it is given, only the label of the hegyi@1888: ///given node will be reset, instead of all of them. hegyi@1888: int resetNodeText (Node node=INVALID); hegyi@1837: hegyi@1888: ///This function is called, when any of the displayed attributes have to be updated, or changed hegyi@1888: hegyi@1888: ///\param itisedge if true, edge property has to be changed, else node property hegyi@1888: ///\param prop the id of property that has to changed or updated hegyi@1888: void propertyChange(bool itisedge, int prop); hegyi@1888: hegyi@1888: ///updates the given property hegyi@1888: hegyi@1888: ///\param edge if it is not INVALID, only the property of the given edge will be updated, instead of all of them hegyi@1888: ///\param prop the property to update hegyi@1888: void propertyUpdate(Edge edge, int prop); hegyi@1888: hegyi@1888: ///updates the given property hegyi@1888: hegyi@1888: ///\param node if it is not INVALID, only the property of the given node will be updated, instead of all of them hegyi@1888: ///\param prop the property to update hegyi@1888: void propertyUpdate(Node node, int prop); hegyi@1888: hegyi@1888: ///updates all the property for the given edge hegyi@1837: void propertyUpdate(Edge); hegyi@1888: hegyi@1888: ///updates all the property for the given node hegyi@1837: void propertyUpdate(Node); hegyi@1837: ladanyi@1442: ///Callback for 'ViewZoomIn' action. ladanyi@1442: virtual void zoomIn(); ladanyi@1442: ///Callback for 'ViewZoomOut' action. ladanyi@1442: virtual void zoomOut(); ladanyi@1442: ///Callback for 'ViewZoomFit' action. ladanyi@1442: virtual void zoomFit(); ladanyi@1442: ///Callback for 'ViewZoom100' action. ladanyi@1442: virtual void zoom100(); ladanyi@1442: ///Sets the scroll region of the convas to the bounding box of the graph. ladanyi@1442: void updateScrollRegion(); ladanyi@1442: hegyi@1468: ///This function changes the tool in the graph-editor's hand hegyi@1468: void changeEditorialTool(int); hegyi@1468: ladanyi@1442: protected: ladanyi@1442: hegyi@1888: //maximizing, minimizing, restoring window, etc. ladanyi@1442: virtual bool on_expose_event(GdkEventExpose *); ladanyi@1442: ladanyi@1442: private: ladanyi@1442: ladanyi@1442: ///This function is responsible for the correct ladanyi@1442: ///reaction of any action happened in the territory ladanyi@1442: ///of the canvas hegyi@1505: ///DEPRECATED!!!! hegyi@1524: bool eventHandler(GdkEvent* e, Node n); ladanyi@1442: hegyi@1468: ///actual event handler hegyi@1468: /// hegyi@1468: ///Actual event handler should be stored, to be able to disconnect it and later reconnect it. hegyi@1468: sigc::connection actual_handler; hegyi@1468: hegyi@1468: ///event handler for the case when move-tool is active hegyi@1524: bool moveEventHandler(GdkEvent*); hegyi@1468: ///event handler for the case when create_node-tool is active hegyi@1524: bool createNodeEventHandler(GdkEvent*); hegyi@1468: ///event handler for the case when create_edge-tool is active hegyi@1524: bool createEdgeEventHandler(GdkEvent*); hegyi@1485: ///event handler for the case when eraser-tool is active hegyi@1524: bool eraserEventHandler(GdkEvent*); hegyi@1550: ///event handler for the case when edge map editor tool is active hegyi@1524: bool edgeMapEditEventHandler(GdkEvent*); hegyi@1550: ///event handler for the case when node map editor tool is active hegyi@1550: bool nodeMapEditEventHandler(GdkEvent*); hegyi@1485: hegyi@1501: public: hegyi@1505: ///Moves the text to new place hegyi@1524: void textReposition(xy); hegyi@1888: hegyi@1505: ///Activates an edge belonging to a BrokenEdge hegyi@1888: hegyi@1579: ///After we have activated an edge this way, hegyi@1579: ///the GDC object will know, which edge is under forming hegyi@1888: ///therefore it can redraw the necessary elements on the canvas, hegyi@1579: ///for example the text belonging to the \ref BrokenEdge can be hegyi@1579: ///redrawn (\ref textReposition). hegyi@1524: void toggleEdgeActivity(BrokenEdge*, bool); hegyi@1505: hegyi@1505: public: hegyi@1888: hegyi@1888: ///Returns the actual tool in hand hegyi@1524: int getActualTool(); hegyi@1501: hegyi@1888: ///draws the graph hegyi@1888: hegyi@1888: ///Called when opening a file. ladanyi@1606: void drawGraph(); hegyi@1888: hegyi@1888: ///Clears the canvas hegyi@1888: hegyi@1888: ///It achieves this by deleting all data hegyi@1888: ///structure used to help handle the displayed graph. ladanyi@1606: void clear(); ladanyi@1606: hegyi@1585: ///creates a new Nodemap hegyi@1888: hegyi@1888: ///\param init initial value of the map hegyi@1888: ///\param mapname name of new map hegyi@1888: int addNewNodeMap(double init,std::string mapname); hegyi@1585: ///creates a new Edgemap hegyi@1888: hegyi@1888: ///\param init initial value of the map hegyi@1888: ///\param mapname name of new map hegyi@1888: int addNewEdgeMap(double init,std::string mapname); hegyi@1585: hegyi@1501: private: hegyi@1486: ///Deletes the given element. alpar@1643: void deleteItem(Node); hegyi@1486: ///Deletes the given element. alpar@1643: void deleteItem(Edge); hegyi@1468: hegyi@1501: private: hegyi@1501: ladanyi@1442: ///Map of nodes of graph ladanyi@1442: Graph::NodeMap nodesmap; ladanyi@1442: ladanyi@1442: ///Map of edges of graph hegyi@1499: Graph::EdgeMap edgesmap; ladanyi@1442: ladanyi@1442: ///Map of texts to write on edges ladanyi@1442: Graph::EdgeMap edgetextmap; ladanyi@1442: hegyi@1512: ///Map of texts to write on nodes hegyi@1512: Graph::NodeMap nodetextmap; hegyi@1512: ladanyi@1442: ///Group of graphical elements of displayed_graph ladanyi@1442: Gnome::Canvas::Group displayed_graph; ladanyi@1442: hegyi@1814: private: ladanyi@1442: ///Indicates whether the button of mouse is pressed or not hegyi@1500: int isbutton; ladanyi@1442: hegyi@1501: ///Stores the actual tool in hand hegyi@1501: int actual_tool; hegyi@1501: ladanyi@1442: ///At this location was the mousebutton pressed. ladanyi@1442: ///It helps to calculate the distance of dragging. ladanyi@1442: double clicked_x, clicked_y; ladanyi@1442: ladanyi@1442: ///Remembers which Gnome::Canvas::Item was pressed. hegyi@1888: hegyi@1888: ///this variable is needed, to work on it after selection hegyi@1888: Gnome::Canvas::Item * active_item; hegyi@1888: hegyi@1888: ///Remembers which Gnome::Canvas::Item was pressed. hegyi@1888: hegyi@1888: ///this variable is used at edge creation, it will hegyi@1888: ///be the secondly selected node. No local variable hegyi@1888: ///can be used for this purpose inside the function, hegyi@1888: ///because the node selected by button press, and hegyi@1888: ///the edge is created by button release. Both of hegyi@1888: ///them is different function call. hegyi@1888: Gnome::Canvas::Item * target_item; hegyi@1888: hegyi@1888: ///selected node (for any editing) alpar@1643: Node active_node; hegyi@1888: hegyi@1888: ///selected edge (for any editing) alpar@1643: Edge active_edge; hegyi@1888: hegyi@1888: ///the edge that is selected by clicking on the red arrow in the middle of it hegyi@1888: hegyi@1888: ///This edge is stored only for the purpose of reshape it. hegyi@1888: ///That is why it is selected in a different manner. alpar@1643: Edge forming_edge; hegyi@1579: hegyi@1888: ///Map displayed by label can be edited. hegyi@1888: std::string nodemap_to_edit; hegyi@1888: hegyi@1888: ///Map displayed by label can be edited. hegyi@1888: std::string edgemap_to_edit; ladanyi@1442: ladanyi@1442: static const int zoom_step = 5; hegyi@1499: hegyi@1814: private: hegyi@1814: hegyi@1888: ///reference to the container, in which the canvas is hegyi@1849: NoteBookTab & mytab; hegyi@1614: alpar@1936: XY calcArrowPos(XY, XY, XY, XY, bool); ladanyi@1442: }; ladanyi@1442: ladanyi@1442: #endif //GRAPH_DISPLAYER_CANVAS_H