001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
004    package graphlab.graph.graph;
005    
006    import graphlab.graph.atributeset.EdgeAttrSet;
007    import graphlab.graph.event.EdgeModelListener;
008    import graphlab.graph.old.Arrow;
009    import graphlab.graph.old.ArrowHandler;
010    import graphlab.graph.old.GStroke;
011    import graphlab.library.BaseEdge;
012    import graphlab.library.BaseEdgeProperties;
013    import graphlab.platform.attribute.AttributeSet;
014    
015    import java.awt.geom.Line2D;
016    import java.util.HashMap;
017    import java.util.Map;
018    
019    /**
020     * User: azin azadi,roozbeh ebrahimi
021     */
022    public class EdgeModel extends BaseEdge<VertexModel> {
023    
024        public EdgeModelListener view;
025        private boolean isSelected = false;
026        private boolean showWeight = true;
027        private GStroke stroke;
028    
029        private Arrow arrow = ArrowHandler.defaultArrow;
030    
031        /**
032         * the location of the lable relative to the center of the edge
033         */
034        private GraphPoint labelLocation = new GraphPoint(0, 0);
035    
036        /**
037         * it's a straight line between source and target vertices
038         */
039        public Line2D.Double line = new Line2D.Double();
040    
041        public GraphPoint curveControlPoint = new GraphPoint(0, 0);
042    
043        /**
044         * the text that is showing as the label of the edge on screen
045         */
046        String text = "";
047    
048        /**
049         * This is a place to put custom attributes in the vertex, It will be shown in property editor and editable
050         */
051        private HashMap<String, Object> userDefinedAttributes = null;
052    
053        /**
054         * these attributed will be added to each vertice's userDefinedAttributes on constructing time.
055         */
056        private static HashMap<String, Object> globalUserDefinedAttributes = null;
057    
058    
059        /**
060         * sets and stores a user defined attribute for the vertex. here you can put any attribute you like that are not available
061         * in the standard attributes. your attributes will be editable in property editor part of GUI.
062         * Use this method carefully. user defined attributes are stored in HashMap and bad use of them will cause memory leak in large graphs
063         *
064         * @param name
065         * @param value
066         */
067        public void setUserDefinedAttribute(String name, Object value) {
068            if (userDefinedAttributes == null) {
069                userDefinedAttributes = new HashMap<String, Object>();
070            }
071            userDefinedAttributes.put(name, value);
072        }
073    
074        /**
075         * returns the specified user defined attribute, or null if it does not exists.
076         *
077         * @param name
078         * @return
079         */
080        public <t> t getUserDefinedAttribute(String name) {
081            if (userDefinedAttributes == null)
082                return null;
083            return (t) userDefinedAttributes.get(name);
084        }
085    
086        /**
087         * removes the given attribute from the list of user defined attributes
088         *
089         * @param name
090         */
091        public void removeUserDefinedAttribute(String name) {
092            userDefinedAttributes.remove(name);
093            if (userDefinedAttributes.size() == 0)
094                userDefinedAttributes = null;
095        }
096    
097        /**
098         * @return a HashMap containing all user defined attributes.
099         */
100        public HashMap<String, Object> getUserDefinedAttributes() {
101            return userDefinedAttributes;
102        }
103    
104    
105        /**
106         * sets and stores a global user defined attribute for the vertex. this attributes will be added to each vertex on
107         * constructing time using setUserDefinedAttribute method.
108         * <p/>
109         * note that this method only affects the afterward created vertices, and current vertices will not affected by this method.
110         */
111        public static void addGlobalUserDefinedAttribute(String name, Object defaultvalue) {
112            if (globalUserDefinedAttributes == null) {
113                globalUserDefinedAttributes = new HashMap<String, Object>();
114            }
115            globalUserDefinedAttributes.put(name, defaultvalue);
116        }
117    
118        /**
119         * @see VertexModel#addGlobalUserDefinedAttribute
120         */
121        public static void removeGlobalUserDefinedAttribute(String name) {
122            globalUserDefinedAttributes.remove(name);
123            if (globalUserDefinedAttributes.size() == 0)
124                globalUserDefinedAttributes = null;
125        }
126    
127        {
128            //default constructor
129            if (globalUserDefinedAttributes != null) {
130                userDefinedAttributes = new HashMap<String, Object>();
131                userDefinedAttributes.putAll(globalUserDefinedAttributes);
132            }
133        }
134    
135        /**
136         * This is the copy constructor method for the Edge Model
137         *
138         * @param vm1
139         * @param vm2
140         * @return
141         */
142        public EdgeModel getCopy(VertexModel vm1, VertexModel vm2) {
143            return new EdgeModel(this, vm1, vm2);
144        }
145    
146        /**
147         * copy constructor
148         * creates a copy (clone) of edge,
149         * the source and target of edge will be source and target parameters
150         * other properties of edge will be copied from edge parameter
151         *
152         * @param edge
153         */
154        public EdgeModel(EdgeModel edge, VertexModel source, VertexModel target) {
155            super(source, target);
156            //copies all attributes from second edge to first edge
157            AttributeSet a = new EdgeAttrSet(edge);
158            AttributeSet b = new EdgeAttrSet(this);
159            Map<String, Object> map = a.getAttrs();
160            for (String name : map.keySet()) {
161                b.put(name, map.get(name));
162            }
163            updateText();
164            showWeight = GraphModel.showEdgeWeights;
165            stroke = FastRenderer.defaultStroke;
166        }
167    
168        public EdgeModel(VertexModel v1, VertexModel v2) {
169            super(v1, v2);
170            showWeight = GraphModel.showEdgeWeights;
171            stroke = FastRenderer.defaultStroke;
172        }
173    
174        GStroke last;
175    
176        public void setMark(boolean m) {
177            super.setMark(m);
178            repaintView();
179        }
180    
181        private void repaintView() {
182            if (view != null) {
183                view.repaint(this);
184            }
185        }
186    
187        public void setStroke(GStroke stroke) {
188            this.stroke = stroke;
189            repaintView();
190        }
191    
192        public GStroke getStroke() {
193            return stroke;
194        }
195    
196        public void setWeight(int weight) {
197            super.setWeight(weight);
198            updateText();
199            repaintView();
200        }
201    
202        public void setProp(BaseEdgeProperties prop) {
203            super.setProp(prop);
204            repaintView();
205        }
206    
207        public void setColor(int color) {
208            super.setColor(color);
209            repaintView();
210        }
211    
212        public Arrow getArrow() {
213            return arrow;
214        }
215    
216        public void setArrow(Arrow a) {
217            this.arrow = a;
218            repaintView();
219        }
220    
221        public void setEdgeModelListener(EdgeModelListener listener) {
222            this.view = listener;
223        }
224    
225        /**
226         * Returns the getAngle, in radians, of the edge from the positive
227         * x-axis, where the source vertex marks the origin of the edge. The
228         * getAngle will be in the range of 0 to 2<em>pi</em> and will increase
229         * counter-clockwise around the origin.
230         * (this method taked from GraphMaker Project)
231         *
232         * @return getAngle in radians from positive x-axis.
233         */
234        public double getAngle() {
235            // Subtract y coordinates in reverse order from normal
236            // as the screen coordinate system is flipped along the
237            // x-axis from the Cartesian coordinate system.
238            GraphPoint sourceLoc = source.getLocation();
239            GraphPoint targetLoc = target.getLocation();
240            double angle = Math.atan2(sourceLoc.y + source.getCenter().y - targetLoc.y - target.getCenter().y,
241                    sourceLoc.x + source.getCenter().x - targetLoc.x - target.getCenter().x);
242            if (angle < 0) {
243                // atan2 returns getAngle in phase -pi to pi, which means
244                // we have to convert the answer into 0 to 2pi range.
245                angle += 2 * Math.PI;
246            }
247            return angle;
248        } // getAngle
249    
250        public String toString() {
251            return source + "->" + target;
252        }
253    
254        public boolean isSelected() {
255            return isSelected;
256        }
257    
258        public void setSelected(boolean selected) {
259            isSelected = selected;
260            repaintView();
261        }
262    
263        public String getId() {
264            //todo: omid: BaseEdge doesn't have id!
265            return source.getId() + "" + target.getId();
266        }
267    
268    
269        //---------------    + Curved Edge            --------------------
270        /**
271         * @return return the curve control point of this edge, relative to the center of the edge
272         *         the abstract position can be give by: (src.x + trg.x) / 2 + ctrlPnt.x  , also for y
273         */
274        public GraphPoint getCurveControlPoint() {
275            if (curveControlPoint == null) {
276                curveControlPoint = new GraphPoint(0, 0);
277            }
278            return curveControlPoint;
279        }
280    
281        public void setCurveControlPoint(GraphPoint controlPoint) {
282            this.curveControlPoint = controlPoint;
283            repaintView();
284        }
285        //---------------    - Curved Edge            --------------------
286    
287        //--------------        +text operation            ---------------
288        String label;
289    
290        public void setLabel(String label) {
291            this.label = label;
292            updateText();
293        }
294    
295        public String getLabel() {
296            return label;
297        }
298    
299        private void updateText() {
300            String _label;
301            if (!isShowWeight())
302                _label = label;
303            else if (isShowWeight())
304                _label = String.valueOf(super.getWeight());
305            else
306                _label = label + "," + String.valueOf(super.getWeight());
307            this.text = _label;
308            repaintView();
309        }
310        //--------------        -text operation            ---------------
311    
312    
313        public boolean isShowWeight() {
314            return showWeight;
315        }
316    
317        public void setShowWeight(boolean showWeight) {
318            this.showWeight = showWeight;
319            updateText();
320            repaintView();
321        }
322    
323        public void updateBounds() {
324            repaintView();
325        }
326    
327        public void setLabelLocation(GraphPoint graphPoint) {
328            this.labelLocation = graphPoint;
329            repaintView();
330        }
331    
332        public GraphPoint getLabelLocation() {
333            return labelLocation;
334        }
335    
336    }