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.plugins.main.core.actions;
005    
006    import graphlab.graph.atributeset.*;
007    import graphlab.graph.event.EdgeEvent;
008    import graphlab.graph.event.GraphSelectData;
009    import graphlab.graph.event.VertexEvent;
010    import graphlab.graph.graph.EdgeModel;
011    import graphlab.graph.graph.GraphModel;
012    import graphlab.graph.graph.VertexModel;
013    import graphlab.graph.old.GStroke;
014    import static graphlab.graph.old.GStroke.*;
015    import graphlab.platform.attribute.*;
016    import graphlab.platform.core.AbstractAction;
017    import graphlab.platform.core.BlackBoard;
018    import graphlab.plugins.main.select.Select;
019    import graphlab.plugins.main.select.SelectPluginMethods;
020    import graphlab.plugins.main.ui.GStrokeEditor;
021    import graphlab.ui.AttributeSetView;
022    import graphlab.ui.PortableNotifiableAttributeSetImpl;
023    import graphlab.ui.UIUtils;
024    import graphlab.ui.components.gpropertyeditor.GPropertyEditor;
025    
026    import java.util.HashSet;
027    
028    /**
029     * the left side property editor of graphlab gui
030     *
031     * @author Azin Azadi
032     */
033    public class GraphPropertyEditor extends AbstractAction implements AttributeListener {
034        public GPropertyEditor getPropertyEditor() {
035            return prosheet;
036        }
037    
038        private GPropertyEditor prosheet;
039    
040        public NotifiableAttributeSet NotifiableAttributeSet;
041    
042        public AttributeSetView viewer;
043    
044        VertexModel lastVertex;
045    
046        EdgeModel lastEdge;
047    
048        private TimeLimitedNotifiableAttrSet target;
049    
050        AttributeSetView edgeView = new AttributeSetView();
051    
052        AttributeSetView vertexView = new AttributeSetView();
053    
054        AttributeSetView graphView = new AttributeSetView();
055    
056        AttributeSetView selectView = new AttributeSetView();
057    
058        HashSet<String> hiddenVertexAttributes = new HashSet<String>();
059    
060        HashSet<String> hiddenEdgeAttributes = new HashSet<String>();
061    
062        PortableNotifiableAttributeSetImpl xx = new PortableNotifiableAttributeSetImpl();
063    
064        TimeLimitedNotifiableAttrSet selectionAttributes = new TimeLimitedNotifiableAttrSet(new AttributeSetImpl());
065    
066        SelectPluginMethods spm;
067    
068        /**
069         * constructor
070         *
071         * @param bb the blackboard of the action
072         */
073        public GraphPropertyEditor(BlackBoard bb) {
074            super(bb);
075            spm = new SelectPluginMethods(blackboard);
076            prosheet = new GPropertyEditor();
077            prosheet.setSize(150, 100);
078            UIUtils.setComponent(blackboard, "property editor", prosheet);
079            listen4Event(EdgeEvent.EVENT_KEY);
080            listen4Event(VertexEvent.EVENT_KEY);
081            listen4Event(Select.EVENT_KEY);
082            listen4Event(GraphSelectData.EVENT_KEY);
083    
084    //        graphView.setVisible(GraphAttrSet.CENTERX, false);
085    //        graphView.setVisible(GraphAttrSet.CENTERY, false);
086    //        graphView.setVisible(GraphAttrSet.DIRECTED, false);
087    //        graphView.setVisible(GraphAttrSet.ZOOM, false);
088            graphView.setIndex(GraphAttrSet.LABEL, 0);
089            graphView.setIndex(GraphAttrSet.DIRECTED, 1);
090            graphView.setIndex(GraphAttrSet.DRAW_VERTEX_LABELS, 5);
091            graphView.setIndex(GraphAttrSet.DRAW_EDGE_LABELS, 6);
092            graphView.setEditable(GraphAttrSet.DIRECTED, false);
093            graphView.setEditable(GraphAttrSet.LABEL, true);
094    
095    //        graphView.setIndex(EdgeAttrSet.SHOW_EDGE_LABELS, 3);
096    
097    //Storing Id in vertex is deprecated
098    //        vertexView.setVisible(VertexModel.ID, false);
099    //        vertexView.setVisible(VertexModel.XPOS, false);
100    //        vertexView.setVisible(VertexModel.YPOS, false);
101            vertexView.setIndex(VertexAttrSet.LABEL, 0);
102            vertexView.setIndex(VertexAttrSet.COLOR, 2);
103            vertexView.setIndex(VertexAttrSet.SHAPE, 4);
104            vertexView.setIndex(VertexAttrSet.BORDER, 6);
105            vertexView.setVisible(VertexAttrSet.SELECTED, false);
106            vertexView.setEditor(VertexAttrSet.BORDER, new GStrokeEditor() {
107                public Object[] getValues() {
108                    return new GStroke[]{
109                            GStroke.empty,
110                            simple,
111                            solid,
112                            strong,
113                            dashed,
114                            dotted,
115                            dashed_dotted,
116                            dashed_dotted_dotted,
117                            dashed_dashed_dotted
118                    };
119                }
120            });
121            vertexView.setEditor(VertexAttrSet.COLOR, new GMergedColorEditor(true));
122            vertexView.setrenderer(VertexAttrSet.COLOR, new GMergedColorRenderer(true));
123    
124    //        edgeView.setVisible(EdgeAttrSet.DIRECTED, false);
125    //        edgeView.setVisible(EdgeAttrSet.LABEL, false);
126            edgeView.setEditable(EdgeAttrSet.SOURCE, false);
127            edgeView.setEditable(EdgeAttrSet.TARGET, false);
128            edgeView.setIndex(EdgeAttrSet.LABEL, 0);
129            edgeView.setIndex(EdgeAttrSet.WEIGHT, 1);
130            edgeView.setIndex(EdgeAttrSet.ARROW, 4);
131            edgeView.setEditor(EdgeAttrSet.COLOR, new GMergedColorEditor(false));
132            edgeView.setrenderer(EdgeAttrSet.COLOR, new GMergedColorRenderer(false));
133    //        updateSelectView();
134    
135        }
136    
137    
138        private VertexModel lastVertex() {
139            VertexEvent x = blackboard.getData(VertexEvent.EVENT_KEY);
140            return (x == null ? null : x.v);
141        }
142    
143        private EdgeModel lastEdge() {
144            EdgeEvent x = blackboard.getData(EdgeEvent.EVENT_KEY);
145            return (x == null ? null : x.e);
146        }
147    
148        private GraphModel lastGraph() {
149            GraphSelectData x = blackboard.getData(GraphSelectData.EVENT_KEY);
150            return (x == null ? null : x.g);
151        }
152    
153        public void performAction(String eventName, Object value) {
154            prosheet = (GPropertyEditor) UIUtils.getComponent(blackboard,
155                    "property editor");
156            if (getTarget() != null)
157                if (eventName == Select.EVENT_KEY) {
158                    if (!spm.isSelectionEmpty()) {
159                        updatePropertyEditor_selected();
160    //                    viewer = selectView;
161                    } else {
162                        setTarget(new GraphNotifiableAttrSet(lastGraph()));
163                        viewer = graphView;
164                    }
165                }
166    //        if (eventName ==VertexEvent.name)) {
167    //            VertexEvent ve = blackboard.get(VertexEvent.name);
168    //            if (ve.eventType == VertexEvent.PRESSED) {
169    //                if (spm.isSelectionEmpty()) {
170    //                    setTarget(new VertexNotifiableAttrSet(lastVertex()));
171    //                    viewer = vertexView;
172    //                }
173    //            }
174    //        }
175    //        if (eventName ==EdgeEvent.name)) {
176    //            EdgeEvent ve = blackboard.get(EdgeEvent.name);
177    //            if (ve.eventType == EdgeEvent.PRESSED) {
178    //                if (spm.isSelectionEmpty()) {
179    //                    setTarget(new EdgeNotifiableAttrSet(lastEdge()));
180    //                    viewer = edgeView;
181    //                }
182    //            }
183    //        }
184            if (eventName == GraphSelectData.EVENT_KEY) {
185                setTarget(new GraphNotifiableAttrSet(lastGraph()));
186                viewer = graphView;
187            }
188            updateTarget();
189        }
190    
191        private void updateTarget() {
192            if (prosheet != null && getTarget() != null) {
193                xx.setView(viewer);
194                xx.setModel(getTarget());
195                prosheet.connect(xx);
196            }
197        }
198    
199        public void attributeUpdated(String name, Object oldVal, Object newVal) {
200            //occurs whenever one attribute in selection attribute changed by user
201            //note that the vertex and edge attributes are updates directly, not from here
202            if (!iChangedTheAttribute) {
203                String key = name.substring(1);     //the original name of attribute
204                if (name.startsWith("v")) { //it was a vertex attribute
205                    for (VertexModel v : spm.getSelectedVertices()) {
206                        VertexAttrSet _v = new VertexAttrSet(v);
207                        _v.put(key, newVal);
208                    }
209                }
210                if (name.startsWith("e")) { //it was an edge attribute
211                    for (EdgeModel e : spm.getSelectedEdges()) {
212                        EdgeAttrSet _e = new EdgeAttrSet(e);
213                        _e.put(key, newVal);
214    
215                    }
216                }
217            }
218        }
219    
220        boolean iChangedTheAttribute = false;
221    
222        private void updatePropertyEditor_selected() {
223            HashSet<VertexModel> selectedVertices = spm.getSelectedVertices();
224            HashSet<EdgeModel> selectedEdges = spm.getSelectedEdges();
225    
226            int numOfSelectedVertices = selectedVertices.size();
227            int numOfSelectedEdges = selectedEdges.size();
228    
229            //if there was only 1 selected vertex(edge) show the classic editor for it
230            if (numOfSelectedVertices + numOfSelectedEdges == 1) {
231                if (numOfSelectedVertices == 1) {
232                    setTarget(new VertexNotifiableAttrSet(selectedVertices.iterator().next()));
233                    viewer = vertexView;
234                } else {
235                    setTarget(new EdgeNotifiableAttrSet(selectedEdges.iterator().next()));
236                    viewer = edgeView;
237                }
238            } else {
239                viewer = selectView;
240    
241                iChangedTheAttribute = true;
242                TimeLimitedNotifiableAttrSet retAtrs = new TimeLimitedNotifiableAttrSet(new AttributeSetImpl());
243                retAtrs.removeAttributeListener(this);
244    
245                //adding each Vertex/Edge attribute to selectionAttributes
246                int i = 0;
247                retAtrs.put("Vertices", numOfSelectedVertices);
248                selectView.setEditable("Vertices", false);
249                selectView.setIndex("Vertices", i++);
250                for (VertexModel v : selectedVertices) {
251                    if (i < 500) {
252                        AttributeSet vAtrs = new VertexAttrSet(v);
253                        vertexView.setAttribute(vAtrs);
254                        for (String atrName : vertexView.getNames()) {
255                            String key = vertexAtrName(atrName);
256                            insertAttributeToSelectionAtrs(retAtrs, key, vAtrs, atrName);
257                            selectView.setDisplayName(key, atrName);
258                            selectView.setIndex(key, i++);
259                        }
260                    }
261                }
262    
263                retAtrs.put("   ", "");
264                selectView.setEditable("   ", false);
265                retAtrs.put("Edges", numOfSelectedEdges);
266                selectView.setIndex("   ", i++);
267                selectView.setIndex("Edges", i++);
268                selectView.setEditable("Edges", false);
269                for (EdgeModel e : selectedEdges) {
270                    if (i < 1000) {
271                        AttributeSet eAtrs = new EdgeAttrSet(e);
272                        for (String atrName : eAtrs.getAttrs().keySet()) {
273                            String key = edgeAtrName(atrName);
274                            insertAttributeToSelectionAtrs(retAtrs, key, eAtrs, atrName);
275                            selectView.setDisplayName(key, atrName);
276                            selectView.setIndex(key, i++);
277                        }
278                    }
279                }
280                selectView.setVisible("v" + VertexAttrSet.LOCATION, false);
281                selectView.setVisible("v" + VertexAttrSet.SELECTED, false);
282                selectView.setEditor("v" + VertexAttrSet.BORDER, new GStrokeEditor() {
283                    public Object[] getValues() {
284                        return new GStroke[]{
285                                GStroke.empty,
286                                simple,
287                                solid,
288                                strong,
289                                dashed,
290                                dotted,
291                                dashed_dotted,
292                                dashed_dotted_dotted,
293                                dashed_dashed_dotted
294                        };
295                    }
296                });
297                selectView.setEditor("v" + VertexAttrSet.COLOR, new GMergedColorEditor());
298                selectView.setrenderer("v" + VertexAttrSet.COLOR, new GMergedColorRenderer());
299    
300                selectView.setEditor("e" + VertexAttrSet.COLOR, new GMergedColorEditor());
301                selectView.setrenderer("e" + VertexAttrSet.COLOR, new GMergedColorRenderer());
302    
303                viewer = selectView;
304                retAtrs.addAttributeListener(this);
305    //            updateSelectView();
306                iChangedTheAttribute = false;
307    
308                setTarget(retAtrs);
309            }
310    
311        }
312    
313        /**
314         * adds the given atr from source to dest, and if there was some values
315         * on the place before, invalidate the place
316         *
317         * @param dest
318         * @param key     reffers to the atr name in dest
319         * @param source
320         * @param atrName reffers to the atr name in source that should be inserted to dest
321         */
322        private void insertAttributeToSelectionAtrs(AttributeSet dest, String key, AttributeSet source, String atrName) {
323            if (dest.getAttrs().containsKey(key)) {
324                Object oldVal = dest.get(key);
325                if (oldVal == null)
326                    return;
327                Object newVal = source.get(atrName);
328                if (!oldVal.equals(newVal)) {
329                    selectView.setValid(key, false);
330                }
331            } else {
332                selectView.setValid(key, true);  //it is valid default (in first time)
333            }
334            dest.put(key, source.get(atrName));
335        }
336    
337    //    private void updateSelectView() {
338    //        //selectView is the union of vertexView and edgeView
339    ////        int maxIndex = Integer.MIN_VALUE;
340    ////        selectView.setIndex("Vertices", 0);
341    //        for (String key : selectionAttributes.getAttrs().keySet()) {
342    //            String name = key.substring(1);     //the original name of attribute
343    //            if (key.startsWith("v")) {
344    //                selectView.setVisible(key, vertexView.isVisible(name));
345    ////                selectView.setDisplayName(key, name);
346    ////                selectView.setCategory(key, vertexAtrName(vertexView.getCategory(name)));
347    //                selectView.setDescription(key, vertexView.getDescription(name));
348    //                selectView.setEditable(key, vertexView.isEditable(name));
349    ////                selectView.setIndex(key, vertexView.getIndex(name));
350    ////                maxIndex = Math.max(maxIndex, vertexView.getIndex(name));
351    //            }
352    ////            selectView.setIndex("Edges", maxIndex + 1);
353    //            if (key.startsWith("e")) {
354    //                selectView.setVisible(key, edgeView.isVisible(name));
355    ////                selectView.setDisplayName(key, name);
356    ////                selectView.setCategory(key, vertexAtrName(edgeView.getCategory(name)));
357    //                selectView.setDescription(key, edgeView.getDescription(name));
358    //                selectView.setEditable(key, edgeView.isEditable(name));
359    ////                selectView.setIndex(key, maxIndex + edgeView.getIndex(name));
360    //            }
361    //        }
362    //    }
363    
364        /**
365         * suggests a name for the given vertex attribute to be used in selection attributed
366         */
367        private String vertexAtrName(String name) {
368            return "v" + name;
369        }
370    
371        /**
372         * suggests a name for the given edge attribute to be used in selection attributed
373         */
374        private String edgeAtrName(String name) {
375            return "e" + name;
376        }
377    
378    
379        private TimeLimitedNotifiableAttrSet getTarget() {
380            return target;
381        }
382    
383        private void setTarget(TimeLimitedNotifiableAttrSet target) {
384            if (this.target != null) {
385                this.target.stop();
386            }
387            this.target = target;
388            this.target.stop();
389        }
390    }