hegyi@1: /* -*- C++ -*- hegyi@1: * hegyi@1: * This file is a part of LEMON, a generic C++ optimization library hegyi@1: * hegyi@1: * Copyright (C) 2003-2006 hegyi@1: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport hegyi@1: * (Egervary Research Group on Combinatorial Optimization, EGRES). hegyi@1: * hegyi@1: * Permission to use, modify and distribute this software is granted hegyi@1: * provided that this copyright notice appears in all copies. For hegyi@1: * precise terms see the accompanying LICENSE file. hegyi@1: * hegyi@1: * This software is provided "AS IS" with no warranty of any kind, hegyi@1: * express or implied, and with no claim as to its suitability for any hegyi@1: * purpose. hegyi@1: * hegyi@1: */ hegyi@1: hegyi@1: #ifndef GRAPH_DISPLAYER_CANVAS_H hegyi@1: #define GRAPH_DISPLAYER_CANVAS_H hegyi@1: hegyi@1: class NoteBookTab; hegyi@1: hegyi@1: #include "all_include.h" hegyi@1: #include hegyi@1: #include hegyi@1: hegyi@1: ///This class is the canvas, on which the digraph can be drawn. hegyi@1: class DigraphDisplayerCanvas : public Gnome::Canvas::CanvasAA hegyi@1: { hegyi@1: friend class BrokenArc; hegyi@1: friend class LoopArc; hegyi@1: hegyi@1: class ArcBase : public Gnome::Canvas::Group hegyi@1: { hegyi@1: protected: hegyi@1: ///Reference to the canvas, on which the digraph is drawn. hegyi@1: hegyi@1: ///It is needed, because some datas needed from hegyi@1: ///digraph can be accessed by this or should be sent hegyi@1: ///as parameter, but it would be complicated hegyi@1: DigraphDisplayerCanvas& canvas; hegyi@1: hegyi@1: ///The arc that the class displays. hegyi@1: hegyi@1: ///It is needed, because some datas needed from hegyi@1: ///digraph can be accessed by this or should be sent hegyi@1: ///as parameter, but it would be complicated hegyi@1: Arc arc; hegyi@1: hegyi@1: Gnome::Canvas::Polygon arrow; hegyi@1: hegyi@1: void drawArrow(XY); hegyi@1: public: hegyi@1: ArcBase(Gnome::Canvas::Group&, Arc, DigraphDisplayerCanvas&); hegyi@1: virtual ~ArcBase(); hegyi@1: virtual void draw() = 0; hegyi@1: virtual void setLineWidth(int) = 0; hegyi@1: virtual void setFillColor(Gdk::Color) = 0; hegyi@1: virtual Gnome::Canvas::Item * getLine() = 0; hegyi@1: }; hegyi@1: hegyi@1: ///Arc displayer class hegyi@1: hegyi@1: ///This class is responsible for displaying arcs in digraph. hegyi@1: ///The displayed arc is broken in the middle. The hegyi@1: ///aim of this is to be able to indicate direction of arcs hegyi@1: ///and to be able to display more then one arcs between the hegyi@1: ///same source and target hegyi@1: class BrokenArc : public ArcBase hegyi@1: { hegyi@1: private: hegyi@1: Gnome::Canvas::Line line; hegyi@1: hegyi@1: ///Indicates whether the button of mouse is pressed or not at the moment. hegyi@1: bool isbutton; hegyi@1: hegyi@1: ///At this location was the mousebutton pressed. Horizontal component. hegyi@1: hegyi@1: ///It helps to calculate the hegyi@1: ///distance of dragging. hegyi@1: double clicked_x; hegyi@1: hegyi@1: ///At this location was the mousebutton pressed. Vertical component. hegyi@1: hegyi@1: ///It helps to calculate the hegyi@1: ///distance of dragging. hegyi@1: double clicked_y; hegyi@1: hegyi@1: ///event handler for forming broken arcs hegyi@1: hegyi@1: ///\param event the hegyi@1: ///event to handle hegyi@1: bool arcFormerEventHandler(GdkEvent* event); hegyi@1: hegyi@1: public: hegyi@1: ///Constructor of broken arc class. hegyi@1: hegyi@1: ///\param g the group to which the arc belongs hegyi@1: ///\param _arc the represented arc hegyi@1: ///\param gc the canvas hegyi@1: BrokenArc(Gnome::Canvas::Group&, Arc, DigraphDisplayerCanvas&); hegyi@1: hegyi@1: ///Destructor of broken arc class hegyi@1: hegyi@1: ///Frees up hegyi@1: ///reserved memory hegyi@1: ~BrokenArc(); hegyi@1: hegyi@1: ///The function that draws the arc based on collected data hegyi@1: void draw(); hegyi@1: hegyi@1: void setLineWidth(int); hegyi@1: void setFillColor(Gdk::Color); hegyi@1: hegyi@1: Gnome::Canvas::Item * getLine() { return (Gnome::Canvas::Item *)(&line); }; hegyi@1: }; hegyi@1: hegyi@1: class LoopArc : public ArcBase hegyi@1: { hegyi@1: private: hegyi@1: Gnome::Canvas::Ellipse line; hegyi@1: bool arcFormerEventHandler(GdkEvent* e); hegyi@1: bool isbutton; hegyi@1: public: hegyi@1: LoopArc(Gnome::Canvas::Group&, Arc, DigraphDisplayerCanvas&); hegyi@1: ~LoopArc(); hegyi@1: void draw(); hegyi@1: void setLineWidth(int); hegyi@1: void setFillColor(Gdk::Color); hegyi@1: Gnome::Canvas::Item * getLine() { return (Gnome::Canvas::Item *)(&line); }; hegyi@1: }; hegyi@1: hegyi@1: ///Type of canvas, on which the digraph is drawn hegyi@1: typedef Gnome::Canvas::CanvasAA Parent; hegyi@1: hegyi@1: public: hegyi@1: ///Constructor hegyi@1: hegyi@1: ///\param nbt the tab of the window, in which the digraph is displayed hegyi@1: DigraphDisplayerCanvas(NoteBookTab & nbt); hegyi@1: hegyi@1: ///destructor of the class hegyi@1: virtual ~DigraphDisplayerCanvas(); hegyi@1: hegyi@1: ///Returns a color of the rainbow based on a map value and the min and max value of the given map hegyi@1: hegyi@1: ///min and max is purple, between them there is a linear assign hegyi@1: Gdk::Color rainbowColorCounter(double, double, double); hegyi@1: hegyi@1: ///Changes the width of arc(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the values to be set hegyi@1: ///\param arc if it is given, only the width of the given arc will be set, instead of all of them. hegyi@1: int changeArcWidth (std::string mapname, Arc arc=INVALID); hegyi@1: hegyi@1: ///Resets width of arc(s) to the default value hegyi@1: hegyi@1: ///\param arc if it is given, only the width of the hegyi@1: ///given arc will be reset, instead of all of them. hegyi@1: int resetArcWidth (Arc arc=INVALID); hegyi@1: hegyi@1: ///Changes the color of arc(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the new values hegyi@1: ///\param arc if it is given, only the color of the given arc will be set, instead of all of them. hegyi@1: int changeArcColor (std::string mapname, Arc arc=INVALID); hegyi@1: hegyi@1: ///Resets color of arc(s) to the default value hegyi@1: hegyi@1: ///\param arc if it is given, only the color of the hegyi@1: ///given arc will be reset, instead of all of them. hegyi@1: int resetArcColor (Arc arc=INVALID); hegyi@1: hegyi@1: ///Changes the label of arc(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the new values hegyi@1: ///\param arc if it is given, only the label of the given arc will be set, instead of all of them. hegyi@1: int changeArcText (std::string mapname, Arc arc=INVALID); hegyi@1: hegyi@1: ///Resets label of arc(s) to the default value hegyi@1: hegyi@1: ///\param arc if it is given, only the color of the hegyi@1: ///given arc will be reset, instead of all of them. hegyi@1: int resetArcText (Arc arc=INVALID); hegyi@1: hegyi@1: ///Changes the radius of node(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the new values hegyi@1: ///\param node if it is given, only the radius of the given node will be set, instead of all of them. hegyi@1: int changeNodeRadius (std::string mapname, Node node=INVALID); hegyi@1: hegyi@1: ///Resets radius of node(s) to the default value hegyi@1: hegyi@1: ///\param node if it is given, only the radius of the hegyi@1: ///given node will be reset, instead of all of them. hegyi@1: int resetNodeRadius (Node node=INVALID); hegyi@1: hegyi@1: ///Changes the color of node(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the new values hegyi@1: ///\param node if it is given, only the color of the given node will be set, instead of all of them. hegyi@1: int changeNodeColor (std::string mapname, Node node=INVALID); hegyi@1: hegyi@1: ///Resets color of node(s) to the default value hegyi@1: hegyi@1: ///\param node if it is given, only the color of the hegyi@1: ///given node will be reset, instead of all of them. hegyi@1: int resetNodeColor (Node node=INVALID); hegyi@1: hegyi@1: ///Changes the label of node(s) according to the given map. hegyi@1: hegyi@1: ///\param mapname is the name of the map which contains the new values hegyi@1: ///\param node if it is given, only the label of the given node will be set, instead of all of them. hegyi@1: int changeNodeText (std::string mapname, Node node=INVALID); hegyi@1: hegyi@1: ///Resets label of node(s) to the default value hegyi@1: hegyi@1: ///\param node if it is given, only the label of the hegyi@1: ///given node will be reset, instead of all of them. hegyi@1: int resetNodeText (Node node=INVALID); hegyi@1: hegyi@1: ///This function is called, when any of the displayed attributes have to be updated, or changed hegyi@1: hegyi@1: ///\param itisarc if true, arc property has to be changed, else node property hegyi@1: ///\param prop the id of property that has to changed or updated hegyi@1: void propertyChange(bool itisarc, int prop); hegyi@1: hegyi@1: ///updates the given property hegyi@1: hegyi@1: ///\param arc if it is not INVALID, only the property of the given arc will be updated, instead of all of them hegyi@1: ///\param prop the property to update hegyi@1: void propertyUpdate(Arc arc, int prop); hegyi@1: hegyi@1: ///updates the given property hegyi@1: hegyi@1: ///\param node if it is not INVALID, only the property of the given node will be updated, instead of all of them hegyi@1: ///\param prop the property to update hegyi@1: void propertyUpdate(Node node, int prop); hegyi@1: hegyi@1: ///updates all the property for the given arc hegyi@1: void propertyUpdate(Arc); hegyi@1: hegyi@1: ///updates all the property for the given node hegyi@1: void propertyUpdate(Node); hegyi@1: hegyi@1: ///Callback for 'ViewZoomIn' action. hegyi@1: virtual void zoomIn(); hegyi@1: ///Callback for 'ViewZoomOut' action. hegyi@1: virtual void zoomOut(); hegyi@1: ///Callback for 'ViewZoomFit' action. hegyi@1: virtual void zoomFit(); hegyi@1: ///Callback for 'ViewZoom100' action. hegyi@1: virtual void zoom100(); hegyi@1: ///Sets the scroll region of the convas to the bounding box of the digraph. hegyi@1: void updateScrollRegion(); hegyi@1: hegyi@1: ///This function changes the tool in the digraph-editor's hand hegyi@1: void changeEditorialTool(int); hegyi@1: hegyi@1: protected: hegyi@1: hegyi@1: //maximizing, minimizing, restoring window, etc. hegyi@1: virtual bool on_expose_event(GdkEventExpose *); hegyi@1: hegyi@1: private: hegyi@1: hegyi@1: ///This function is responsible for the correct hegyi@1: ///reaction of any action happened in the territory hegyi@1: ///of the canvas hegyi@1: ///DEPRECATED!!!! hegyi@1: bool eventHandler(GdkEvent* e, Node n); hegyi@1: hegyi@1: ///actual event handler hegyi@1: /// hegyi@1: ///Actual event handler should be stored, to be able to disconnect it and later reconnect it. hegyi@1: sigc::connection actual_handler; hegyi@1: hegyi@1: ///event handler for the case when move-tool is active hegyi@1: bool moveEventHandler(GdkEvent*); hegyi@1: ///event handler for the case when create_node-tool is active hegyi@1: bool createNodeEventHandler(GdkEvent*); hegyi@1: ///event handler for the case when create_arc-tool is active hegyi@1: bool createArcEventHandler(GdkEvent*); hegyi@1: ///event handler for the case when eraser-tool is active hegyi@1: bool eraserEventHandler(GdkEvent*); hegyi@1: ///event handler for the case when map editor tool is active hegyi@1: bool mapEditEventHandler(GdkEvent*); hegyi@1: ///event handler for the case when user scrolls the mouse hegyi@1: bool scrollEventHandler(GdkEvent*); hegyi@1: hegyi@1: private: hegyi@1: ///moves node according to the given parameters hegyi@1: void moveNode(double, double, Gnome::Canvas::Item * item=NULL, Node node=INVALID); hegyi@1: hegyi@1: public: hegyi@1: ///Moves the text to new place hegyi@1: void textReposition(XY); hegyi@1: hegyi@1: ///Activates an arc belonging to an ArcBase hegyi@1: hegyi@1: ///After we have activated an arc this way, hegyi@1: ///the GDC object will know, which arc is under forming hegyi@1: ///therefore it can redraw the necessary elements on the canvas, hegyi@1: ///for example the text belonging to the \ref ArcBase can be hegyi@1: ///redrawn (\ref textReposition). hegyi@1: void toggleArcActivity(ArcBase*, bool); hegyi@1: hegyi@1: public: hegyi@1: hegyi@1: ///Returns the actual tool in hand hegyi@1: int getActualTool(); hegyi@1: hegyi@1: ///Sets node representation settings hegyi@1: void setView(bool, bool, double, double); hegyi@1: hegyi@1: ///Gets node representation settings hegyi@1: void getView(bool &, bool &, double&, double&); hegyi@1: hegyi@1: ///draws the digraph hegyi@1: hegyi@1: ///Called when opening a file. hegyi@1: void drawDigraph(); hegyi@1: hegyi@1: ///Clears the canvas hegyi@1: hegyi@1: ///It achieves this by deleting all data hegyi@1: ///structure used to help handle the displayed digraph. hegyi@1: void clear(); hegyi@1: hegyi@1: ///creates a new Nodemap hegyi@1: hegyi@1: ///\param init initial value of the map hegyi@1: ///\param mapname name of new map hegyi@1: int addNewNodeMap(double init,std::string mapname); hegyi@1: ///creates a new Arcmap hegyi@1: hegyi@1: ///\param init initial value of the map hegyi@1: ///\param mapname name of new map hegyi@1: int addNewArcMap(double init,std::string mapname); hegyi@1: hegyi@1: void reDesignDigraph(); hegyi@1: hegyi@1: ///Show whether the digraph is already drawn. hegyi@1: bool is_drawn; hegyi@1: hegyi@1: private: hegyi@1: ///Deletes the given element. hegyi@1: void deleteItem(Node); hegyi@1: ///Deletes the given element. hegyi@1: void deleteItem(Arc); hegyi@1: hegyi@1: private: hegyi@1: hegyi@1: ///Map of nodes of digraph hegyi@1: Digraph::NodeMap nodesmap; hegyi@1: hegyi@1: ///Map of arcs of digraph hegyi@1: Digraph::ArcMap arcsmap; hegyi@1: hegyi@1: ///Map of texts to write on arcs hegyi@1: Digraph::ArcMap arctextmap; hegyi@1: hegyi@1: ///Map of texts to write on nodes hegyi@1: Digraph::NodeMap nodetextmap; hegyi@1: hegyi@1: ///Group of digraphical elements of displayed_graph hegyi@1: Gnome::Canvas::Group displayed_graph; hegyi@1: hegyi@1: private: hegyi@1: ///Indicates whether the button of mouse is pressed or not hegyi@1: int isbutton; hegyi@1: hegyi@1: ///Stores the actual tool in hand hegyi@1: int actual_tool; hegyi@1: hegyi@1: ///At this location was the mousebutton pressed. hegyi@1: ///It helps to calculate the distance of dragging. hegyi@1: double clicked_x, clicked_y; hegyi@1: hegyi@1: ///Remembers which Gnome::Canvas::Item was pressed. hegyi@1: hegyi@1: ///this variable is needed, to work on it after selection hegyi@1: Gnome::Canvas::Item * active_item; hegyi@1: hegyi@1: ///Remembers which Gnome::Canvas::Item was pressed. hegyi@1: hegyi@1: ///this variable is used at arc creation, it will hegyi@1: ///be the secondly selected node. No local variable hegyi@1: ///can be used for this purpose inside the function, hegyi@1: ///because the node selected by button press, and hegyi@1: ///the arc is created by button release. Both of hegyi@1: ///them is different function call. hegyi@1: Gnome::Canvas::Item * target_item; hegyi@1: hegyi@1: ///selected node (for any editing) hegyi@1: Node active_node; hegyi@1: hegyi@1: ///selected arc (for any editing) hegyi@1: Arc active_arc; hegyi@1: hegyi@1: ///the arc that is selected by clicking on the red arrow in the middle of it hegyi@1: hegyi@1: ///This arc is stored only for the purpose of reshape it. hegyi@1: ///That is why it is selected in a different manner. hegyi@1: Arc forming_arc; hegyi@1: hegyi@1: ///Map displayed by label can be edited. hegyi@1: std::string nodemap_to_edit; hegyi@1: hegyi@1: ///Map displayed by label can be edited. hegyi@1: std::string arcmap_to_edit; hegyi@1: hegyi@1: static const int zoom_step = 5; hegyi@1: hegyi@1: ///Is node radius autoscaled hegyi@1: bool autoscale; hegyi@1: hegyi@1: ///Should we track zoomfactor changes hegyi@1: bool zoomtrack; hegyi@1: hegyi@1: ///to store the zoom factor when it was "fixed" hegyi@1: double fixed_zoom_factor; hegyi@1: hegyi@1: ///Node radius size hegyi@1: double radius_size; hegyi@1: hegyi@1: ///Arc width hegyi@1: double arc_width; hegyi@1: hegyi@1: ///Was redesign run on this digraph already? hegyi@1: /// hegyi@1: ///If not, the layout will be modified randomly hegyi@1: ///to avoid frozen layout because of wrong hegyi@1: ///initial state hegyi@1: bool was_redesigned; hegyi@1: hegyi@1: private: hegyi@1: hegyi@1: ///reference to the container, in which the canvas is hegyi@1: NoteBookTab & mytab; hegyi@1: hegyi@1: XY calcArrowPos(XY, XY, XY, XY, int); hegyi@1: hegyi@1: bool background_set; hegyi@1: Glib::RefPtr refBackground; hegyi@1: Gnome::Canvas::Pixbuf *background; hegyi@1: public: hegyi@1: void setBackground(); hegyi@1: }; hegyi@1: hegyi@1: #endif //GRAPH_DISPLAYER_CANVAS_H