In order to notify other objects when the Graph objects in the GraphPanel have been modified, the GraphPanel class implements the Notify interface. This means that any object (class unknown) can use the notifyOnModify() method to request that the GraphPanel notify the specified object each time a Graph is been modified. This mechanism allows the GraphPanel to notify the NetWorKsPanel of modifications without creating a class interdependency.
The GraphPanel class also includes load() and deleteAll() methods
which allow outside objects to load a Graph from a String
, or to clear the current Graph.
package GraphStuff;
import MyUtil.*;
import java.util.*;
import java.awt.*;
public class GraphPanel extends Panel {
public static final int Simple=0;
public static final int SimpleUndirected=1;
public static final String[] graphTypes = {"directed", "undirected"};
public GraphPanel () {
super();
graphA = new Graph[2];
graphA[0]= new SimpleGraph();
graphA[1]= new SimpleUndirectedGraph();
numsA=new UNNL[2];
numsA[0]= new UNNL();
numsA[1]= new UNNL();
E = new Edge(0,1,0,100);
V= new Vertex(1);
cG = 0;
graph=graphA[cG];
nums = numsA[cG];
General.showWeights=true;
General.showCapacities=false;
General.showFlows=false;
General.showMinimums=false;
General.showDemands=false;
cursor = new xPoint(0,0);
downCursor = new xPoint(0,0);
}
// list of objects to notify when the graph is edited
private Vector p_nosey = new Vector(10,5);
private int cG; // current graph (index)
public Graph graphA[]; // graphs
public Graph graph; // current graph
public UNNL numsA[];
public UNNL nums; // UNNL for current graph
private xPoint cursor,downCursor;
private Trash trash;
private boolean movingVertex=false; // set when moving a vertex
private GraphControlPanel gCP;
private Vertex V;
private Edge E;
int border=7;
Image backgroundImage , drawingImage;
Graphics backgroundG, drawingG;
static Color backGroundColor = new Color(255,255,255);
private boolean doneInit = false;
public void addControl(GraphControlPanel p) {
if (gCP!=null || p ==null)
return;
gCP=p;
gCP.setDirB(graphTypes[cG]);
}
void modified(boolean tf) {
Object tmp;
if (tf && p_nosey.size()>0) {
Enumeration obs = p_nosey.elements();
p_nosey=new Vector(10,5);
while (obs.hasMoreElements()) {
tmp=obs.nextElement();
((Notify)tmp).modified(cG);
}
}
}
public void notifyOnModify(Object n) {
if (n!=null && !p_nosey.contains(n)) {
p_nosey.addElement(n);
}
}
public void updateBackgroundImage() {
backgroundG.setColor(backGroundColor);
backgroundG.fillRect(border,border,this.size().width-2*border,
this.size().height-2*border);
graph.draw(backgroundG, !Graph.selectedStuff );
}
public void updateDrawingImage() {
drawingG.drawImage(backgroundImage, 0, 0, this);
graph.draw(drawingG, Graph.selectedStuff );
trash.draw(drawingG);
}
public void update(Graphics g) {
paint(g);
}
public void fullPaint() {
updateBackgroundImage();
repaint();
}
public int currentGraph() { return cG; }
public void currentGraph(int which) {
if (which==cG)
return;
if (graph!=null)
graph.unselect();
if (which>=graphTypes.length || which<1)
cG=0;
else
cG=which;
graph=graphA[cG];
nums=numsA[cG];
if (gCP!=null)
gCP.setDirB(graphTypes[cG]);
fullPaint();
}
void deleteAll() {
nums = numsA[cG] = new UNNL();
graph.deleteAll();
modified(true);
fullPaint();
}
public String graphString() {
StringBuffer sb = new StringBuffer(80);
if (General.showWeights) sb.append("showWeights ");
if (General.showFlows) sb.append("showFlows ");
if (General.showCapacities) sb.append("showCapacities ");
if (General.showMinimums) sb.append("showMinimums ");
if (General.showLabels) sb.append("showLabels ");
if (General.showDemands) sb.append("showDemands ");
sb.append(" radii=");
sb.append(General.vor());
sb.append(" font=");
sb.append(General.fontSize());
sb.append("\n");
sb.append(graph);
return new String(sb);
}
public boolean load(String str) {
Graph g = SimpleUndirectedGraph.fromString(str);
if (g!=null) {
graphA[SimpleUndirected]=g;
currentGraph(SimpleUndirected);
graph=graphA[SimpleUndirected];
} else {
g = SimpleGraph.fromString(str);
if (g==null) {
System.out.println(
"Error: GraphPanel load(String str) "
+"- str does not contain a Graph\n");
return false;
}
graphA[Simple]=g;
currentGraph(Simple);
graph=graphA[Simple];
}
General.showWeights= (str.indexOf("showWeights")>=0);
General.showFlows= (str.indexOf("showFlows")>=0);
General.showCapacities= (str.indexOf("showCapacities")>=0);
General.showMinimums= (str.indexOf("showMinimums")>=0);
General.showLabels= (str.indexOf("showLabels")>=0);
General.showDemands= (str.indexOf("showDemands")>=0);
General.vor(Parse.intFollowing(str,"radii=",0,General.vor()));
General.fontSize(Parse.intFollowing(str,"font=",0,General.fontSize()));
if (gCP!=null) {
gCP.displayItems(General.showWeights, General.showFlows,
General.showCapacities, General.showMinimums,
General.showLabels, General.showDemands);
gCP.updateVorRadii();
}
nums = numsA[cG] = new UNNL();
Vertex[] V = graphA[cG].vertices();
int max = 0;
for(int i=0;i<V.length;i++)
max=V[i].vNum()>max?V[i].vNum():max;
if (max>0) {
boolean used[] = new boolean[max+1];
while(numsA[cG].get()<max);
for(int i=0;i<V.length;i++)
used[V[i].vNum()]=true;
for(int i=1;i<used.length;i++)
if (!used[i])
numsA[cG].reuse(i);
}
modified(true);
fullPaint();
return true;
}
private Vertex V() {
return (Vertex)(V.clone());
}
private Edge E() {
return (Edge)(E.clone());
}
public void paint (Graphics g) {
if (!doneInit) {
modified(true);
setBackground(backGroundColor);
backgroundImage = createImage(this.size().width, this.size().height);
backgroundG = backgroundImage.getGraphics();
backgroundG.setColor(General.gridDark);
backgroundG.fillRect(0,0,this.size().width,this.size().height);
backgroundG.setColor(General.gridColor);
backgroundG.fillRect(2,2,this.size().width-4,this.size().height-4);
backgroundG.setColor(General.gridDark);
backgroundG.fillRect(5,5,this.size().width-10,this.size().height-10);
backgroundG.clipRect(border,border,this.size().width-2*border,
this.size().height-2*border);
drawingImage = createImage(this.size().width, this.size().height);
drawingG = drawingImage.getGraphics();
trash = new Trash(this.size().width-50,this.size().height-70,60,90);
updateBackgroundImage();
doneInit=true;
}
updateDrawingImage();
g.drawImage(drawingImage,0,0,this);
}
public boolean mouseDown(Event evt, int x, int y) {
downCursor.x=x;downCursor.y=y;
adjInside(downCursor);
movingVertex=false;
Object sPart,newSelection;
if (graph.beenSelected()) {
sPart=graph.selectedPart();
if (trash.contains(downCursor)) {
graph.unselect();
if (sPart instanceof Vertex) {
nums.reuse(((Vertex)sPart).vNum());
graph.delete((Vertex)sPart);
modified(true);
} else {
graph.delete((Edge)sPart);
modified(true);
}
modified(true);
sPart=null;
} else if (graph.contains(downCursor)) {
newSelection=graph.select(downCursor);
if (sPart==newSelection) {
graph.unselect();
} else if (sPart instanceof Vertex
&& newSelection instanceof Vertex
&& !graph.isEdge(((Vertex)sPart).vNum(),
((Vertex)newSelection).vNum()) ) {
Edge tmp=E();
int u = ((Vertex)sPart).vNum();
int v = ((Vertex)newSelection).vNum();
gCP.data(tmp);
graph.put(u,v,tmp);
graph.unselect();
modified(true);
} else if ( gCP!=null) {
gCP.selected(newSelection);
}
} else {
graph.unselect();
}
fullPaint();
} else {
if (graph.contains(downCursor)) {
graph.select(downCursor);
sPart=graph.selectedPart();
if (gCP!=null) {
gCP.selected(sPart);
}
fullPaint();
} else if (trash.contains(downCursor)) {
trash.beenSelected(true);
} else {
Vertex V = V().center(downCursor);
if (gCP!=null)
gCP.data(V);
graph.put(nums.get(),V);
modified(true);
fullPaint();
}
}
return true;
}
public boolean mouseUp(Event evt, int x, int y) {
cursor.x=x;cursor.y=y;
Object sPart;
adjInside(cursor);
if (graph.beenSelected()) {
sPart=graph.selectedPart();
if (trash.contains(cursor)) {
graph.unselect();
if (sPart instanceof Vertex) {
nums.reuse(((Vertex)sPart).vNum());
graph.delete((Vertex)sPart);
modified(true);
} else {
graph.delete((Edge)sPart);
modified(true);
}
} else if (movingVertex) {
graph.unselect();
}
fullPaint();
} else if (trash.beenSelected()) {
trash.beenSelected(false);
}
movingVertex=false;
return true;
}
public boolean mouseDrag(Event evt, int x, int y) {
int dist = Math.abs(downCursor.x-x) + Math.abs(downCursor.y-y);
cursor.x=x;cursor.y=y;
if (graph.beenSelected() ) {
Object sPart=graph.selectedPart();
if (sPart instanceof Vertex &&(movingVertex||dist>3) ){
movingVertex=true;
adjInside(cursor);
((Vertex)sPart).center(cursor);
repaint();
}
} else if (trash.beenSelected()) {
adjInside(cursor);
trash.center(cursor);
repaint();
}
return true;
}
private xPoint adjInside(xPoint c) {
int top = border+General.vor(),
bottom = this.size().height-border-General.vor(),
left = border+General.vor(),
right = this.size().width-border-General.vor();
c.x=c.x>left?c.x:left;
c.x=c.x<right?c.x:right;
c.y=c.y>top?c.y:top;
c.y=c.y<bottom?c.y:bottom;
return c;
}
}