Project

General

Profile

Revision 701

Code cleanup; added class for constant defs; click-in-boundary checking

View differences:

trunk/code/projects/colonet/client/ColonetConstants.java
1

  
2
public class ColonetConstants {
3

  
4
  // Used for painting circles around the robots
5
  public static final int ROBOT_RADIUS = 30;
6

  
7
  // Used for the robot controller panel
8
  public static final int VECTOR_CONTROLLER_HEIGHT = 190;
9
  public static final int VECTOR_CONTROLLER_WIDTH = 320;
10
  
11
  // Used for webcam image
12
  public static final int WEBCAM_BORDER = 16;
13
	public static final int BATTERY_WIDTH = 50;
14
	public static final int BATTERY_HEIGHT = 10;
15
	public static final int WEBCAM_DELAY = 100;
16
	public static final String WEBCAM_PATH = "http://roboclub9.frc.ri.cmu.edu/colonet.jpg";
17

  
18
  // Set the default look and feel - choose one
19
  public static final String LOOK_AND_FEEL = javax.swing.UIManager.getSystemLookAndFeelClassName();
20
  //public static final String LOOK_AND_FEEL = javax.swing.UIManager.getCrossPlatformLookAndFeelClassName();
21
  //public static final String LOOK_AND_FEEL = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
22

  
23
}
trunk/code/projects/colonet/client/Colonet.java
17 17
*/
18 18
public class Colonet extends JApplet implements ActionListener, MouseInputListener, KeyListener {
19 19

  
20
	// Used for painting
21
	final int BUFFER = 50;
22
	final int RADIUS = 30;
23

  
24
	// Used for the robot controller
25
	final int VECTOR_CONTROLLER_HEIGHT = 190;
26
	final int VECTOR_CONTROLLER_WIDTH = 320;
27

  
28 20
	// Connection
29 21
	JTextField txtHost;
30 22
	JTextField txtPort;
......
93 85
	volatile ColonetServerInterface csi;
94 86

  
95 87
	public void init () {
96
		// Set the default look and feel - choose one
97
		String laf = UIManager.getSystemLookAndFeelClassName();
98
		//String laf = UIManager.getCrossPlatformLookAndFeelClassName();
99
		//String laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
88
		// Set the default look and feel
89
		String laf = ColonetConstants.LOOK_AND_FEEL;
100 90
		try {
101 91
			UIManager.setLookAndFeel(laf);
102 92
		} catch (UnsupportedLookAndFeelException exc) {
......
188 178
		panelRobotDirectionButtons.add(btnL);
189 179
		panelRobotDirectionButtons.add(btnR);
190 180

  
191
		imageVectorControl = gc.createCompatibleImage(VECTOR_CONTROLLER_WIDTH, VECTOR_CONTROLLER_HEIGHT);
181
		imageVectorControl = gc.createCompatibleImage(ColonetConstants.VECTOR_CONTROLLER_WIDTH, ColonetConstants.VECTOR_CONTROLLER_HEIGHT);
192 182
		vectorController = new VectorController(imageVectorControl, self);
193 183
		panelRobotDirection.setLayout(new BorderLayout());
194 184
		panelRobotDirection.add(vectorController, BorderLayout.CENTER);
......
267 257
		panelControl.setLayout(new GridLayout(1,1));
268 258
		tabPaneControl = new JTabbedPane(JTabbedPane.TOP);
269 259
		tabPaneControl.setFont(new Font("arial", Font.PLAIN, 16));
270
		tabPaneControl.setPreferredSize(new Dimension(VECTOR_CONTROLLER_WIDTH, 0));
260
		tabPaneControl.setPreferredSize(new Dimension(ColonetConstants.VECTOR_CONTROLLER_WIDTH, 0));
271 261
		tabPaneControl.addTab("Connection", panelServerInterface);
272 262
		tabPaneControl.addTab("Robots", panelRobotControl);
273 263
		//tabPaneControl.addTab("Tasks", panelTaskManager);
......
407 397
      public void run () {
408 398
        btnConnect.setText("Disconnect");
409 399
        lblConnectionStatus.setText("Status: Connected");
410
          btnF.setEnabled(true);
411
          btnB.setEnabled(true);
412
          btnL.setEnabled(true);
413
          btnR.setEnabled(true);
414
          btnActivate.setEnabled(true);
415
          btnAssignID.setEnabled(true);
416
          btnSetBounds.setEnabled(true);
417
          btnClearBounds.setEnabled(true);
418
          btnCommand_MoveTo.setEnabled(true);
419
          btnCommand_MoveAll.setEnabled(true);
400
        btnF.setEnabled(true);
401
        btnB.setEnabled(true);
402
        btnL.setEnabled(true);
403
        btnR.setEnabled(true);
404
        btnActivate.setEnabled(true);
405
        btnAssignID.setEnabled(true);
406
        btnSetBounds.setEnabled(true);
407
        btnClearBounds.setEnabled(true);
408
        btnCommand_MoveTo.setEnabled(true);
409
        btnCommand_MoveAll.setEnabled(true);
420 410
      }
421 411
    };
422 412
    SwingUtilities.invokeLater(r);
......
432 422
	        public void run () {
433 423
		        btnConnect.setText("Connect");
434 424
	            lblConnectionStatus.setText("Status: Disconnected");
435
                btnF.setEnabled(false);
436
                btnB.setEnabled(false);
437
                btnL.setEnabled(false);
438
                btnR.setEnabled(false);
439
                btnActivate.setEnabled(false);
440
                btnAssignID.setEnabled(false);
441
                btnSetBounds.setEnabled(false);
442
                btnClearBounds.setEnabled(false);
443
                btnCommand_MoveTo.setEnabled(false);
444
                btnCommand_MoveAll.setEnabled(false);
425
              btnF.setEnabled(false);
426
              btnB.setEnabled(false);
427
              btnL.setEnabled(false);
428
              btnR.setEnabled(false);
429
              btnActivate.setEnabled(false);
430
              btnAssignID.setEnabled(false);
431
              btnSetBounds.setEnabled(false);
432
              btnClearBounds.setEnabled(false);
433
              btnCommand_MoveTo.setEnabled(false);
434
              btnCommand_MoveAll.setEnabled(false);
445 435
		    }
446 436
		};
447 437
		SwingUtilities.invokeLater(r);
......
500 490
	*/
501 491
	public void parseBattery (String line) {
502 492
	    int botNum, level;
503
	    System.out.println("Got battery update:" + line);
504 493
	    try {
505 494
		    String [] str = line.split(" ");
506 495
		    botNum = Integer.parseInt(str[2]);
......
577 566
	public void mousePressed(MouseEvent e) {
578 567
		//Start a new Thread to handle the MouseEvent
579 568
		(new MouseHandler(e)).start();
580
		repaint();
581 569
	}
582 570
	public void mouseExited(MouseEvent e) {
583 571
	}
......
585 573
	}
586 574
	public void mouseReleased(MouseEvent e) {
587 575
    (new MouseHandler(e)).start();
588
		repaint();
589 576
	}
590 577
	public void mouseClicked(MouseEvent e) {
591 578
	}
592 579
	public void mouseDragged(MouseEvent e) {
593 580
    (new MouseHandler(e)).start();
594
		repaint();
595 581
	}
596 582
	public void mouseMoved(MouseEvent e) {
597 583
	}
......
631 617

  
632 618
			// If we are selecting a waypoint (destination) for a specific bot
633 619
			if (setWaypoint && setWaypointID >= 0 && e.getID() == MouseEvent.MOUSE_PRESSED) {
620
			  // If the user clicks outside the boundary, do nothing
621
			  if (boundary.isActive() && !boundary.contains(e.getX(), e.getY())) {
622
			    return;
623
			  }
634 624
				setWaypoint = false;
635 625
				panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
636 626
				if (selectedBot < 0) {
......
651 641
			// Right-click also means we are moving a robot
652 642
			if ((e.getButton() == MouseEvent.BUTTON2 || e.getButton() == MouseEvent.BUTTON3)  
653 643
          && e.getID() == MouseEvent.MOUSE_PRESSED) {
644
        // If the user clicks outside the boundary, do nothing
645
			  if (boundary.isActive() && !boundary.contains(e.getX(), e.getY())) {
646
			    return;
647
			  }
654 648
				if (selectedBot < 0) {
655 649
					return;
656 650
				}
......
668 662

  
669 663
			// If we are setting all waypoints
670 664
			if (setWaypoint && e.getID() == MouseEvent.MOUSE_PRESSED) {
665
			  // If the user clicks outside the boundary, do nothing
666
			  if (boundary.isActive() && !boundary.contains(e.getX(), e.getY())) {
667
			    return;
668
			  }
671 669
				setWaypoint = false;
672 670
				panelWebcam.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
673 671
				for (Map.Entry<Integer,RobotIcon> entry : robotIcons.entrySet()) {
......
885 883
									int id = r.id;
886 884
										if (id >= 0) {
887 885
										csi.sendBatteryRequest(id);
888
										System.out.println("Sent battery request (" + id + ")");
889 886
									}
890 887
							}
891 888
						}
......
907 904

  
908 905
	/*
909 906
	* WebcamPanel class
910
	* Enables more efficient image handling in a component-controlled environment
907
	* Contains the webcam image
911 908
	*/
912 909
	class WebcamPanel extends JPanel {
913
		final int BORDER = 16;	// this is arbitrary. it makes the image look nice inside a border.
914
		final int BATTERY_WIDTH = 50;
915
		final int BATTERY_HEIGHT = 10;
910

  
916 911
		volatile BufferedImage img;
917 912
		BufferedImage buffer;
918 913

  
......
935 930
			}
936 931

  
937 932
			// Calculate scaling
938
			int maxWidth = getWidth() - 2*BORDER;
939
			int maxHeight = getHeight() - 2*BORDER;
933
			int maxWidth = getWidth() - 2*ColonetConstants.WEBCAM_BORDER;
934
			int maxHeight = getHeight() - 2*ColonetConstants.WEBCAM_BORDER;
940 935
			double widthRatio = 1.0 * maxWidth / img.getWidth();
941 936
			double heightRatio = 1.0 * maxHeight / img.getHeight();
942 937
			double scale = 0;
......
949 944
				scale = heightRatio;
950 945
				newHeight = maxHeight;
951 946
				newWidth = (int) (img.getWidth() * scale);
952
				y = BORDER;
953
				x = (maxWidth - newWidth) / 2 + BORDER;
947
				y = ColonetConstants.WEBCAM_BORDER;
948
				x = (maxWidth - newWidth) / 2 + ColonetConstants.WEBCAM_BORDER;
954 949
			} else {	//width is the limiting factor
955 950
				scale = widthRatio;
956 951
				newWidth = maxWidth;
957 952
				newHeight = (int) (img.getHeight() * scale);
958
				x = BORDER;
959
				y = (maxHeight - newHeight) / 2 + BORDER;
953
				x = ColonetConstants.WEBCAM_BORDER;
954
				y = (maxHeight - newHeight) / 2 + ColonetConstants.WEBCAM_BORDER;
960 955
			}
961 956

  
962 957
			// Draw image onto the buffer
......
967 962
			Image imgScaled = img.getScaledInstance(newWidth, newHeight, Image.SCALE_FAST);
968 963
			bufferedGraphics.drawImage(imgScaled, x, y, this);
969 964

  
970
            // Draw boundary
971
            if (boundary.set || boundary.active) {
972
               bufferedGraphics.setColor(Color.BLUE);
973
               int width = boundary.panel_p2.x - boundary.panel_p1.x;
974
               int height = boundary.panel_p2.y - boundary.panel_p1.y;
975
               bufferedGraphics.drawRect(boundary.panel_p1.x, boundary.panel_p1.y, width, height);
976
            }
965
      // Draw boundary
966
      if (boundary.set || boundary.active) {
967
         bufferedGraphics.setColor(Color.BLUE);
968
         int width = boundary.panel_p2.x - boundary.panel_p1.x;
969
         int height = boundary.panel_p2.y - boundary.panel_p1.y;
970
         bufferedGraphics.drawRect(boundary.panel_p1.x, boundary.panel_p1.y, width, height);
971
      }
977 972

  
978 973
			// Draw Identifiers and battery levels
979 974
			if (robotIcons != null) {
......
984 979
					// Identifier circle
985 980
					int px = (int) (x + r.x * scale);
986 981
					int py = (int) (y + r.y * scale);
987
					bufferedGraphics.drawOval(px-RADIUS, py-RADIUS, 2*r.RADIUS, 2*r.RADIUS);
982
					int radius = ColonetConstants.ROBOT_RADIUS;
983
					bufferedGraphics.drawOval(px-radius, py-radius, 2*radius, 2*radius);
988 984
					// ID, if applicable
989 985
					if (r.id > 0) {
990 986
					    bufferedGraphics.setFont(new Font("arial", Font.PLAIN, 36));
......
992 988
					}
993 989
					// Battery
994 990
					if (r.battery >= 0) {
995
					    int pixels = r.battery * BATTERY_WIDTH / 100;
991
					    int pixels = r.battery * ColonetConstants.BATTERY_WIDTH / 100;
996 992
						if (r.battery > 50)
997 993
						    bufferedGraphics.setColor(Color.GREEN);
998 994
						else if (r.battery > 25)
999 995
						    bufferedGraphics.setColor(Color.YELLOW);
1000 996
						else
1001 997
						    bufferedGraphics.setColor(Color.RED);
1002
						bufferedGraphics.fillRect(px+20, py+20, pixels, BATTERY_HEIGHT);
998
						bufferedGraphics.fillRect(px+20, py+20, pixels, ColonetConstants.BATTERY_HEIGHT);
1003 999
						bufferedGraphics.setColor(Color.BLACK);
1004
						bufferedGraphics.drawRect(px+20, py+20, BATTERY_WIDTH, BATTERY_HEIGHT);
1000
						bufferedGraphics.drawRect(px+20, py+20, ColonetConstants.BATTERY_WIDTH, ColonetConstants.BATTERY_HEIGHT);
1005 1001
					}
1006 1002
					// If the robot has a destination, draw the vector
1007 1003
					if (r.destx >= 0) {
......
1015 1011
			if (r != null) {
1016 1012
				int px = (int) (x + r.x * scale);
1017 1013
				int py = (int) (y + r.y * scale);
1014
				int radius = ColonetConstants.ROBOT_RADIUS;
1018 1015
				bufferedGraphics.setColor(Color.BLACK);
1019
				bufferedGraphics.drawOval(px-RADIUS-6, py-RADIUS-6, 2*r.RADIUS+12, 2*r.RADIUS+12);
1016
				bufferedGraphics.drawOval(px-radius-6, py-radius-6, 2*radius+12, 2*radius+12);
1020 1017
			}
1021 1018

  
1022 1019
			//Display buffered content
......
1033 1030
			}
1034 1031

  
1035 1032
			// Calculate scaling
1033
			int border = ColonetConstants.WEBCAM_BORDER;
1036 1034
			int clickx = e.getX();
1037 1035
			int clicky = e.getY();
1038
			int maxWidth = getWidth() - 2*BORDER;
1039
			int maxHeight = getHeight() - 2*BORDER;
1036
			int maxWidth = getWidth() - 2*border;
1037
			int maxHeight = getHeight() - 2*border;
1040 1038
			double widthRatio = 1.0 * maxWidth / img.getWidth();
1041 1039
			double heightRatio = 1.0 * maxHeight / img.getHeight();
1042 1040
			double scale = 0;
......
1049 1047
				scale = heightRatio;
1050 1048
				newHeight = maxHeight;
1051 1049
				newWidth = (int) (img.getWidth() * scale);
1052
				py = clicky - BORDER;
1053
				px = clickx - BORDER - (maxWidth - newWidth) / 2;
1050
				py = clicky - border;
1051
				px = clickx - border - (maxWidth - newWidth) / 2;
1054 1052
			} else {	//width is the limiting factor
1055 1053
				scale = widthRatio;
1056 1054
				newWidth = maxWidth;
1057 1055
				newHeight = (int) (img.getHeight() * scale);
1058
				px = clickx - BORDER;
1059
				py = clicky - BORDER - (maxHeight - newHeight) / 2;
1056
				px = clickx - border;
1057
				py = clicky - border - (maxHeight - newHeight) / 2;
1060 1058
			}
1061 1059
			py = (int) (py / scale);
1062 1060
			px = (int) (px / scale);
......
1071 1069
	*/
1072 1070
	class WebcamLoader extends Thread
1073 1071
	{
1074
		final int WEBCAMLOADER_DELAY = 100;
1075
		final String IMAGE_PATH = "http://roboclub9.frc.ri.cmu.edu/colonet.jpg";
1076

  
1077 1072
		URL imagePath;
1078

  
1079 1073
		MediaTracker mt;
1080 1074
		BufferedImage image;
1081 1075
		Random rand;
......
1092 1086
		{
1093 1087
			while (true) {
1094 1088
				try {
1095
					Thread.sleep(WEBCAMLOADER_DELAY);
1089
					Thread.sleep(ColonetConstants.WEBCAM_DELAY);
1096 1090
					if (image != null)
1097 1091
						image.flush();
1098 1092
					System.gc();
1099 1093
					try {
1100
						imagePath = new URL(IMAGE_PATH + "?rand=" + rand.nextInt(100000));
1094
						imagePath = new URL(ColonetConstants.WEBCAM_PATH + "?rand=" + rand.nextInt(100000));
1101 1095
					} catch (MalformedURLException e) {
1102
						System.out.println("Malformed URL: could not form URL from: [" + IMAGE_PATH + "]\n");
1096
						System.out.println("Malformed URL: could not form URL from: [" + ColonetConstants.WEBCAM_PATH + "]\n");
1103 1097
					}
1104 1098
					image = ImageIO.read(imagePath);
1105 1099
					// The MediaTracker waitForID pauses the thread until the image is loaded.
......
1144 1138
          csi.sendBoundary(img_p1.x, img_p1.y, img_p2.x, img_p2.y);
1145 1139
      }
1146 1140
    }
1141
    
1142
    public boolean isActive () {
1143
      return active;
1144
    }
1145
    
1146
    public boolean isSet () {
1147
      return set;
1148
    }
1149
    
1150
    /**
1151
    *  Returns a Rectangle designating the active area 
1152
    *  in the coordinate system of the JPanel.
1153
    *  Returns null if the boundary is not active.
1154
    */
1155
    public Rectangle toPanelRect () {
1156
      if (!active)
1157
        return null;
1158
      return new Rectangle (panel_p1.x, panel_p1.y, (panel_p2.x-panel_p1.x), (panel_p2.y-panel_p1.y));
1159
    }
1160
    
1161
    /** 
1162
    *  Determines whether a coordinate in the coordinate
1163
    *  system of the JPanel is contained within the boundary.
1164
    *  If the boundary is not active, then this method 
1165
    *  returns false.
1166
    */
1167
    public boolean contains (int x, int y) {
1168
      Rectangle rect = this.toPanelRect();
1169
      if (rect == null || !this.active)
1170
        return false;
1171
      return rect.contains(x,y);
1172
    }
1173
        
1147 1174
  }
1148 1175

  
1149 1176
}
trunk/code/projects/colonet/client/RobotIcon.java
14 14
*	 Provides a means for graphically representing and keeping track of webcam bots.
15 15
*/
16 16
public class RobotIcon {
17
	public final int RADIUS = 30;
18
	public final int CLOSE = 80;
19 17

  
20 18
	public int x, y;
21 19
	public int destx, desty;
......
43 41
	}
44 42

  
45 43
	/**
46
	*	 Determines if a given point is within a reasonable range of the current location
47
	*	 to be considered the same robot when moving. The threshold is determined by the
48
	*	 CLOSE value.
49
	*
50
	*	 @return Whether or not the given point is reasonably close to the current location.
51
	*
52
	*/
53
	public boolean isClose (int nx, int ny) {
54
		int dist = (int) Point.distance(this.x, this.y, nx, ny);
55
		return (dist < CLOSE);
56
	}
57

  
58
	/**
59 44
	*	 Determines whether a given point is within the rectangle that circumscribes the
60 45
	*	 robot's circlular icon. Used for clicking on robots in webcam view.
61 46
	*
62 47
	*/
63 48
	public boolean contains (int px, int py) {
64
		Rectangle rect = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS);
49
	int radius = ColonetConstants.ROBOT_RADIUS;
50
		Rectangle rect = new Rectangle(x-radius, y-radius, 2*radius, 2*radius);
65 51
		return rect.contains(px, py);
66 52
	}
67 53

  

Also available in: Unified diff