The NetWorKsPanel class is an applet which may be run on a web
page
.
The NetWorKs and NWKFrame classes work together to run an instance of this applet outside of a browser.
The NetWorKsPanel directly handles events concerning running algorithms and
also handles switching between the various control panels displayed across the
top of its display area. The NetWorKsPanel also creates a GraphPanel and a
GraphControlPanel. The GraphPanel is the drawing area displayed in the bottom
of the NetWorKsPanels display area. The GraphControlPanel contains the
controls for editing the graph and is swapped in and out of the top of the
NetWorKsPanel as needed.
There are also two Panels used to allow selecting and then running an
algorithm.
The algSelP Panel handles selection, and the algCntrlP Panel allows stepping
through the algorithm.
The algSelP Panel contains a List object which allows users to select an algorithm. This list also includes an option to return to the GraphControlPanel in case the user decides to edit the graph before selecting an algorithm to run. If the user selects an algorithm which is not currently running, the NetWorKsPanel handles the list selection event by first invoking the init() method of the selected GraphAlgorithm, and then switching the top panel to display Panel algCntrlP. If the user selects the currently running algorithm, the event is handled by simply switching back to Panel algCntrlP.
The algCntrlP Panel contains buttons to restart the algorithm, execute one step of the algorithm, select a different algorithm, or to return to the GraphControlPanel to edit the graph. It also contains a TextArea to display communication from GraphAlgorithm to the user. Events generated by the restart button are handled by invoking the init() method, and step button events invoke the step() method. Also note that Strings returned by the graphAlgorithm init() and step() methods are displayed in the TextArea. The remaining logic for this panel is straightforward.
The logic for swapping the GraphControlPanel in and out is not so simple. Suppose a user has started an algorithm and decides to edit the graph. Certain changes should be allowed without forcing the user to restart the algorithm: moving vertices, changing font size, changing vertex radii, etc. But since GraphAlgorithm objects assume the graph does not change between steps, it is important for the NetWorKsPanel to know if the user makes changes relevant to the algorithm. Now the GraphControlPanel allows editing vertices and edges, but the GraphPanel is in charge of adding or deleting vertices and edges. Since the GraphPanel also knows when the GraphControlPanel modifies the graph, the GraphPanel notifies the NetWorKsPanel when the user makes changes relevant to the algorithm. This means that when a user presses the algorithms button on the GraphControlPanel, the NetWorKsPanel decides between swapping in Panel algSelP and algCntrlP based on whether or not the user has changed the graph in a way that is relevant to the current algorithm.
This same notification mechanism allows the NetWorKsPanel to swap in the GraphControlPanel if a user adds or deletes vertices or edges while the algSelP or algCntrlP Panels are being displayed.
package GraphStuff;
import MyUtil.*;
import MyAwt.*;
import java.awt.*;
public class NetWorKsPanel extends java.applet.Applet implements Notify {
boolean justDrawing;
int curAlg;
GraphAlgorithm alg[] = Algorithms.algs;
Panel topP = new Panel(),
buttonP = new InsetPanel(new Insets(8,0,14,4)),
algP = new Panel(),
algSelP = new Panel(),
algCntrlP = new Panel();
CardLayout card = new CardLayout();
Button mainB = new Button("algorithm"),
editB = new Button("edit"),
restartB = new Button("restart"),
stepB = new Button("step"),
selectB = new Button("algorithms");
List algL = new List(4,false);
TextArea stateTA = new TextArea("",3,80);
GraphPanel gP = new GraphPanel();
GraphControlPanel gCP = new GraphControlPanel(gP,mainB);
public final GraphPanel gp() { return gP;}
public void init() {
justDrawing=false;
curAlg=-1;
gP.notifyOnModify(this);
algL.addItem("Edit Graph");
for(int i=0;i<alg.length;i++)
algL.addItem(alg[i].title());
algSelP.setLayout(new BorderLayout());
algSelP.add("Center",algL);
buttonP.setLayout(new GridLayout(2,2,4,4));
buttonP.add(editB);
buttonP.add(selectB);
buttonP.add(restartB);
buttonP.add(stepB);
algCntrlP.setLayout(new BorderLayout());
algCntrlP.add("West",buttonP);
algCntrlP.add("Center",stateTA);
algP.setLayout(card);
algP.add("algSelP",algSelP);
algP.add("algCntrlP",algCntrlP);
topP.setLayout(card);
topP.add("algP",algP);
topP.add("gCP",gCP);
this.setLayout(new BorderLayout());
add("North" , topP);
add("Center",gP);
stateTA.setEditable(false);
card.show(algP,"algSelP");
algP.invalidate();
validate();
}
public boolean action(Event evt, Object arg) {
if (evt.target instanceof Button) {
if ( evt.target==restartB ) {
gP.currentGraph(alg[curAlg].GraphType());
replaceText(stateTA,alg[curAlg].init(gP));
gP.fullPaint();
} else if ( evt.target==stepB ) {
gP.currentGraph(alg[curAlg].GraphType());
replaceText(stateTA,alg[curAlg].step(gP));
gP.fullPaint();
} else if ( evt.target==selectB ) {
card.show(algP,"algSelP");
} else if ( evt.target==mainB ) {
gP.notifyOnModify(this);
card.show(topP,"algP");
} else if ( evt.target==editB ) {
card.show(topP,"gCP");
}
}
else if (evt.target instanceof List) {
if (evt.target==algL) {
int sel = ((List)evt.target).getSelectedIndex();
if(sel !=0) {
if (curAlg!=sel-1) {
curAlg=sel-1;
gP.currentGraph(alg[curAlg].GraphType());
stateTA.setText(alg[curAlg].init(gP));
gCP.displayItems(alg[curAlg].showWeights(),
alg[curAlg].showFlows(),
alg[curAlg].showCapacities(),
alg[curAlg].showMinimums(),
alg[curAlg].showLabels(),
alg[curAlg].showDemands());
}
else gP.currentGraph(alg[curAlg].GraphType());
gP.graph.unselect();
gP.fullPaint();
card.show(algP,"algCntrlP");
validate();
return true;
} else {
card.show(topP,"gCP");
curAlg=-1;
return true;
}
}
}
return false;
}
private void replaceText(TextArea ta, String txt) {
if (txt==null)
return;
ta.setText(txt);
}
public void modified(int n) {
card.show(algP,"algSelP");
card.show(topP,"gCP");
curAlg=-1;
}
}
Note that the algorithms button on the GraphControlPanel belongs to the NetWorKsPanel. This allows the NetWorKsPanel to identify events triggered by the algorithms button by reference rather than by its label.