// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.plugins.main.core.actions;
import graphtea.graph.atributeset.*;
import graphtea.graph.event.EdgeEvent;
import graphtea.graph.event.GraphSelectData;
import graphtea.graph.event.VertexEvent;
import graphtea.graph.graph.Edge;
import graphtea.graph.graph.GraphModel;
import graphtea.graph.graph.Vertex;
import graphtea.graph.old.GStroke;
import graphtea.platform.attribute.*;
import graphtea.platform.core.AbstractAction;
import graphtea.platform.core.BlackBoard;
import graphtea.plugins.main.select.Select;
import graphtea.plugins.main.select.SelectPluginMethods;
import graphtea.plugins.main.ui.GStrokeEditor;
import graphtea.ui.AttributeSetView;
import graphtea.ui.PortableNotifiableAttributeSetImpl;
import graphtea.ui.UIUtils;
import graphtea.ui.components.gpropertyeditor.GPropertyEditor;
import java.util.HashSet;
import java.util.Set;
import static graphtea.graph.old.GStroke.*;
/**
* the left side property editor of graphtea gui
*
* @author Azin Azadi
*/
public class GraphPropertyEditor extends AbstractAction implements AttributeListener {
public GPropertyEditor getPropertyEditor() {
return prosheet;
}
private GPropertyEditor prosheet;
public NotifiableAttributeSet NotifiableAttributeSet;
public AttributeSetView viewer;
Vertex lastVertex;
Edge lastEdge;
private TimeLimitedNotifiableAttrSet target;
AttributeSetView edgeView = new AttributeSetView();
AttributeSetView vertexView = new AttributeSetView();
AttributeSetView graphView = new AttributeSetView();
AttributeSetView selectView = new AttributeSetView();
HashSet<String> hiddenVertexAttributes = new HashSet<>();
HashSet<String> hiddenEdgeAttributes = new HashSet<>();
PortableNotifiableAttributeSetImpl xx = new PortableNotifiableAttributeSetImpl();
TimeLimitedNotifiableAttrSet selectionAttributes = new TimeLimitedNotifiableAttrSet(new AttributeSetImpl());
SelectPluginMethods spm;
/**
* constructor
*
* @param bb the blackboard of the action
*/
public GraphPropertyEditor(BlackBoard bb) {
super(bb);
spm = new SelectPluginMethods(blackboard);
prosheet = new GPropertyEditor();
prosheet.setSize(150, 100);
UIUtils.setComponent(blackboard, "property editor", prosheet);
listen4Event(EdgeEvent.EVENT_KEY);
listen4Event(VertexEvent.EVENT_KEY);
listen4Event(Select.EVENT_KEY);
listen4Event(GraphSelectData.EVENT_KEY);
// graphView.setVisible(GraphAttrSet.CENTERX, false);
// graphView.setVisible(GraphAttrSet.CENTERY, false);
// graphView.setVisible(GraphAttrSet.DIRECTED, false);
// graphView.setVisible(GraphAttrSet.ZOOM, false);
graphView.setIndex(GraphAttrSet.LABEL, 0);
graphView.setIndex(GraphAttrSet.DIRECTED, 1);
graphView.setIndex(GraphAttrSet.DRAW_VERTEX_LABELS, 5);
graphView.setIndex(GraphAttrSet.DRAW_EDGE_LABELS, 6);
graphView.setEditable(GraphAttrSet.DIRECTED, false);
graphView.setEditable(GraphAttrSet.LABEL, true);
// graphView.setIndex(EdgeAttrSet.SHOW_EDGE_LABELS, 3);
//Storing Id in vertex is deprecated
// vertexView.setVisible(Vertex.ID, false);
// vertexView.setVisible(Vertex.XPOS, false);
// vertexView.setVisible(Vertex.YPOS, false);
vertexView.setIndex(VertexAttrSet.LABEL, 0);
vertexView.setIndex(VertexAttrSet.COLOR, 2);
vertexView.setIndex(VertexAttrSet.SHAPE, 4);
vertexView.setIndex(VertexAttrSet.BORDER, 6);
vertexView.setVisible(VertexAttrSet.SELECTED, false);
vertexView.setEditor(VertexAttrSet.BORDER, new GStrokeEditor() {
public Object[] getValues() {
return new GStroke[]{
GStroke.empty,
simple,
solid,
strong,
dashed,
dotted,
dashed_dotted,
dashed_dotted_dotted,
dashed_dashed_dotted
};
}
});
vertexView.setEditor(VertexAttrSet.COLOR, new GMergedColorEditor(true));
vertexView.setrenderer(VertexAttrSet.COLOR, new GMergedColorRenderer(true));
// edgeView.setVisible(EdgeAttrSet.DIRECTED, false);
// edgeView.setVisible(EdgeAttrSet.LABEL, false);
edgeView.setEditable(EdgeAttrSet.SOURCE, false);
edgeView.setEditable(EdgeAttrSet.TARGET, false);
edgeView.setIndex(EdgeAttrSet.LABEL, 0);
edgeView.setIndex(EdgeAttrSet.WEIGHT, 1);
edgeView.setIndex(EdgeAttrSet.ARROW, 4);
edgeView.setEditor(EdgeAttrSet.COLOR, new GMergedColorEditor(false));
edgeView.setrenderer(EdgeAttrSet.COLOR, new GMergedColorRenderer(false));
// updateSelectView();
}
private Vertex lastVertex() {
VertexEvent x = blackboard.getData(VertexEvent.EVENT_KEY);
return (x == null ? null : x.v);
}
private Edge lastEdge() {
EdgeEvent x = blackboard.getData(EdgeEvent.EVENT_KEY);
return (x == null ? null : x.e);
}
private GraphModel lastGraph() {
GraphSelectData x = blackboard.getData(GraphSelectData.EVENT_KEY);
return (x == null ? null : x.g);
}
public void performAction(String eventName, Object value) {
prosheet = (GPropertyEditor) UIUtils.getComponent(blackboard,
"property editor");
if (getTarget() != null)
if (eventName == Select.EVENT_KEY) {
if (!spm.isSelectionEmpty()) {
updatePropertyEditor_selected();
// viewer = selectView;
} else {
setTarget(new GraphNotifiableAttrSet(lastGraph()));
viewer = graphView;
}
}
// if (eventName ==VertexEvent.name)) {
// VertexEvent ve = blackboard.get(VertexEvent.name);
// if (ve.eventType == VertexEvent.PRESSED) {
// if (spm.isSelectionEmpty()) {
// setTarget(new VertexNotifiableAttrSet(lastVertex()));
// viewer = vertexView;
// }
// }
// }
// if (eventName ==EdgeEvent.name)) {
// EdgeEvent ve = blackboard.get(EdgeEvent.name);
// if (ve.eventType == EdgeEvent.PRESSED) {
// if (spm.isSelectionEmpty()) {
// setTarget(new EdgeNotifiableAttrSet(lastEdge()));
// viewer = edgeView;
// }
// }
// }
if (eventName == GraphSelectData.EVENT_KEY) {
setTarget(new GraphNotifiableAttrSet(lastGraph()));
viewer = graphView;
}
updateTarget();
}
private void updateTarget() {
if (prosheet != null && getTarget() != null) {
xx.setView(viewer);
xx.setModel(getTarget());
prosheet.connect(xx);
}
if(getTarget() != null) {
getTarget().addAttributeListener(new AttributeListener() {
@Override
public void attributeUpdated(String name, Object oldVal, Object newVal) {
blackboard.setData("undo point", lastGraph());
}
});
}
}
public void attributeUpdated(String name, Object oldVal, Object newVal) {
//occurs whenever one attribute in selection attribute changed by user
//note that the vertex and edge attributes are updates directly, not from here
if (!iChangedTheAttribute) {
String key = name.substring(1); //the original name of attribute
if (name.startsWith("v")) { //it was a vertex attribute
for (Vertex v : spm.getSelectedVertices()) {
VertexAttrSet _v = new VertexAttrSet(v);
_v.put(key, newVal);
}
}
if (name.startsWith("e")) { //it was an edge attribute
for (Edge e : spm.getSelectedEdges()) {
EdgeAttrSet _e = new EdgeAttrSet(e);
_e.put(key, newVal);
}
}
}
}
boolean iChangedTheAttribute = false;
private void updatePropertyEditor_selected() {
HashSet<Vertex> selectedVertices = spm.getSelectedVertices();
HashSet<Edge> selectedEdges = spm.getSelectedEdges();
int numOfSelectedVertices = selectedVertices.size();
int numOfSelectedEdges = selectedEdges.size();
//if there was only 1 selected vertex(edge) show the classic editor for it
if (numOfSelectedVertices + numOfSelectedEdges == 1) {
if (numOfSelectedVertices == 1) {
setTarget(new VertexNotifiableAttrSet(selectedVertices.iterator().next()));
viewer = vertexView;
} else {
setTarget(new EdgeNotifiableAttrSet(selectedEdges.iterator().next()));
viewer = edgeView;
}
} else {
viewer = selectView;
iChangedTheAttribute = true;
TimeLimitedNotifiableAttrSet retAtrs = new TimeLimitedNotifiableAttrSet(new AttributeSetImpl());
retAtrs.removeAttributeListener(this);
//adding each Vertex/Edge attribute to selectionAttributes
int i = 0;
retAtrs.put("Vertices", numOfSelectedVertices);
selectView.setEditable("Vertices", false);
selectView.setIndex("Vertices", i++);
for (Vertex v : selectedVertices) {
if (i < 500) {
AttributeSet vAtrs = new VertexAttrSet(v);
vertexView.setAttribute(vAtrs);
for (String atrName : vertexView.getNames()) {
String key = vertexAtrName(atrName);
insertAttributeToSelectionAtrs(retAtrs, key, vAtrs, atrName);
selectView.setDisplayName(key, atrName);
selectView.setIndex(key, i++);
}
}
}
retAtrs.put(" ", "");
selectView.setEditable(" ", false);
retAtrs.put("Edges", numOfSelectedEdges);
selectView.setIndex(" ", i++);
selectView.setIndex("Edges", i++);
selectView.setEditable("Edges", false);
for (Edge e : selectedEdges) {
if (i < 1000) {
AttributeSet eAtrs = new EdgeAttrSet(e);
for (String atrName : ((Set<String>)eAtrs.getAttrs().keySet())) {
String key = edgeAtrName(atrName);
insertAttributeToSelectionAtrs(retAtrs, key, eAtrs, atrName);
selectView.setDisplayName(key, atrName);
selectView.setIndex(key, i++);
}
}
}
selectView.setVisible("v" + VertexAttrSet.LOCATION, false);
selectView.setVisible("v" + VertexAttrSet.SELECTED, false);
selectView.setEditor("v" + VertexAttrSet.BORDER, new GStrokeEditor() {
public Object[] getValues() {
return new GStroke[]{
GStroke.empty,
simple,
solid,
strong,
dashed,
dotted,
dashed_dotted,
dashed_dotted_dotted,
dashed_dashed_dotted
};
}
});
selectView.setEditor("v" + VertexAttrSet.COLOR, new GMergedColorEditor());
selectView.setrenderer("v" + VertexAttrSet.COLOR, new GMergedColorRenderer());
selectView.setEditor("e" + VertexAttrSet.COLOR, new GMergedColorEditor());
selectView.setrenderer("e" + VertexAttrSet.COLOR, new GMergedColorRenderer());
viewer = selectView;
retAtrs.addAttributeListener(this);
// updateSelectView();
iChangedTheAttribute = false;
setTarget(retAtrs);
}
}
/**
* adds the given atr from source to dest, and if there was some values
* on the place before, invalidate the place
*
* @param dest The destination attribute set
* @param key reffers to the atr name in dest
* @param source The source attribute set
* @param atrName reffers to the atr name in source that should be inserted to dest
*/
private void insertAttributeToSelectionAtrs(AttributeSet dest, String key, AttributeSet source, String atrName) {
if (dest.getAttrs().containsKey(key)) {
Object oldVal = dest.get(key);
if (oldVal == null)
return;
Object newVal = source.get(atrName);
if (!oldVal.equals(newVal)) {
selectView.setValid(key, false);
}
} else {
selectView.setValid(key, true); //it is valid default (in first time)
}
dest.put(key, source.get(atrName));
}
// private void updateSelectView() {
// //selectView is the union of vertexView and edgeView
//// int maxIndex = Integer.MIN_VALUE;
//// selectView.setIndex("Vertices", 0);
// for (String key : selectionAttributes.getAttrs().keySet()) {
// String name = key.substring(1); //the original name of attribute
// if (key.startsWith("v")) {
// selectView.setVisible(key, vertexView.isVisible(name));
//// selectView.setDisplayName(key, name);
//// selectView.setCategory(key, vertexAtrName(vertexView.getCategory(name)));
// selectView.setDescription(key, vertexView.getDescription(name));
// selectView.setEditable(key, vertexView.isEditable(name));
//// selectView.setIndex(key, vertexView.getIndex(name));
//// maxIndex = Math.max(maxIndex, vertexView.getIndex(name));
// }
//// selectView.setIndex("Edges", maxIndex + 1);
// if (key.startsWith("e")) {
// selectView.setVisible(key, edgeView.isVisible(name));
//// selectView.setDisplayName(key, name);
//// selectView.setCategory(key, vertexAtrName(edgeView.getCategory(name)));
// selectView.setDescription(key, edgeView.getDescription(name));
// selectView.setEditable(key, edgeView.isEditable(name));
//// selectView.setIndex(key, maxIndex + edgeView.getIndex(name));
// }
// }
// }
/**
* suggests a name for the given vertex attribute to be used in selection attributed
*/
private String vertexAtrName(String name) {
return "v" + name;
}
/**
* suggests a name for the given edge attribute to be used in selection attributed
*/
private String edgeAtrName(String name) {
return "e" + name;
}
private TimeLimitedNotifiableAttrSet getTarget() {
return target;
}
public void track(){}
private void setTarget(TimeLimitedNotifiableAttrSet target) {
if (this.target != null) {
this.target.stop();
}
this.target = target;
this.target.stop();
}
}