// //width = 425 height = 250 import java.awt.*; import java.applet.*; public class NumberLine extends Applet { NumberPanel np; Checkbox AddBox, SubtractBox, MultiplyBox, Num1Box, Num2Box; Button CalcButton = new Button("Calculate"); Button ResetButton = new Button("Reset"); public void init() { setBackground(Color.white); np = new NumberPanel(); CheckboxGroup opsGroup = new CheckboxGroup(); CheckboxGroup linesGroup = new CheckboxGroup(); AddBox = new Checkbox("Add",opsGroup,true); SubtractBox = new Checkbox("Subtract",opsGroup,false); MultiplyBox = new Checkbox("Multiply",opsGroup,false); Num1Box = new Checkbox("1st Number",linesGroup,true); Num2Box = new Checkbox("2nd Number",linesGroup,false); Panel p1 = new Panel(); p1.setLayout(new GridLayout(3,1)); p1.setBackground(Color.white); p1.add(AddBox); p1.add(SubtractBox); // p1.add(MultiplyBox); Panel p2 = new Panel(); p2.setLayout(new GridLayout(3,1)); p2.setBackground(Color.white); p2.add(Num1Box); p2.add(Num2Box); Panel buttonPanel = new Panel(); buttonPanel.setBackground(Color.white); buttonPanel.add(CalcButton); buttonPanel.add(ResetButton); /* Panel opsPanel = new Panel(); opsPanel.setLayout(new GridLayout(1,2,2,2)); opsPanel.setBackground(Color.white); opsPanel.add(p1); opsPanel.add(p2); */ /* Panel mainPanel = new Panel(); mainPanel.setLayout(new GridLayout(1,3,2,2)); mainPanel.setBackground(Color.white); mainPanel.add(p1); mainPanel.add(p2); mainPanel.add(buttonPanel); */ add(np); add(p1); add(p2); add(buttonPanel); } public void resetApplet() { AddBox.setState(true); SubtractBox.setState(false); MultiplyBox.setState(false); Num1Box.setState(true); Num2Box.setState(false); np.resetPanel(); // np = null; // np = new NumberPanel(); repaint(); } public void getControls() { /* Panel p = new Panel(); p.setLayout(new GridLayout()); p.add(AddButton); p.add(SubtractButton); p.add(MultiplyButton); p.add(CalcButton); p.add(ResetButton); p.add(Num1Button); p.add(Num2Button); return p; */ } public void paint(Graphics g) { } public boolean action(Event event, Object obj) { if(!np.animating && !np.animated) { if(event.target == AddBox) { System.out.println("Add Button"); np.showOperation = "add"; np.graph2D = false; // np.showCalc = true; np.repaint(); } else if(event.target == SubtractBox) { System.out.println("Subtract Button"); np.showOperation = "subtract"; np.graph2D = false; // np.showCalc = true; np.repaint(); } else if(event.target == MultiplyBox) { System.out.println("Multiply Button"); np.showOperation = "multiply"; np.graph2D = true; // np.showCalc = true; np.repaint(); } else if(event.target == CalcButton) { System.out.println("Equals Button"); np.calculate(); } else if(event.target == Num1Box) { System.out.println("1st Number"); np.selectedVector = "num1"; } else if(event.target == Num2Box) { System.out.println("2nd Number"); np.selectedVector = "num2"; } } else //(np.animating || np.animated) { if(np.showOperation == "add") AddBox.setState(true); else if(np.showOperation == "subtract") SubtractBox.setState(true); else if(np.showOperation == "multiply") MultiplyBox.setState(true); if(np.selectedVector == "num1") Num1Box.setState(true); else if(np.selectedVector == "num2") Num2Box.setState(true); } if(event.target == ResetButton) { System.out.println("Reset Button"); resetApplet(); np.repaint(); } return true; } } // END NumberLine class ///////////////////////////////////////////////////// // // // NumberPanel // // // ///////////////////////////////////////////////////// //Ideas: Make the numberline a background so all whole // number points can be drawn quickly class NumberPanel extends Panel implements Runnable { Color myColor = new Color(255,255,200); Dimension panelSize = new Dimension(401,201); Dimension size = new Dimension(400,200); int centerX; int centerY; int curX; int curY; int border = 25; public String selectedVector; //'num1' || 'num2' public String showOperation; //'add' || 'subtract' || 'multiply' public String precision; //'int' || 'double' public boolean graph2D; //false = 1D (add/subtract); true = 2D (multiply) // public boolean showCalc; public boolean showResult; public boolean animateResult; VectorLine v1; VectorLine v2; int num1; int num2; int result; int graphMin, //Min unit shown on graph (used as left-most point. IMPORTANT for // calculating distances between points on the graph!!) graphMax, //Max unit shown on graph graphUnitsPerMark, //Number of units between the marks on the graph (initially 5) // (not necessarily the same as graphPixelsPerUnit, but can be) graphRange; //Range of numbers the graph should cover. This measures the spaces // between the marks, basically... The real range will be one more // than the range says. Ex: if graphRange==4 and graphMin==2, then // the graph will run from 2 -> 6... that's 2, 3, 4, 5, and 6: 5 // points on the graph. double graphPixelsPerUnit; //Number of actual pixels between units on the graph (initially 5) // double because it may not be exact. In fact, it probably won't be // an integer, since the factors of 350 are 2, 5, 5, and 7 // Factors of 350: 2, 5, 7, (10), 14, (25), (35), (50), (70), 175 Thread runner2; boolean animating, animated; private static final int MINMARKS = 2; //Must have a mark at each end private static final int MAXMARKS = 15; //Perfect for range of 70... //For extra precision, later on // double double_num1; // double double_num2; // Export Panel Size public Dimension getMinimumSize() {return panelSize;} public Dimension getPreferredSize() {return panelSize;} public NumberPanel() { setPanel(); } public void resetPanel() { stop(); //stop thread of execution setPanel(); //sets Panel back to defaults repaint(); //repaint the panel } private void setPanel() { centerX = size.width/2; centerY = size.height/2; curX = 0; curY = 0; setBackground(myColor); v1 = new VectorLine(centerX,centerY - 15); v2 = new VectorLine(centerX,centerY - 30); v1.setColor(Color.blue); v2.setColor(Color.red); selectedVector = "num1"; showOperation = "add"; precision = "int"; graph2D = false; showResult = false; animating = false; animated = false; num1 = 0; num2 = 0; graphMin = -35; graphMax = 35; graphPixelsPerUnit = 5; graphUnitsPerMark = 5; } public void paint(Graphics g) { if(graph2D == true) //used for multiplication drawGrid(g); else //used for addition/subtraction drawGrid(g); // Draw Vectors v1.show(g); v2.show(g); // Draw Frame g.setColor(Color.black); g.drawRect(0,0,size.width,size.height); // if(showCalc == true) // { String operator = " + "; if(showOperation == "add") operator = " + "; if(showOperation == "subtract") operator = " - "; if(showOperation == "multiply") operator = " x "; //Show calculation if (showResult == true) { // setFont(new Font()); g.drawString(num1+operator+num2+" = "+result,centerX,size.height-20); } else { // setFont(new Font()); g.drawString(num1+operator+num2+" = ",centerX,size.height-20); } // } // else //showCalc == false // { // g.drawString("Select an operation",centerX,size.height-20); // } } public void drawGrid(Graphics g) { g.setColor(Color.black); g.drawLine(border,centerY,size.width-border,centerY); g.drawLine(border,centerY+1,size.width-border,centerY+1); for (int i = graphMin;i<=graphMax;i+=graphUnitsPerMark) { int tempint = toCoord(i); // if (i%5 == 0) // { g.drawLine(tempint,centerY-5,tempint,centerY+5); if (i < 0) { if (i > -10) g.drawString(""+i,tempint-7,centerY+20); else //i < -10 g.drawString(""+i,tempint-10,centerY+20); } else //i >= 0 { if (i < 10) g.drawString(""+i,tempint-3,centerY+20); else //i > 10 g.drawString(""+i,tempint-7,centerY+20); } // } // else // i is not a multiple of 5 // { // g.drawLine(tempint,centerY-2,tempint,centerY+2); // } } } public boolean mouseDown(Event evt, int x, int y) { System.out.println("x:"+x+"\ty: "+y); if(!animating && !animated) { snapToGrid(x,y); System.out.println("X: "+curX+" Y: "+curY); if(selectedVector == "num1") v1.setEnd(curX,curY); else //if (selectedVector == "num2") v2.setEnd(curX,curY); repaint(); } return true; } public boolean mouseDrag(Event evt, int x, int y) { if(!animating && !animated) { snapToGrid(x,y); System.out.println("X: "+curX+" Y: "+curY); if(selectedVector == "num1") v1.setEnd(curX,curY); else //if (selectedVector == "num1") v2.setEnd(curX,curY); repaint(); } return true; } private void snapToGrid(int x,int y) { curX = x; curY = y; if(precision == "int") { if(x < border) curX = border; else if (x > size.width-border) curX = size.width-border; else { /* if((x%5 == 1) || (x%5 == 2)) curX = (x/5) * 5; else //x%5 == 3 || x%5 ==4 curX = ((x/5) + 1) * 5; */ if(x % graphPixelsPerUnit < graphPixelsPerUnit/2) curX = (x/graphPixelsPerUnit) * graphPixelsPerUnit; else //(x % graphPixelsPerUnit >= graphPixelsPerUnit/2) curX = ((x/graphPixelsPerUnit) + 1) * graphPixelsPerUnit; } } if(selectedVector == "num1") num1 = (curX - centerX)/graphPixelsPerUnit; else //selectedVector == "num2" num2 = (curX - centerX)/graphPixelsPerUnit; } public int toCoord(int x) { //int range = 30; //int unitScale = (centerX*range); return graphPixelsPerUnit*x+centerX; } public void calculate() { showResult = true; animateResult = true; // showCalc = true; if(showOperation == "add") { result = num1 + num2; } else if(showOperation == "subtract") { result = num1 - num2; } else if(showOperation == "multiply") { result = num1 * num2; } repaint(); start(); } private void animateResult() { } //Threading stuff public void start() { runner2 = new Thread(this); runner2.start(); } public void stop() { if (runner2 != null) { runner2.stop(); //stop is unsafe!!!!!!!!! runner2 = null; } } public void run() { Thread thisThread = Thread.currentThread(); while(animateResult) { animating = true; try { thisThread.sleep(400); } catch (InterruptedException e) {} if(result > graphMax) { //animate movement of numberline to the left if result > 35 while(graphMax < result) { graphMax+=graphUnitsPerMark; graphMin+=graphUnitsPerMark; try {Thread.sleep(100); } catch (InterruptedException e){} repaint(); } } else if (result < graphMin) { //animate movement of numberline to the right if result < 35 } if(showOperation == "add") { int v2tail = v2.tailx, v1end = v1.x, diff = v1end - v2tail; if(diff > 0) { for(;diff > 0;diff--) { v2.moveRight(1); try {Thread.sleep(50); } catch (InterruptedException e){} repaint(); } animated = true; } else if(diff < 0) { for(;diff < 0;diff++) { v2.moveLeft(1); try {Thread.sleep(50); } catch (InterruptedException e){} repaint(); } animated = true; } } else if(showOperation == "subtract") { int v2tail = v2.tailx, v2end = v2.x, v1end = v1.x, diff = v1end - v2end; if(diff > 0) { for(;diff > 0;diff--) { v2.moveRight(1); try {Thread.sleep(50); } catch (InterruptedException e){} repaint(); } animated = true; } else if(diff < 0) { for(;diff < 0;diff++) { v2.moveLeft(1); try {Thread.sleep(50); } catch (InterruptedException e){} repaint(); } animated = true; } } else if(showOperation == "multiply") { } animating = false; animateResult = false; repaint(); } } // End Run } // END NumberPanel class ///////////////////////////////////////////////////// // // // VectorLine // // // ///////////////////////////////////////////////////// class VectorLine { public int x, y, tailx, taily; /* int border = 20, width = 400, height = 200; */ double double_tailx, double_taily; boolean valid; String precision; Dimension size = new Dimension(401,201); int centerX; int centerY; Color vectorColor = Color.black; public VectorLine(int tailx,int taily) { valid = false; setTail(tailx,taily); precision= "int"; centerX = size.width/2; centerY = size.height/2; } public VectorLine(int tailx,int taily,Dimension size) { valid = false; setTail(tailx,taily); this.size = size; precision= "int"; centerX = size.width/2; centerY = size.height/2; } public VectorLine(double double_tailx,double double_taily) { valid = false; setTail(double_tailx,double_taily); precision = "double"; centerX = size.width/2; centerY = size.height/2; } public VectorLine(double double_tailx,double double_taily,Dimension size) { valid = false; setTail(double_tailx,double_taily); this.size = size; precision = "double"; centerX = size.width/2; centerY = size.height/2; } public boolean isValid() { //used when trying to perform an operation on the numberline... if all vectors aren't valid, // then reject the operation return valid; } public void setColor(Color color) { vectorColor = color; } public void setEnd(int x, int y) { this.x = x; this.y = y; valid = true; } public void setTail(int tailx, int taily) { this.tailx = tailx; this.taily = taily; //valid = true; } public void setTail(double double_tailx, double double_taily) { this.double_tailx = double_tailx; this.double_taily = double_taily; valid = true; } public void set(double x, double y) { //this.x = Math.round(); } public void show(Graphics g) { if (isValid()) { g.setColor(vectorColor); drawArrow(tailx,taily,x,taily,g); } } public void moveRight(int increment) { x += increment; tailx += increment; } public void moveLeft(int increment) { x -= increment; tailx -= increment; } public void drawArrow(int x1, int y1, int x2, int y2, Graphics g) { double d = Math.atan((float)((double)(y1 - y2) / (double)(x1 - x2))); if(x1 - x2 < 0) d += 3.1415926535897931D; g.drawLine(x1, y1, x2, y2); g.drawLine(x2, y2, x2 + (int)(Math.cos(d + 0.29999999999999999D) * 10D), y2 + (int)(Math.sin(d + 0.29999999999999999D) * 10D)); g.drawLine(x2, y2, x2 + (int)(Math.cos(d - 0.29999999999999999D) * 10D), y2 + (int)(Math.sin(d - 0.29999999999999999D) * 10D)); } public void drawArc() { //Draw an arc from (tailx,taily) --> (x,taily) //Have: chord, altitude from chord to top of circle //Need to calculate: bounding rectangle, center of circle, arc to show } } // END VectorLine class