Project

General

Profile

Revision 32

Added by Greg Tress over 16 years ago

added new xcode project files

View differences:

trunk/code/projects/colonet/ColonetGUI/build/Colonet.build/Colonet.build/JavaFileList
1
"Colonet.java"
2
"ColonetServerInterface.java"
trunk/code/projects/colonet/ColonetGUI/build/Colonet
1
link /Users/gmtress/Documents/Colony/roboclub_repository/colony/trunk/code/projects/colonet/ColonetGUI/build/Colonet.jar
0 2

  
trunk/code/projects/colonet/ColonetGUI/Colonet.java
1
//
2
//  Colonet.java
3
//
4

  
5
import javax.swing.*;
6
import java.awt.*;
7
import java.awt.image.*;
8
import java.awt.event.*;
9
import java.net.*;
10
import java.io.*;
11
import java.util.Random;
12
import java.applet.*;
13

  
14
public class Colonet extends JApplet implements ActionListener, MouseListener, Runnable {
15

  
16
	final int CANVAS_SIZE = 500;  //don't make this too large, or the applet will be slow.
17
	final int BUFFER = 50;
18
	final int RADIUS = 30;
19

  
20
	// Connection
21
	JTextField txtHost;				
22
	JTextField txtPort;				
23
	JButton btnConnect;	
24
	JButton btnGraph;
25
	JLabel lblConnectionStatus;
26
	JTextArea txtInput;
27
	JTextArea txtInfo; 
28
	JPanel panelConnect;
29
	JPanel panelServerInterface;
30
	
31
	// Stats
32
	JLabel lblBattery;
33
	JLabel lblTokenPasses;
34
	JLabel lblHastToken;
35
	JPanel panelStats;
36
	
37
	// South
38
	JPanel panelSouth;
39
	JTextArea log;
40
	JScrollPane spLog;
41
	
42
	// Control
43
	JPanel panelControl;
44
	JTabbedPane tabPaneControl;
45
	JPanel panelRobotControl;
46
	JPanel panelRobotDirection;
47
	JPanel panelRobotCommands;
48
	JButton btnF, btnB, btnL, btnR, btnActivate;
49
	
50
	// Task Manager
51
	JPanel panelTaskManager;
52
	JScrollPane spTaskManager;
53
	JPanel panelTaskManagerControls;
54
	JPanel panelTaskManagerControlsPriority;
55
	DefaultListModel taskListModel;
56
	JList taskList;
57
	JButton btnAddTask;
58
	JButton btnRemoveTask;
59
	JButton btnMoveTaskUp;
60
	JButton btnMoveTaskDown;
61
	
62
	// Graphics
63
	JPanel panel;
64
	GraphicsConfiguration gc;
65
	volatile BufferedImage image;
66
	volatile Graphics2D canvas;
67
	int cx, cy;
68
	
69
	Socket socket;					
70
	OutputStreamWriter out;			//TODO: add a BufferedWriter
71
	DataListener datalistener;  
72
	
73
	Font botFont;
74
	Random random = new Random();
75
	volatile int tokenLoc;  //the token is currently here
76
	volatile int numBots;
77
	volatile int selectedBot;  //the user has selected this bot
78
	volatile Rectangle[] botRect;  //contains boundary shapes around bots for click detection
79
	
80
	Thread drawThread;
81
	SelectionIndicator indicator;
82
	PacketMonitor packetMonitor;
83

  
84
	
85
	public void init () {
86
		// set the default look and feel
87
        String laf = UIManager.getSystemLookAndFeelClassName();
88
        try {
89
            UIManager.setLookAndFeel(laf);
90
        } catch (UnsupportedLookAndFeelException exc) {
91
            System.err.println ("Warning: UnsupportedLookAndFeel: " + laf);
92
        } catch (Exception exc) {
93
            System.err.println ("Error loading " + laf + ": " + exc);
94
        }
95
		// We should invoke and wait to avoid browser display difficulties
96
		Runnable r = new Runnable() {
97
			public void run() {
98
				createAndShowGUI();
99
			}
100
		};
101
		try {
102
			SwingUtilities.invokeAndWait(r);
103
		} catch (InterruptedException e) {
104
			//Not really sure why we would be in this situation
105
			System.out.println(e);
106
		} catch (java.lang.reflect.InvocationTargetException e) {
107
			//This should never happen. Seriously.
108
			System.out.println(e);
109
		}
110
	}
111
	
112
	public void destroy () {
113
		try { drawThread.interrupt(); } catch (Exception e) { }
114
		try { indicator.interrupt(); } catch (Exception e) { }
115
		try { packetMonitor.interrupt(); } catch (Exception e) { }
116
	}
117

  
118
	private synchronized void createAndShowGUI () {
119
		// init graphical elements
120
		panel = new JPanel(false);  //set automatic double-buffering to false. we are doing it manually.
121
		
122
		// Connection area
123
		txtInput = new JTextArea("- 9 3 - 1\n- - - 5 -\n4 - - - 2\n- - - - -\n1 - - 3 -");
124
		txtInput.setBorder(BorderFactory.createTitledBorder("Input Matrix"));
125
		txtInfo = new JTextArea();
126
		txtInfo.setBorder(BorderFactory.createTitledBorder("Info"));
127
		txtInfo.setEditable(false);
128
		btnGraph = new JButton("Run");
129
		txtHost = new JTextField("roboclub1.frc.ri.cmu.edu");
130
		txtHost.setBorder(BorderFactory.createTitledBorder("Host"));
131
		txtPort = new JTextField("10123");
132
		txtPort.setBorder(BorderFactory.createTitledBorder("Port"));
133
		btnConnect = new JButton("Connect");
134
		lblConnectionStatus = new JLabel("Status: Offline");
135
		panelConnect = new JPanel();
136
		panelConnect.setLayout(new GridLayout(6,1));
137
		panelConnect.add(lblConnectionStatus);
138
		panelConnect.add(txtHost);
139
		panelConnect.add(txtPort);
140
		panelConnect.add(btnConnect);
141
		panelConnect.add(txtInfo);
142
		panelConnect.add(btnGraph);
143
		panelServerInterface = new JPanel();
144
		panelServerInterface.setLayout(new GridLayout(2,1));
145
		panelServerInterface.add(panelConnect);
146
		panelServerInterface.add(txtInput);
147
				
148
		// Status Elements
149
		lblTokenPasses = new JLabel();
150
		lblBattery = new JLabel("???");
151
		panelStats = new JPanel();
152
		panelStats.setLayout(new GridLayout(4,2));
153
		panelStats.add(new JLabel("Token Passes / sec          "));
154
		panelStats.add(lblTokenPasses);
155
		panelStats.add(new JLabel("Battery     "));
156
		panelStats.add(lblBattery);
157
		panelStats.add(new JLabel("Token Passes / sec     "));
158
		panelStats.add(lblTokenPasses);
159
		
160
		//TODO: add panelStats somewhere!
161

  
162
		// Robot direction panel
163
		panelRobotDirection = new JPanel();
164
		btnF = new JButton("^");
165
		btnB = new JButton("v");
166
		btnL = new JButton("<");
167
		btnR = new JButton(">");
168
		btnActivate = new JButton("o");
169
		panelRobotDirection = new JPanel();
170
		panelRobotDirection.setLayout(new GridLayout(3,3));
171
		panelRobotDirection.add(new JLabel(""));
172
		panelRobotDirection.add(btnF);
173
		panelRobotDirection.add(new JLabel(""));
174
		panelRobotDirection.add(btnL);
175
		panelRobotDirection.add(btnActivate);
176
		panelRobotDirection.add(btnR);
177
		panelRobotDirection.add(new JLabel(""));
178
		panelRobotDirection.add(btnB);
179
		panelRobotDirection.add(new JLabel(""));
180
		
181
		// Robot Control and Commands
182
		panelRobotCommands = new JPanel();
183
		panelRobotCommands.setLayout(new FlowLayout());
184
		panelRobotCommands.add(new JLabel("Commands go here"));
185
		panelRobotControl = new JPanel();
186
		panelRobotControl.setLayout(new GridLayout(2,1));
187
		panelRobotControl.add(panelRobotDirection);
188
		panelRobotControl.add(panelRobotCommands);
189
		
190
		// Task Manager
191
		panelTaskManager = new JPanel();
192
		panelTaskManager.setLayout(new BorderLayout());
193
		taskListModel = new DefaultListModel();
194
		taskListModel.addElement("Map the Environment");
195
		taskListModel.addElement("Clean Up Chemical Spill");
196
		taskListModel.addElement("Grow Plants");
197
		taskListModel.addElement("Save the Cheerleader");
198
		taskListModel.addElement("Save the World");
199
		taskList = new JList(taskListModel);
200
		taskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
201
		taskList.setSelectedIndex(0);
202
		spTaskManager = new JScrollPane(taskList);
203
		panelTaskManagerControls = new JPanel();
204
		panelTaskManagerControls.setLayout(new GridLayout(1,3));
205
		panelTaskManagerControlsPriority = new JPanel();
206
		panelTaskManagerControlsPriority.setLayout(new GridLayout(1,2));
207
		btnAddTask = new JButton("Add...");
208
		btnRemoveTask = new JButton("Remove");
209
		btnMoveTaskUp = new JButton("^");
210
		btnMoveTaskDown = new JButton("v");
211
		panelTaskManagerControlsPriority.add(btnMoveTaskUp);
212
		panelTaskManagerControlsPriority.add(btnMoveTaskDown);
213
		panelTaskManagerControls.add(btnAddTask);
214
		panelTaskManagerControls.add(btnRemoveTask);
215
		panelTaskManagerControls.add(panelTaskManagerControlsPriority);
216
		panelTaskManager.add(spTaskManager, BorderLayout.CENTER);
217
		panelTaskManager.add(panelTaskManagerControls, BorderLayout.SOUTH);
218
		panelTaskManager.add(new JLabel("Current Task Queue"), BorderLayout.NORTH);
219
		
220
		// Message log
221
		log = new JTextArea();
222
		spLog = new JScrollPane(log,
223
			ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 
224
			ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
225
		spLog.setBorder(BorderFactory.createTitledBorder("Log"));
226
		spLog.setPreferredSize(new Dimension(0, 150));
227
		log.setEditable(false);
228
		
229
		// Main control mechanism
230
		panelControl = new JPanel();
231
		panelControl.setLayout(new GridLayout(1,1));
232
		tabPaneControl = new JTabbedPane(JTabbedPane.TOP);
233
		tabPaneControl.setPreferredSize(new Dimension(300, 0));
234
		tabPaneControl.addTab("Connection", panelServerInterface);
235
		tabPaneControl.addTab("Robots", panelRobotControl);
236
		tabPaneControl.addTab("Tasks", panelTaskManager);
237
		panelControl.add(tabPaneControl);
238
		
239
		// Set up elements in the south
240
		panelSouth = new JPanel();
241
		panelSouth.setLayout(new GridLayout(1,2));
242
		panelSouth.add(spLog);
243

  
244
		this.getContentPane().setLayout(new BorderLayout());
245
		this.getContentPane().add(panel, BorderLayout.CENTER);
246
		this.getContentPane().add(panelSouth, BorderLayout.SOUTH);
247
		this.getContentPane().add(panelControl, BorderLayout.EAST);
248
		this.setVisible(true);
249
		
250
		btnAddTask.addActionListener(this);
251
		btnRemoveTask.addActionListener(this);
252
		btnMoveTaskUp.addActionListener(this);
253
		btnMoveTaskDown.addActionListener(this);
254
		btnGraph.addActionListener(this);
255
		btnConnect.addActionListener(this);
256
		panel.addMouseListener(this);
257
		
258
		
259
		// Get the graphics configuration of the screen to create a buffer
260
		gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
261
			.getDefaultScreenDevice().getDefaultConfiguration();
262
		image = gc.createCompatibleImage(CANVAS_SIZE,CANVAS_SIZE);
263
		canvas = image.createGraphics();
264
		canvas.setStroke(new BasicStroke(2));  //set pen width
265
		
266
		// Calculate center of canvas
267
		cx = image.getWidth() / 2;
268
		cy = image.getHeight() / 2;
269
		
270
		botFont = new Font("Arial", Font.PLAIN, 30);
271
		tokenLoc = 0;
272
		numBots = 0;
273
		selectedBot = 0;
274
		
275
		// Set up dependent threads
276
		indicator = new SelectionIndicator(canvas);
277
		indicator.setRadius(RADIUS+3, 15);  //a tad more than the bot radius
278
		packetMonitor = new PacketMonitor();
279
		datalistener = new DataListener();
280
	
281
	}
282
	
283
	public synchronized void paint (Graphics g)
284
	{
285
		/*	First, redraw the graphical components in the applet. 
286
			This paint method overrides the built-in paint of the 
287
			JApplet, and we don't want to deal with redrawing the
288
			components manually. Fuck that shit. */
289
		super.paint(g);
290
		
291
		// Place the buffered image on the screen, inside the panel
292
		panel.getGraphics().drawImage(image, 0, 0, Color.WHITE, this);
293
		
294
	}
295
	
296
	public synchronized void update (Graphics g)
297
	{
298
		paint(g);
299
	}
300
	
301
	public void actionPerformed (ActionEvent e)
302
	{
303
		Object source = e.getSource();
304
		if (source == btnGraph) {
305
			btnGraph.setEnabled(false);
306
			lblConnectionStatus.setText("Simulating");
307
			
308
			//Start dependent threads
309
			drawThread = new Thread(this, "drawThread");
310
			drawThread.start();
311
			indicator.start();
312
			packetMonitor.start();
313
		} else if (source == btnConnect) {
314
			doSocket();
315
		} else if (source == btnRemoveTask) {
316
			try {
317
				taskListModel.remove(taskList.getSelectedIndex());
318
			} catch (ArrayIndexOutOfBoundsException ex) {
319
			}
320
		}
321
	}
322
	
323
	private void randomize ()
324
	{
325
		Random r = new Random();
326
		StringBuilder s = new StringBuilder();
327
		
328
		int count = r.nextInt(8) + 1;
329
		for (int i = 0; i < count; i++)
330
		{
331
			for (int j = 0; j < count; j++)
332
			{
333
				if (r.nextBoolean())	
334
					s.append("" + (r.nextInt(16) + 1));
335
				else 
336
					s.append("-");
337
				if (j != count-1)
338
					s.append(" ");
339
			}
340
			if (i != count-1) s.append("\n");
341
		}
342
		
343
		txtInput.setText(s.toString());
344
	}
345
	
346
	private void doSocket ()
347
	{
348
		//make sure hostname and port are valid
349
		if (txtHost.getText().equals("") || txtPort.getText().equals("")) {
350
			err("Please enter a hostname and port.");
351
			return;
352
		}
353
		int port = 0;
354
		try {
355
			port = Integer.parseInt(txtPort.getText());
356
		} catch (Exception e) {
357
			err("Invalid port");
358
			return;
359
		}
360
		
361
		//make sure we aren't already connected. if so, disconnect first.
362
		if (socket != null && socket.isConnected()) {
363
			try {
364
				out.close();
365
				socket.close();
366
			} catch (IOException e) {}
367
		}
368
		
369
		try {
370
			socket = new Socket(txtHost.getText(), port);
371
		} catch (UnknownHostException e) {
372
			err("Unknown Host Exception");
373
			return;
374
		} catch (IOException e) {
375
			err("IO Exception\n\n" + e);
376
			return;
377
		} catch (java.security.AccessControlException e) {
378
			err("Permission denied by java.security.AccessControlException."
379
			+"\n\nYou may only connect to the server from which this applet was loaded.");
380
			return;
381
		}
382
		if (socket == null || !socket.isConnected()) {
383
			err("Connection failed. Try connecting again.");
384
			return;
385
		}
386
		msg("Connected to " + txtHost.getText() + " on port " + port + "\n");
387
		lblConnectionStatus.setText("Online");
388
		try {
389
			out = new OutputStreamWriter(socket.getOutputStream());
390
		} catch (IOException e) {
391
			warn("Could not get OutputStream from socket connection.");
392
		}
393
	
394
	}
395
	
396
	public void drawRobot (int id, int x, int y) 
397
	{
398
		//save the bot in memory, so we can tell if we click on it later
399
		botRect[id] = new Rectangle(x-RADIUS, y-RADIUS, 2*RADIUS, 2*RADIUS);
400
	
401
		//draw the bot on the canvas
402
		canvas.setColor(Color.BLACK);
403
		canvas.drawOval(x-RADIUS, y-RADIUS, RADIUS*2, RADIUS*2);
404
		
405
		//draw the label
406
		canvas.setFont(botFont);
407
		canvas.drawString("" + id, x-10, y+10);
408
	}
409
	
410
	public void drawConnection (int start, int end, int radius, Color color)
411
	{
412
		final int ARROW_LENGTH = 18;
413
	
414
		double angle = 2.0 * Math.PI / numBots;
415
		int startx, starty, endx, endy;
416
		startx = cx - (int)(radius * Math.cos(start * angle));
417
		starty = cy - (int)(radius * Math.sin(start * angle));
418
		endx = cx - (int)(radius * Math.cos(end * angle));
419
		endy = cy - (int)(radius * Math.sin(end * angle));
420
		canvas.setColor(color);
421
		canvas.drawLine(startx, starty, endx, endy);
422
		
423
		//create arrow
424
		if (color.equals(Color.BLACK)) return;
425
		int big_dy = starty - endy;
426
		int big_dx = endx - startx;
427
		double theta = 0;
428
		if (big_dx == 0 && starty > endy) //pointing up
429
			theta = Math.PI/2;
430
		else if (big_dx == 0 && starty < endy) //pointing down 
431
			theta = 3*Math.PI/2;
432
		else if (big_dy == 0 && startx > endx) //pointing left
433
			theta = Math.PI;
434
		else if (big_dy == 0 && startx < endx) //pointing right
435
			theta = 0;
436
		else
437
			theta = Math.atan(1.0 * big_dy / big_dx);
438
		
439
		//create ploygon
440
		Polygon poly = new Polygon();
441
		int dx_arrow = Math.abs((int)(ARROW_LENGTH * Math.cos(theta)));
442
		int dy_arrow = Math.abs((int)(ARROW_LENGTH * Math.sin(theta)));
443
		int dy_half = (int)(ARROW_LENGTH/2 * Math.cos(theta));
444
		int dx_half = (int)(ARROW_LENGTH/2 * Math.sin(theta));
445
		int rx = (big_dx > 0) ? endx - dx_arrow : endx + dx_arrow;
446
		int ry = (big_dy > 0) ? endy + dy_arrow : endy - dy_arrow;
447
		//System.out.println("" + start + "->" + end + " : dx=" + big_dx + ",dy=" + big_dy + ",dy_arrow=" + dy_arrow + ",dx_arrow=" + dx_arrow + ",theta=" + theta + ",endx=" + endx + ",endy=" + endy + ",rx=" + rx + ",ry=" + ry);
448
		poly.addPoint(endx, endy);
449
		poly.addPoint(rx - dx_half, ry - dy_half);
450
		poly.addPoint(rx + dx_half, ry + dy_half);
451
		canvas.fillPolygon(poly);
452
	}
453
	
454
	public void run ()
455
	{
456
		while (true)
457
		{
458
			step();
459
			repaint();
460
			try { Thread.sleep(90); }
461
				catch (InterruptedException e) { return; }
462
		}
463
	}
464
	
465
	public void step () 
466
	{
467
		final int DIAMETER = image.getWidth() - 2*BUFFER;
468
		final int BIGRADIUS = DIAMETER / 2;
469
		final int TOKENRADIUS = 40;
470
		boolean valid;
471
	
472
		// clear image
473
		canvas.setColor(Color.WHITE);
474
		canvas.fillRect(0, 0, image.getWidth(), image.getHeight());
475
		
476
		// parse the matrix, to see what robots exist
477
		String [] rows = txtInput.getText().split("\n");
478
		numBots = rows.length;
479
		String [][] entries = new String[numBots][numBots];
480
		valid = true;
481
		for (int i = 0; i < numBots; i++) 
482
		{
483
			entries[i] = rows[i].split(" ");
484
			if (entries[i].length != rows.length) valid = false;
485
		}
486
		
487
		if (valid)
488
		{
489
			this.showStatus("Matrix OK");
490
			
491
			// draw robots and find which one is seleced
492
			double angle = 2.0 * Math.PI / numBots;
493
			canvas.setColor(Color.BLACK);
494
			botRect = new Rectangle[numBots];
495
			int x, y;
496
			if (selectedBot >= numBots) selectedBot = 0;
497
			for (int i = 0; i < numBots; i++)
498
			{
499
				x = cx - (int)(BIGRADIUS * Math.cos(i * angle));
500
				y = cy - (int)(BIGRADIUS * Math.sin(i * angle));
501
				drawRobot(i, x, y);
502
				if (i == selectedBot) indicator.setCenter(x, y);
503
			}
504
			
505
			// draw token marker
506
			int tokenx, tokeny;
507
			int tokenNum = tokenLoc;
508
			tokenx = cx - (int)(BIGRADIUS * Math.cos(tokenNum * angle));
509
			tokeny = cy - (int)(BIGRADIUS * Math.sin(tokenNum * angle));
510
			canvas.setColor(Color.RED);
511
			canvas.drawOval(tokenx-TOKENRADIUS, tokeny-TOKENRADIUS, 2*TOKENRADIUS, 2*TOKENRADIUS);
512
			
513
			// create an inner circle along which the connections are made.
514
			// let the diameter of this circle be 2*RADIUS less than the outerDiameter.
515
			// see what connections exist
516
			for (int row = 0; row < numBots; row++)
517
			{
518
				for(int col = 0; col < numBots; col++)
519
				{
520
					if (! entries[row][col].equals("-") && entries[col][row].equals("-") && row != col) //one-way
521
					{
522
						//drawConnection(row, col, BIGRADIUS-RADIUS, Color.GRAY);
523
						drawConnection(row, col, BIGRADIUS-RADIUS, new Color(200,200,200));
524
					}
525
					else if (! entries[row][col].equals("-") && ! entries[col][row].equals("-") && row != col) //two-way
526
					{
527
						drawConnection(row, col, BIGRADIUS-RADIUS, Color.BLACK);
528
					}
529
				}
530
			}
531
			
532
			// draw the selection indicator
533
			indicator.draw();
534
			txtInfo.setText("Packet statistics: ???");
535
			
536
		}
537
		else // if matrix is not valid
538
		{
539
			this.showStatus("Error: Invalid matrix");
540
		}
541
	
542
	}
543
	
544
	/*	At this point, moveToken is only called by the simulator.
545
	*	In the future, it can be rewritten to account for non-standard
546
	*	token passing or deleted if the information can be retrieved
547
	*	directly from the Colonet server instead.
548
	*/
549
	public void moveToken ()
550
	{
551
		try { tokenLoc = (tokenLoc+1)%numBots; }
552
			catch (ArithmeticException e) { }  // in case numRobots is zero
553
		
554
		packetMonitor.addTokenPass();
555
	}
556
	
557
	//
558
	// MouseEvent methods
559
	//
560
	public void mouseExited(MouseEvent e) {}
561
	public void mouseEntered(MouseEvent e) {}
562
	public void mouseReleased(MouseEvent e) {}
563
	public void mouseClicked(MouseEvent e) {}
564
	public void mousePressed(MouseEvent e)
565
	{
566
		try {
567
			for (int i = 0; i < numBots; i++)
568
			{
569
				if (botRect[i].contains(e.getPoint()))
570
					selectedBot = i;
571
			}
572
		} catch (Exception ex) {
573
			System.out.println(e);
574
		}
575
	
576
	}
577
	
578
	private void msg (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.INFORMATION_MESSAGE);}
579
	private void warn (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.WARNING_MESSAGE);}
580
	private void err (String text) {JOptionPane.showMessageDialog(null, text, "Colonet", JOptionPane.ERROR_MESSAGE);}
581
	
582
	
583
	/*
584
	*	SelectionIndicator thread.
585
	*	Graphical representation of the selection marker
586
	*
587
	*	step() and draw() are synchronized methods. step() is private and 
588
	*	used to update the position of the crosshairs. draw() is called 
589
	*	externally and should only run if all calculations in step() have
590
	*	been completed.
591
	*/
592
	private class SelectionIndicator extends Thread
593
	{
594
	
595
		final int INDICATOR_DELAY = 100;
596
		final double DTHETA = 0.3;    //larger values make the marker rotate faster
597
		Graphics2D g;   //canvas to draw on
598
		boolean running;
599
		
600
		int sx, sy;		//center
601
		int r, dr;		//radius and width of marker
602
		double theta;   //current angle
603
		
604
		volatile Polygon poly1, poly2, poly3, poly4;
605
		
606
		int px1, py1;
607
		int rx1, ry1;
608
		int px2, py2;
609
		int rx2, ry2;
610
		int px3, py3;
611
		int rx3, ry3;
612
		int px4, py4;
613
		int rx4, ry4;
614
		
615
		int steps;
616
	
617
		public SelectionIndicator (Graphics2D g)
618
		{
619
			super("SelectionIndicator");
620
			this.g = g;
621
			running = false;
622
			steps = 0;
623
			
624
			theta = 0;
625
			rx1 = 0; ry1 = 0;
626
			px1 = 0; py1 = 0;
627
			rx2 = 0; ry2 = 0;
628
			px2 = 0; py2 = 0;
629
			rx3 = 0; ry3 = 0;
630
			px3 = 0; py3 = 0;
631
			rx4 = 0; ry4 = 0;
632
			px4 = 0; py4 = 0;
633
		}
634
		
635
		public synchronized void setCenter (int sx, int sy)
636
		{
637
			if (sx == this.sx && sy == this.sy) return;
638
			this.sx = sx;
639
			this.sy = sy;
640
			steps = 0;
641
		}
642
		
643
		public synchronized void setRadius (int r, int dr)
644
		{
645
			this.r = r;
646
			this.dr = dr;
647
			steps = 0;
648
		}
649
		
650
		public void run ()
651
		{
652
			running = true;
653
			while (running)
654
			{
655
				step();
656
				try { Thread.sleep(INDICATOR_DELAY); }
657
					catch (InterruptedException e) {  running = false; return; }
658
			}
659
		}
660
		
661
		private synchronized void step ()
662
		{
663
			Polygon poly1_new = new Polygon();
664
			Polygon poly2_new = new Polygon();
665
			Polygon poly3_new = new Polygon();
666
			Polygon poly4_new = new Polygon();
667
		
668
			//the step
669
			theta = (theta + DTHETA/Math.PI) % (Math.PI);
670
			
671
			//the calculation
672
			//let p be the point of the pointy thing toward the center
673
			//let r be the point at the opposite side
674
			
675
			//recalculate radius, if it will look cool, lolz
676
			int newr = r;
677
			if (steps < 100) newr = (int)( r + 200/(steps+1) );
678
			
679
			//precompute values for dx and dy
680
			int dx_inner = (int)(newr * Math.cos(theta));
681
			int dy_inner = (int)(newr * Math.sin(theta));
682
			int dx_outer = (int)((newr+dr) * Math.cos(theta));
683
			int dy_outer = (int)((newr+dr) * Math.sin(theta));
684
			
685
			//calculate polygon constants
686
			int dy_poly = (int)(dr/2 * Math.cos(theta));
687
			int dx_poly = (int)(dr/2 * Math.sin(theta));
688
			
689
			//determine critical points
690
			px1 = sx + dx_inner;
691
			py1 = sy - dy_inner;
692
			rx1 = sx + dx_outer;
693
			ry1 = sy - dy_outer;
694
			px2 = sx - dx_inner;
695
			py2 = sy + dy_inner;
696
			rx2 = sx - dx_outer;
697
			ry2 = sy + dy_outer;
698
			px3 = sx - dy_inner;
699
			py3 = sy - dx_inner;
700
			rx3 = sx - dy_outer;
701
			ry3 = sy - dx_outer;
702
			px4 = sx + dy_inner;
703
			py4 = sy + dx_inner;
704
			rx4 = sx + dy_outer;
705
			ry4 = sy + dx_outer;
706
			
707
			//create polygons
708
			poly1_new.addPoint(px1, py1);
709
			poly1_new.addPoint(rx1+dx_poly, ry1+dy_poly);
710
			poly1_new.addPoint(rx1-dx_poly, ry1-dy_poly);
711
			poly2_new.addPoint(px2, py2);
712
			poly2_new.addPoint(rx2+dx_poly, ry2+dy_poly);
713
			poly2_new.addPoint(rx2-dx_poly, ry2-dy_poly);
714
			poly3_new.addPoint(px3, py3);
715
			poly3_new.addPoint(rx3-dy_poly, ry3+dx_poly);
716
			poly3_new.addPoint(rx3+dy_poly, ry3-dx_poly);
717
			poly4_new.addPoint(px4, py4);
718
			poly4_new.addPoint(rx4-dy_poly, ry4+dx_poly);
719
			poly4_new.addPoint(rx4+dy_poly, ry4-dx_poly);
720
			
721
			//reassign updated polygons
722
			poly1 = poly1_new;
723
			poly2 = poly2_new;
724
			poly3 = poly3_new;
725
			poly4 = poly4_new;
726
		
727
			if (steps < 300) steps++;
728
		}
729
		
730
		public synchronized void draw ()
731
		{
732
			if (!running) return;
733
			g.setColor(Color.GRAY);
734
			//draw polygons
735
			g.fillPolygon(poly1);
736
			g.fillPolygon(poly2);
737
			g.fillPolygon(poly3);
738
			g.fillPolygon(poly4);
739
		}
740
	
741
	}
742
	
743
	/*
744
	*	Simulator thread.
745
	*
746
	*/
747
	private class Simulator extends Thread
748
	{
749
		final int SIMULATOR_DELAY = 300;
750
	
751
		boolean running;
752
	
753
		public Simulator ()
754
		{
755
			super("Simulator");
756
			running = false;
757
		}
758
		
759
		public void run ()
760
		{
761
			running = true;
762
			while (running)
763
			{
764
				step();
765
				try { Thread.sleep(SIMULATOR_DELAY); }
766
					catch (InterruptedException e) { running = false; return; }
767
			}
768
		}
769
		
770
		private void step ()
771
		{
772
			// simulate passing the token
773
			moveToken();
774
		
775
		}
776
	
777
	}
778
	
779
	/*
780
	*	PacketMonitor thread.
781
	*
782
	*	Currently, this counts the rate of token passes but will eventually 
783
	*	be modified to keep more important statistics.
784
	*/
785
	private class PacketMonitor extends Thread
786
	{
787
		final int PACKETMONITOR_DELAY = 1000;
788
	
789
		boolean running;
790
		int tokenPasses;
791
	
792
		public PacketMonitor ()
793
		{
794
			super("PacketMonitor");
795
			running = false;
796
			tokenPasses = 0;
797
		}
798
		
799
		public void run ()
800
		{
801
			running = true;
802
			while (running)
803
			{
804
				displayTokenPasses();
805
				try { Thread.sleep(PACKETMONITOR_DELAY); }
806
					catch (InterruptedException e) { running = false; return; }
807
			}
808
		}
809
		
810
		public synchronized void addTokenPass ()
811
		{
812
			tokenPasses++;
813
		}
814
		
815
		public synchronized void displayTokenPasses ()
816
		{
817
			lblTokenPasses.setText("" + tokenPasses);
818
			tokenPasses = 0;
819
		}
820
	
821
	}
822
	
823
	/*
824
	*	DataListener thread.
825
	*
826
	*/
827
	class DataListener extends Thread
828
	{
829
		final int DATALISTENER_DELAY = 1000;
830
		BufferedReader reader;
831
		
832
		public DataListener ()
833
		{
834
			super("Colonet DataListener");
835
		}
836
		
837
		public void run ()
838
		{
839
			String line;
840
			try {
841
				reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
842
			} catch (IOException e) {
843
				warn("Could not open input stream from socket.\nTry relooding the applet.");
844
			}
845
			while (true)
846
			{
847
				try {
848
					if (reader.ready())
849
					{
850
						line = reader.readLine();
851
						if (line != null)
852
						{
853
							msg("Incoming data: [" + line + "]");
854
						}
855
					}
856
					Thread.sleep(DATALISTENER_DELAY);
857
				} catch (InterruptedException e) {
858
					return;
859
				} catch (IOException e) {
860
					warn("IOException while reading incoming data.");
861
				}
862
			}
863
		}
864

  
865
	}
866

  
867
	
868
		
869

  
870
}
trunk/code/projects/colonet/ColonetGUI/copy.sh
1
#! /bin/bash
2

  
3
sudo cp * /var/www/gui/
trunk/code/projects/colonet/ColonetGUI/index_simple.html
1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3

  
4
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
5
<head>
6
	<title>Colony Control Applet - Carnegie Mellon Robotics Club</title>
7
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
8
	<link rel="stylesheet" type="text/css" href="colonetstyle.css" />
9
</head>
10

  
11
<body>
12

  
13
<div class="top">
14
	<h1>Colonet</h1>
15
	<p>Carnegie Mellon Robotics Club: Colony Project</p>
16
	<img src="http://roboclub8.frc.ri.cmu.edu/mainwiki/roboclublogo.png" height="125px" width="110px" />
17
</div>
18

  
19
<div class="app">
20
	<p>
21
	<object
22
		classid = "java:SimpleColonet.class"
23
		type = "application/x-java-applet"
24
		width = "900"
25
		height = "600"
26
		align = "bottom"
27
		codebase = "http://roboclub1.frc.ri.cmu.edu/gui/" 
28
		name = "SimpleColonet"
29
		title = "SimpleColonet" >
30
		<param name = "code" value = "SimpleColonet.class" />
31
	</object>
32
	<br />
33
	</p>
34
</div>
35

  
36
<div class="bottom">
37
	<p><b>Colony Project Home page:</b><br />
38
	<a href="http://www.robotcolony.org/">www.robotcolony.org</a></p>
39
	
40
	<p><b>Colonet Developers:</b><br />
41
	Gregory Tress, Eugene Edward Marinelli III, Jason Knichel, Suresh Nidhiry</p>
42
	
43
	<p><b>Validator:</b><br />
44
	<a href="http://validator.w3.org/check?uri=referer">
45
	<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
46
		 alt="Valid XHTML 1.0 Transitional"
47
		 height="31"
48
		 width="88" 
49
		 border="0"
50
		 />
51
	</a>
52
	<a href="http://jigsaw.w3.org/css-validator/validator?uri=http://roboclub1.frc.ri.cmu.edu/ColonetGUI/colonetstyle.css">
53
  	<img style="border:0;width:88px;height:31px"
54
       src="http://www.w3.org/Icons/valid-css-blue" 
55
       alt="Valid CSS!" />
56
	</a><br />
57
	</p>
58
	
59
</div>
60

  
61

  
62

  
63
</body>
64
</html>
trunk/code/projects/colonet/ColonetGUI/Colonet.xcode/gmtress.mode1
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
<plist version="1.0">
4
<dict>
5
	<key>ActivePerspectiveName</key>
6
	<string>Project</string>
7
	<key>AllowedModules</key>
8
	<array>
9
		<dict>
10
			<key>BundleLoadPath</key>
11
			<string></string>
12
			<key>MaxInstances</key>
13
			<string>n</string>
14
			<key>Module</key>
15
			<string>PBXSmartGroupTreeModule</string>
16
			<key>Name</key>
17
			<string>Groups and Files Outline View</string>
18
		</dict>
19
		<dict>
20
			<key>BundleLoadPath</key>
21
			<string></string>
22
			<key>MaxInstances</key>
23
			<string>n</string>
24
			<key>Module</key>
25
			<string>PBXNavigatorGroup</string>
26
			<key>Name</key>
27
			<string>Editor</string>
28
		</dict>
29
		<dict>
30
			<key>BundleLoadPath</key>
31
			<string></string>
32
			<key>MaxInstances</key>
33
			<string>n</string>
34
			<key>Module</key>
35
			<string>XCTaskListModule</string>
36
			<key>Name</key>
37
			<string>Task List</string>
38
		</dict>
39
		<dict>
40
			<key>BundleLoadPath</key>
41
			<string></string>
42
			<key>MaxInstances</key>
43
			<string>n</string>
44
			<key>Module</key>
45
			<string>XCDetailModule</string>
46
			<key>Name</key>
47
			<string>File and Smart Group Detail Viewer</string>
48
		</dict>
49
		<dict>
50
			<key>BundleLoadPath</key>
51
			<string></string>
52
			<key>MaxInstances</key>
53
			<string>1</string>
54
			<key>Module</key>
55
			<string>PBXBuildResultsModule</string>
56
			<key>Name</key>
57
			<string>Detailed Build Results Viewer</string>
58
		</dict>
59
		<dict>
60
			<key>BundleLoadPath</key>
61
			<string></string>
62
			<key>MaxInstances</key>
63
			<string>1</string>
64
			<key>Module</key>
65
			<string>PBXProjectFindModule</string>
66
			<key>Name</key>
67
			<string>Project Batch Find Tool</string>
68
		</dict>
69
		<dict>
70
			<key>BundleLoadPath</key>
71
			<string></string>
72
			<key>MaxInstances</key>
73
			<string>n</string>
74
			<key>Module</key>
75
			<string>PBXRunSessionModule</string>
76
			<key>Name</key>
77
			<string>Run Log</string>
78
		</dict>
79
		<dict>
80
			<key>BundleLoadPath</key>
81
			<string></string>
82
			<key>MaxInstances</key>
83
			<string>n</string>
84
			<key>Module</key>
85
			<string>PBXBookmarksModule</string>
86
			<key>Name</key>
87
			<string>Bookmarks Tool</string>
88
		</dict>
89
		<dict>
90
			<key>BundleLoadPath</key>
91
			<string></string>
92
			<key>MaxInstances</key>
93
			<string>n</string>
94
			<key>Module</key>
95
			<string>PBXClassBrowserModule</string>
96
			<key>Name</key>
97
			<string>Class Browser</string>
98
		</dict>
99
		<dict>
100
			<key>BundleLoadPath</key>
101
			<string></string>
102
			<key>MaxInstances</key>
103
			<string>n</string>
104
			<key>Module</key>
105
			<string>PBXCVSModule</string>
106
			<key>Name</key>
107
			<string>Source Code Control Tool</string>
108
		</dict>
109
		<dict>
110
			<key>BundleLoadPath</key>
111
			<string></string>
112
			<key>MaxInstances</key>
113
			<string>n</string>
114
			<key>Module</key>
115
			<string>PBXDebugBreakpointsModule</string>
116
			<key>Name</key>
117
			<string>Debug Breakpoints Tool</string>
118
		</dict>
119
		<dict>
120
			<key>BundleLoadPath</key>
121
			<string></string>
122
			<key>MaxInstances</key>
123
			<string>n</string>
124
			<key>Module</key>
125
			<string>XCDockableInspector</string>
126
			<key>Name</key>
127
			<string>Inspector</string>
128
		</dict>
129
		<dict>
130
			<key>BundleLoadPath</key>
131
			<string></string>
132
			<key>MaxInstances</key>
133
			<string>n</string>
134
			<key>Module</key>
135
			<string>PBXOpenQuicklyModule</string>
136
			<key>Name</key>
137
			<string>Open Quickly Tool</string>
138
		</dict>
139
		<dict>
140
			<key>BundleLoadPath</key>
141
			<string></string>
142
			<key>MaxInstances</key>
143
			<string>1</string>
144
			<key>Module</key>
145
			<string>PBXDebugSessionModule</string>
146
			<key>Name</key>
147
			<string>Debugger</string>
148
		</dict>
149
		<dict>
150
			<key>BundleLoadPath</key>
151
			<string></string>
152
			<key>MaxInstances</key>
153
			<string>1</string>
154
			<key>Module</key>
155
			<string>PBXDebugCLIModule</string>
156
			<key>Name</key>
157
			<string>Debug Console</string>
158
		</dict>
159
	</array>
160
	<key>Description</key>
161
	<string>DefaultDescriptionKey</string>
162
	<key>DockingSystemVisible</key>
163
	<false/>
164
	<key>Extension</key>
165
	<string>mode1</string>
166
	<key>FavBarConfig</key>
167
	<dict>
168
		<key>PBXProjectModuleGUID</key>
169
		<string>A341617D0C989B510007BEF2</string>
170
		<key>XCBarModuleItemNames</key>
171
		<dict/>
172
		<key>XCBarModuleItems</key>
173
		<array/>
174
	</dict>
175
	<key>FirstTimeWindowDisplayed</key>
176
	<false/>
177
	<key>Identifier</key>
178
	<string>com.apple.perspectives.project.mode1</string>
179
	<key>MajorVersion</key>
180
	<integer>31</integer>
181
	<key>MinorVersion</key>
182
	<integer>1</integer>
183
	<key>Name</key>
184
	<string>Default</string>
185
	<key>Notifications</key>
186
	<array/>
187
	<key>OpenEditors</key>
188
	<array/>
189
	<key>PerspectiveWidths</key>
190
	<array>
191
		<integer>-1</integer>
192
		<integer>-1</integer>
193
	</array>
194
	<key>Perspectives</key>
195
	<array>
196
		<dict>
197
			<key>ChosenToolbarItems</key>
198
			<array>
199
				<string>active-target-popup</string>
200
				<string>action</string>
201
				<string>NSToolbarFlexibleSpaceItem</string>
202
				<string>buildOrClean</string>
203
				<string>build-and-runOrDebug</string>
204
				<string>com.apple.ide.PBXToolbarStopButton</string>
205
				<string>get-info</string>
206
				<string>toggle-editor</string>
207
				<string>NSToolbarFlexibleSpaceItem</string>
208
				<string>com.apple.pbx.toolbar.searchfield</string>
209
			</array>
210
			<key>ControllerClassBaseName</key>
211
			<string></string>
212
			<key>IconName</key>
213
			<string>WindowOfProjectWithEditor</string>
214
			<key>Identifier</key>
215
			<string>perspective.project</string>
216
			<key>IsVertical</key>
217
			<false/>
218
			<key>Layout</key>
219
			<array>
220
				<dict>
221
					<key>ContentConfiguration</key>
222
					<dict>
223
						<key>PBXBottomSmartGroupGIDs</key>
224
						<array>
225
							<string>1C37FBAC04509CD000000102</string>
226
							<string>1C37FAAC04509CD000000102</string>
227
							<string>1C08E77C0454961000C914BD</string>
228
							<string>1C37FABC05509CD000000102</string>
229
							<string>1C37FABC05539CD112110102</string>
230
							<string>E2644B35053B69B200211256</string>
231
							<string>1C37FABC04509CD000100104</string>
232
							<string>1CC0EA4004350EF90044410B</string>
233
							<string>1CC0EA4004350EF90041110B</string>
234
						</array>
235
						<key>PBXProjectModuleGUID</key>
236
						<string>1CE0B1FE06471DED0097A5F4</string>
237
						<key>PBXProjectModuleLabel</key>
238
						<string>Files</string>
239
						<key>PBXProjectStructureProvided</key>
240
						<string>yes</string>
241
						<key>PBXSmartGroupTreeModuleColumnData</key>
242
						<dict>
243
							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
244
							<array>
245
								<real>186</real>
246
							</array>
247
							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
248
							<array>
249
								<string>MainColumn</string>
250
							</array>
251
						</dict>
252
						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
253
						<dict>
254
							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
255
							<array>
256
								<string>00E6828FFEC88D1A11DB9C8B</string>
257
								<string>1C37FBAC04509CD000000102</string>
258
								<string>A341619F0C989DE00007BEF2</string>
259
								<string>1C37FAAC04509CD000000102</string>
260
								<string>1C37FABC05509CD000000102</string>
261
							</array>
262
							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
263
							<array>
264
								<array>
265
									<integer>19</integer>
266
								</array>
267
							</array>
268
							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
269
							<string>{{0, 36}, {186, 338}}</string>
270
						</dict>
271
						<key>PBXTopSmartGroupGIDs</key>
272
						<array/>
273
						<key>XCIncludePerspectivesSwitch</key>
274
						<true/>
275
						<key>XCSharingToken</key>
276
						<string>com.apple.Xcode.GFSharingToken</string>
277
					</dict>
278
					<key>GeometryConfiguration</key>
279
					<dict>
280
						<key>Frame</key>
281
						<string>{{0, 0}, {203, 356}}</string>
282
						<key>GroupTreeTableConfiguration</key>
283
						<array>
284
							<string>MainColumn</string>
285
							<real>186</real>
286
						</array>
287
						<key>RubberWindowFrame</key>
288
						<string>34 131 690 397 0 0 1280 832 </string>
289
					</dict>
290
					<key>Module</key>
291
					<string>PBXSmartGroupTreeModule</string>
292
					<key>Proportion</key>
293
					<string>203pt</string>
294
				</dict>
295
				<dict>
296
					<key>Dock</key>
297
					<array>
298
						<dict>
299
							<key>ContentConfiguration</key>
300
							<dict>
301
								<key>PBXProjectModuleGUID</key>
302
								<string>1CE0B20306471E060097A5F4</string>
303
								<key>PBXProjectModuleLabel</key>
304
								<string>MyNewFile14.java</string>
305
								<key>PBXSplitModuleInNavigatorKey</key>
306
								<dict>
307
									<key>Split0</key>
308
									<dict>
309
										<key>PBXProjectModuleGUID</key>
310
										<string>1CE0B20406471E060097A5F4</string>
311
										<key>PBXProjectModuleLabel</key>
312
										<string>MyNewFile14.java</string>
313
									</dict>
314
									<key>SplitCount</key>
315
									<string>1</string>
316
								</dict>
317
								<key>StatusBarVisibility</key>
318
								<true/>
319
							</dict>
320
							<key>GeometryConfiguration</key>
321
							<dict>
322
								<key>Frame</key>
323
								<string>{{0, 0}, {482, 0}}</string>
324
								<key>RubberWindowFrame</key>
325
								<string>34 131 690 397 0 0 1280 832 </string>
326
							</dict>
327
							<key>Module</key>
328
							<string>PBXNavigatorGroup</string>
329
							<key>Proportion</key>
330
							<string>0pt</string>
331
						</dict>
332
						<dict>
333
							<key>BecomeActive</key>
334
							<true/>
335
							<key>ContentConfiguration</key>
336
							<dict>
337
								<key>PBXProjectModuleGUID</key>
338
								<string>1CE0B20506471E060097A5F4</string>
339
								<key>PBXProjectModuleLabel</key>
340
								<string>Detail</string>
341
							</dict>
342
							<key>GeometryConfiguration</key>
343
							<dict>
344
								<key>Frame</key>
345
								<string>{{0, 5}, {482, 351}}</string>
346
								<key>RubberWindowFrame</key>
347
								<string>34 131 690 397 0 0 1280 832 </string>
348
							</dict>
349
							<key>Module</key>
350
							<string>XCDetailModule</string>
351
							<key>Proportion</key>
352
							<string>351pt</string>
353
						</dict>
354
					</array>
355
					<key>Proportion</key>
356
					<string>482pt</string>
357
				</dict>
358
			</array>
359
			<key>Name</key>
360
			<string>Project</string>
361
			<key>ServiceClasses</key>
362
			<array>
363
				<string>XCModuleDock</string>
364
				<string>PBXSmartGroupTreeModule</string>
365
				<string>XCModuleDock</string>
366
				<string>PBXNavigatorGroup</string>
367
				<string>XCDetailModule</string>
368
			</array>
369
			<key>TableOfContents</key>
370
			<array>
371
				<string>A341618E0C989C770007BEF2</string>
372
				<string>1CE0B1FE06471DED0097A5F4</string>
373
				<string>A341618F0C989C770007BEF2</string>
374
				<string>1CE0B20306471E060097A5F4</string>
375
				<string>1CE0B20506471E060097A5F4</string>
376
			</array>
377
			<key>ToolbarConfiguration</key>
378
			<string>xcode.toolbar.config.default</string>
379
		</dict>
380
		<dict>
381
			<key>ControllerClassBaseName</key>
382
			<string></string>
383
			<key>IconName</key>
384
			<string>WindowOfProject</string>
385
			<key>Identifier</key>
386
			<string>perspective.morph</string>
387
			<key>IsVertical</key>
388
			<integer>0</integer>
389
			<key>Layout</key>
390
			<array>
391
				<dict>
392
					<key>BecomeActive</key>
393
					<integer>1</integer>
394
					<key>ContentConfiguration</key>
395
					<dict>
396
						<key>PBXBottomSmartGroupGIDs</key>
397
						<array>
398
							<string>1C37FBAC04509CD000000102</string>
399
							<string>1C37FAAC04509CD000000102</string>
400
							<string>1C08E77C0454961000C914BD</string>
401
							<string>1C37FABC05509CD000000102</string>
402
							<string>1C37FABC05539CD112110102</string>
403
							<string>E2644B35053B69B200211256</string>
404
							<string>1C37FABC04509CD000100104</string>
405
							<string>1CC0EA4004350EF90044410B</string>
406
							<string>1CC0EA4004350EF90041110B</string>
407
						</array>
408
						<key>PBXProjectModuleGUID</key>
409
						<string>11E0B1FE06471DED0097A5F4</string>
410
						<key>PBXProjectModuleLabel</key>
411
						<string>Files</string>
412
						<key>PBXProjectStructureProvided</key>
413
						<string>yes</string>
414
						<key>PBXSmartGroupTreeModuleColumnData</key>
415
						<dict>
416
							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
417
							<array>
418
								<real>186</real>
419
							</array>
420
							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
421
							<array>
422
								<string>MainColumn</string>
423
							</array>
424
						</dict>
425
						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
426
						<dict>
427
							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
428
							<array>
429
								<string>29B97314FDCFA39411CA2CEA</string>
430
								<string>1C37FABC05509CD000000102</string>
431
							</array>
432
							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
433
							<array>
434
								<array>
435
									<integer>0</integer>
436
								</array>
437
							</array>
438
							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
439
							<string>{{0, 0}, {186, 337}}</string>
440
						</dict>
441
						<key>PBXTopSmartGroupGIDs</key>
442
						<array/>
443
						<key>XCIncludePerspectivesSwitch</key>
444
						<integer>1</integer>
445
						<key>XCSharingToken</key>
446
						<string>com.apple.Xcode.GFSharingToken</string>
447
					</dict>
448
					<key>GeometryConfiguration</key>
449
					<dict>
450
						<key>Frame</key>
451
						<string>{{0, 0}, {203, 355}}</string>
452
						<key>GroupTreeTableConfiguration</key>
453
						<array>
454
							<string>MainColumn</string>
455
							<real>186</real>
456
						</array>
457
						<key>RubberWindowFrame</key>
458
						<string>373 269 690 397 0 0 1440 878 </string>
459
					</dict>
460
					<key>Module</key>
461
					<string>PBXSmartGroupTreeModule</string>
462
					<key>Proportion</key>
463
					<string>100%</string>
464
				</dict>
465
			</array>
466
			<key>Name</key>
467
			<string>Morph</string>
468
			<key>PreferredWidth</key>
469
			<integer>300</integer>
470
			<key>ServiceClasses</key>
471
			<array>
472
				<string>XCModuleDock</string>
473
				<string>PBXSmartGroupTreeModule</string>
474
			</array>
475
			<key>TableOfContents</key>
476
			<array>
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff