package MaxFlowApplet.mf_gui; import MaxFlowApplet.mf_gui.GraphCanvas; import MaxFlowApplet.graph.*; import MaxFlowApplet.graphic.*; import java.awt.*; import MFApplet; /* The class builds the main window of the program. The window contains * * a canvas, few buttons, checkboxes for determining the algorithm running * * manner. */ public class GraphFrame extends Frame { public GraphFrame(String title, int width, int height, MFApplet applet) { super(title); parentApplet = applet; resize(width, height); }; public GraphFrame(String title, MFApplet applet) { this(title, DEFAULTWIDTH, DEFAULTHEIGHT, applet); }; public void init() { for(int i = 0; i < NUMBEROFGRAPHS; i++) { graphChanged[i] = false; graphStatus[i] = STARTSTATUS; edgeMaxFlow[i] = 0; } graphArray[DEMOGRAPHINDEX] = makeDemoGraph(); graphArray[CUSTOMGRAPHINDEX] = makeNewGraph(); currentGraph = DEMOGRAPHINDEX; appletCanvas = new GraphCanvas(this, graphArray[currentGraph]); // create text and check boxes for custom speed speedBoxGroup = new CheckboxGroup(); stepSpeedBox = new Checkbox("Stop every", speedBoxGroup, true); trail = new Label("step(s)"); speedTextField = new TextField((new Integer(runningSpeed)).toString(), 3); // design the check box for custom speed adjustment customSpeedPanel = new Panel(); customSpeedPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); customSpeedPanel.add(stepSpeedBox); customSpeedPanel.add(speedTextField); customSpeedPanel.add(trail); // create & design check box for running until finish noStopSpeedBox = new Checkbox("Run until finish", speedBoxGroup, false); noStopPanel = new Panel(); noStopPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); noStopPanel.add(noStopSpeedBox); // design the panel of the two check boxes (first from left) speedPanel = new Panel(); speedPanel.setLayout(new BorderLayout()); speedPanel.add("North", customSpeedPanel); speedPanel.add("Center", noStopPanel); // create all buttons goButton = new Button(" GO! "); clearButton = new Button("Clear"); modeButton = new Button("Custom"); helpButton = new Button(" Help "); // set layout of buttonPanel and add buttons and check boxes buttonPanel = new Panel(); buttonPanel.setLayout(new FlowLayout()); buttonPanel.add(speedPanel); buttonPanel.add(goButton); buttonPanel.add(clearButton); buttonPanel.add(modeButton); buttonPanel.add(helpButton); // create the status labels actionStatus = new Label("Version 1.0 of Max Flow Applet by Alex Milanovic and Mony Aladjem"); maxFlowStatus = new Label(graphStatus[currentGraph]); // create the status panel statusPanel = new Panel(); statusPanel.setLayout(new GridLayout(2,1)); statusPanel.add(actionStatus); statusPanel.add(maxFlowStatus); // add canvas and buttons to this frame setLayout(new BorderLayout()); add("North", statusPanel); add("Center", appletCanvas); add("South", buttonPanel); resize(DEFAULTWIDTH, DEFAULTHEIGHT); setBackground(DEFAULTBACKGROUND); } //When the graph is changed in the middle of executing the algorithm, //it's stopped and all the flow in the graph is cleared public boolean mouseDown(Event evt, int x, int y) { if (graphChanged[currentGraph] == false && algorithmOn == false && evt.target.equals(appletCanvas)) { edgeMaxFlow[currentGraph] = 0; appletCanvas.setGreatestEdgeFlow(0); graphChanged[currentGraph] = true; algorithm = new MaxFlow(graphArray[currentGraph]); graphStatus[currentGraph] = STARTSTATUS; maxFlowStatus.setText(graphStatus[currentGraph]); appletCanvas.repaint(); } return super.mouseDown(evt, x, y); }; public boolean action(Event e, Object o) { if (e.target.equals(goButton)) { int oldFlow = 0; if (algorithmOn == false) { // run the algorithm once to find the greatest edge flow algorithm = new MaxFlow(graphArray[currentGraph]); algorithm.runUntilFinish(); int temp = greatestEdgeFlow(graphArray[currentGraph]); appletCanvas.setGreatestEdgeFlow(temp); edgeMaxFlow[currentGraph] = temp; // prepare the algorithm for running algorithm.init(); // if the alg. has been already run, repaint the graph appletCanvas.repaint(); algorithmOn = true; //modeButton.disable(); //clearButton.disable(); appletCanvas.disable(); graphChanged[currentGraph] = false; } // run until finish int stepsToRun = runningSpeed; if (noStopSpeedBox.getState() == true) stepsToRun = Integer.MAX_VALUE; appletCanvas.markAugmentingPath(true); oldFlow = algorithm.currentFlow(); Thread waitThread = new Thread(); do { algorithm.runSteps(1); appletCanvas.repaint(); if (stepsToRun > 1) try { waitThread.sleep(1000); } catch (InterruptedException except) {} stepsToRun--; } while (!algorithm.isFinished() && stepsToRun>0); if (algorithm.isFinished()) { algorithmOn = false; //modeButton.enable(); //clearButton.enable(); appletCanvas.enable(); appletCanvas.markAugmentingPath(false); graphStatus[currentGraph] = "The Maximal Flow in the Graph is "+(new Integer(algorithm.currentFlow())).toString(); maxFlowStatus.setText(graphStatus[currentGraph]); } else { graphStatus[currentGraph] = "Flow increment = "+ (new Integer(algorithm.currentFlow()-oldFlow)).toString(); maxFlowStatus.setText(graphStatus[currentGraph]); } appletCanvas.repaint(); return true; } if (e.target.equals(clearButton) && !algorithmOn) { if (graphChanged[currentGraph] == false) { edgeMaxFlow[currentGraph] = 0; appletCanvas.setGreatestEdgeFlow(0); graphChanged[currentGraph] = true; algorithm = new MaxFlow(graphArray[currentGraph]); graphStatus[currentGraph] = STARTSTATUS; maxFlowStatus.setText(graphStatus[currentGraph]); } if (currentGraph == CUSTOMGRAPHINDEX) graphArray[currentGraph] = makeNewGraph(); else graphArray[currentGraph] = makeDemoGraph(); appletCanvas.setCurrentGraph(graphArray[currentGraph]); appletCanvas.repaint(); return true; } if (e.target.equals(modeButton) && !algorithmOn) { if (currentGraph == CUSTOMGRAPHINDEX) { currentGraph = DEMOGRAPHINDEX; modeButton.setLabel("Custom"); } else { currentGraph = CUSTOMGRAPHINDEX; modeButton.setLabel(" Demo "); } appletCanvas.setGreatestEdgeFlow(edgeMaxFlow[currentGraph]); appletCanvas.setCurrentGraph(graphArray[currentGraph]); maxFlowStatus.setText(graphStatus[currentGraph]); appletCanvas.repaint(); return true; } if (e.target.equals(helpButton)) { InfoDialog helpBox = new InfoDialog( helpText, "Help", 300, 500, this); repaint(); return true; } if (e.target.equals(speedTextField)) { String str; Integer tmp; str = (String) o; try { tmp = new Integer(Integer.parseInt(str)); } catch (NumberFormatException except) { tmp = new Integer(runningSpeed); } if (tmp.intValue() < 1) tmp = new Integer(DEFAULTSPEED); runningSpeed = tmp.intValue(); speedTextField.setText(tmp.toString()); return true; } return super.action(e, o); } // returns the current greatest flow of an edge in the graph protected int greatestEdgeFlow(Graph graph) { int edgesNo = graph.numberOfEdges(); int maxEdgeFlow = 0; GraphicEdge e; for(int i = 0; i < edgesNo; i++) { e = (GraphicEdge) graph.getEdge(i); maxEdgeFlow = Math.max(maxEdgeFlow, e.getFlow()); } return maxEdgeFlow; }; // creates a demo graph protected Graph makeDemoGraph() { Graph demo = makeNewGraph(); GraphicVertex sink = (GraphicVertex) demo.getSink(); GraphicVertex source = (GraphicVertex) demo.getSource(); Point sinkPos = sink.getPosition(); Point sourcePos = source.getPosition(); int diff = sinkPos.x - sourcePos.x; GraphicVertex v1 = new GraphicVertex(sourcePos.x+diff/3, sinkPos.y - 40); GraphicVertex v2 = new GraphicVertex(sourcePos.x+diff/3, sinkPos.y + 40); GraphicVertex v3 = new GraphicVertex(sourcePos.x+2*diff/3, sinkPos.y - 40); GraphicVertex v4 = new GraphicVertex(sourcePos.x+2*diff/3, sinkPos.y + 40); demo.addVertex(v1); demo.addVertex(v2); demo.addVertex(v3); demo.addVertex(v4); GraphicEdge e1 = new GraphicEdge(source, v1, 16); GraphicEdge e2 = new GraphicEdge(source, v2, 13); GraphicEdge e3 = new GraphicEdge(v1, v3, 12); GraphicEdge e4 = new GraphicEdge(v1, v2, 10); GraphicEdge e5 = new GraphicEdge(v2, v1, 4); GraphicEdge e6 = new GraphicEdge(v3, v2, 9); GraphicEdge e7 = new GraphicEdge(v3, sink, 20); GraphicEdge e8 = new GraphicEdge(v4, v3, 7); GraphicEdge e9 = new GraphicEdge(v4, sink, 4); GraphicEdge e10 = new GraphicEdge(v2, v4, 14); demo.addEdge(e1); demo.addEdge(e2); demo.addEdge(e3); demo.addEdge(e4); demo.addEdge(e5); demo.addEdge(e6); demo.addEdge(e7); demo.addEdge(e8); demo.addEdge(e9); demo.addEdge(e10); return demo; } // creates new graph with source and sink protected Graph makeNewGraph() { Graph newGraph = new Graph(); Dimension d; if (appletCanvas != null) { d = appletCanvas.size(); newGraph.setSource(new GraphicVertex(d.width/8, d.height/2)); newGraph.setSink(new GraphicVertex(d.width*7/8, d.height/2)); } else //giving fixed positions to source and sink { newGraph.setSource(new GraphicVertex(70, 110)); newGraph.setSink(new GraphicVertex(520, 110)); } return newGraph; } public void update(Graphics g) { if (size().width < MINWIDTH || size().height < MINHEIGHT) resize(MINWIDTH, MINHEIGHT); super.update(g); } private int runningSpeed = DEFAULTSPEED; protected MFApplet parentApplet; private boolean algorithmOn = false; private String graphStatus[] = new String[NUMBEROFGRAPHS]; private Graph graphArray[] = new Graph[NUMBEROFGRAPHS]; private boolean graphChanged[] = new boolean[NUMBEROFGRAPHS]; private int edgeMaxFlow[] = new int[NUMBEROFGRAPHS]; private int currentGraph; private static final Color DEFAULTBACKGROUND = Color.lightGray; private static final int DEMOGRAPHINDEX = 0; private static final int CUSTOMGRAPHINDEX = 1; private static final int NUMBEROFGRAPHS = 2; protected GraphCanvas appletCanvas; private Button clearButton; private Button goButton; private Button modeButton; private Button helpButton; private CheckboxGroup speedBoxGroup; private Checkbox stepSpeedBox; private Checkbox noStopSpeedBox; private Panel buttonPanel; private Panel speedPanel; private Panel customSpeedPanel; private Panel noStopPanel; private Panel statusPanel; private TextField speedTextField; private Label maxFlowStatus; private Label actionStatus; private Label trail; private MaxFlow algorithm; private static final int DEFAULTWIDTH = 600; private static final int DEFAULTHEIGHT = 400; private static final int MINHEIGHT = 400; private static final int MINWIDTH = 300; private static final int DEFAULTSPEED = 1; private static final int STEPPAUSE = 1000; private static final String STARTSTATUS = "Build or Run"; private static final String helpText = "Colors Source is colored orange.\n"+ " Sink is colored red.\n"+ " Edge capacities are colored white.\n"+ " Edge flows are colored yellow - if there is no flow,"+ " the values are not displayed.\n"+ " Last augmenting path is marked with red color.\n\n"+ "Selecting a vertex When a vertex is selected it's pressed down.\n"+ " Press the mouse key on a vertex to select it.\n\n"+ "Deselecting a vertex When a vertex is selected, press the mouse on it\n"+ " to deselect it.\n\n"+ "Creating a vertex Press a mouse key on the desired location.\n\n"+ "Creating an edge Click on two vertices and an edge between them\n"+ " will be created. You'll be asked to enter its\n"+ " capacity.\n\n"+ "Modifying vertex position Drag the vertex with the mouse.\n\n"+ "Modifying edge capacity Click on the two vertices the edge is connecting.\n"+ " Or click on the arrow of the wanted edge.\n\n"+ "Deleting a vertex Drag the vertex to the trash.\n\n"+ "Deleting an edge When modifying edge capacity press the button\n"+ " 'Delete Edge'.\n\n"+ "Choosing run mode The algorithm can be executed in one step 'Run until finish',\n"+ " or traced every n steps, when n can be determined by user.\n\n"+ "Starting the algorithm Clicking on the button 'Go' will start the algorithm\n"+ " To continue running the algorithm continue pressing 'Go'.\n\n"+ "Switching between graphes The applet starts in demo graph. By clicking on the\n"+ " Demo/Custom you can switch between two graphes.\n\n"+ "Deleting the graph Click on 'Clear' button to delete the graph. If you're\n"+ " working with the demo graph, it will be reset.\n"+ "Help Click on the 'Help' button.\n"; }