Squashed 'third_party/allwpilib_2016/' content from commit 7f61816

Change-Id: If9d9245880859cdf580f5d7f77045135d0521ce7
git-subtree-dir: third_party/allwpilib_2016
git-subtree-split: 7f618166ed253a24629934fcf89c3decb0528a3b
diff --git a/simulation/SimDS/build.gradle b/simulation/SimDS/build.gradle
new file mode 100644
index 0000000..0acaaee
--- /dev/null
+++ b/simulation/SimDS/build.gradle
@@ -0,0 +1,54 @@
+apply plugin: 'java'
+apply plugin: 'application'
+apply plugin: 'com.github.johnrengelman.shadow'
+apply plugin: 'maven-publish'
+
+// Adds the dependency for the shadow plugin, which creates an uberjar with all dependencies
+buildscript {
+    repositories { jcenter() }
+    dependencies {
+        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.1'
+    }
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifact(shadowJar) {
+                // The shadow plugin has the 'all' classifier. We don't want this, so use null instead
+                classifier null
+            }
+            artifact(simDsSources) {
+                classifier 'sources'
+            }
+            artifact(simDsJavadoc) {
+                classifier 'javadoc'
+            }
+            groupId 'edu.wpi.first.wpilibj.simulation'
+            artifactId 'SimDS'
+            version '0.1.0-SNAPSHOT'
+        }
+    }
+    setupWpilibRepo(it)
+}
+
+mainClassName = 'edu.wpi.first.wpilibj.simulation.ds.Main'
+
+dependencies {
+    compile 'net.java.jinput:jinput:2.0.5'
+    compile project(':simulation:JavaGazebo')
+}
+
+task simDsSources(type: Jar, dependsOn: classes) {
+    description = 'Creates the sources jar for the SimDS'
+    group = 'WPILib'
+    classifier = 'sources'
+    from sourceSets.main.allJava
+}
+
+task simDsJavadoc(type: Jar, dependsOn: javadoc) {
+    description = 'Creates the javadoc jar for the SimDS'
+    group = 'WPILib'
+    classifier = 'javadoc'
+    from javadoc.destinationDir
+}
\ No newline at end of file
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/DS.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/DS.java
new file mode 100644
index 0000000..bd12c41
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/DS.java
@@ -0,0 +1,152 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.DropMode;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+
+import org.gazebosim.transport.Node;
+import org.gazebosim.transport.Publisher;
+
+import edu.wpi.first.wpilibj.simulation.ds.FakeJoystick;
+import edu.wpi.first.wpilibj.simulation.ds.ISimJoystick;
+import edu.wpi.first.wpilibj.simulation.ds.JoystickProvider;
+import gazebo.msgs.GzDriverStation.DriverStation;
+
+public class DS {
+	private JoystickProvider joystickProvider;
+	private JoystickList joysticks;
+	
+	private JFrame mainframe;
+	private JPanel modePanel;
+	private ActionListener modeListener;
+	private ButtonGroup modes;
+	private JButton enable, refresh;
+	
+	public enum State {
+		Disabled, Teleop, Autonomous, Test;
+	}
+	private boolean enabled = false;
+	private State state = State.Teleop;
+	private DriverStation.State protoState = DriverStation.State.TELEOP;
+	private Publisher<DriverStation> pub;
+	
+	public DS(JoystickProvider joystickProvider) {
+		this.joystickProvider = joystickProvider;
+		mainframe = new JFrame();
+		mainframe.setTitle("FRC Simulation DriverStation");
+		mainframe.setLayout(new GridBagLayout());
+		GridBagConstraints constraints = new GridBagConstraints();
+		
+		makeModeButtons(constraints);
+        mainframe.pack();
+		constraints.gridy = 1;
+		makeEnableButton(constraints);
+
+		constraints.gridx = 1;
+		constraints.gridy = 0;
+		makeJoystickUI(constraints);
+        mainframe.pack();
+		constraints.gridy = 1;
+		makeRefreshButton(constraints);
+        
+        mainframe.pack();
+        mainframe.setVisible(true);
+	}
+	
+	private void makeModeButtons(GridBagConstraints constraints) {
+		modePanel = new JPanel();
+		modePanel.setLayout(new BoxLayout(modePanel, BoxLayout.PAGE_AXIS));
+		
+		modeListener = new ModeAction(this);
+		JRadioButton teleop = new JRadioButton("Teleop");
+		teleop.setActionCommand(State.Teleop.toString());
+		teleop.addActionListener(modeListener);
+		JRadioButton auto = new JRadioButton("Autonomous");
+		auto.setActionCommand(State.Autonomous.toString());
+		auto.addActionListener(modeListener);
+		JRadioButton test = new JRadioButton("Test");
+		test.setActionCommand(State.Test.toString());
+		test.addActionListener(modeListener);
+		teleop.setSelected(true);
+		
+		modes = new ButtonGroup();
+		modes.add(teleop);
+		modes.add(auto);
+		modes.add(test);
+		modePanel.add(teleop);
+		modePanel.add(auto);
+		modePanel.add(test);
+		mainframe.add(modePanel, constraints);
+	}
+		
+	private void makeEnableButton(GridBagConstraints constraints) {
+		enable = new JButton("Enable");
+		enable.addActionListener(new EnableAction(this));
+		enable.setPreferredSize(new Dimension(modePanel.getSize().width, 50));
+		mainframe.add(enable, constraints);
+	}
+	
+	private void makeJoystickUI(GridBagConstraints constraints) {
+		joysticks = new JoystickList(joystickProvider);
+		mainframe.add(joysticks, constraints);
+		scanForJoysticks();
+	}
+
+	public void scanForJoysticks() {
+		joysticks.removeAll();
+		List<ISimJoystick> sticks = joystickProvider.scanForJoysticks();
+		while (sticks.size() < 6) {
+			sticks.add(new FakeJoystick());
+		}
+		joysticks.setListData(sticks);
+	}
+	
+	private void makeRefreshButton(GridBagConstraints constraints) {
+		refresh = new JButton("Refresh Joysticks");
+		refresh.addActionListener(new RefreshAction(this));
+		refresh.setPreferredSize(new Dimension(joysticks.getSize().width, 50));
+		mainframe.add(refresh, constraints);
+	}
+	
+	public void setEnabled(boolean enabled) {
+		this.enabled = enabled;
+		enable.setText(enabled ? "Disable" : "Enable");
+	}
+	
+	public State getState() {
+		return enabled ? state : State.Disabled;
+	}
+
+	public void setState(State state) {
+		setEnabled(false);
+		this.state = state;
+		switch (state) {
+		case Autonomous: protoState = DriverStation.State.AUTO; break;
+		case Teleop: protoState = DriverStation.State.TELEOP; break;
+		case Test: protoState = DriverStation.State.TEST; break;
+		default: break;
+		}
+	}
+
+	public void toggleEnable() {
+		setEnabled(!enabled);
+	}
+
+	public void advertise(Node node) {
+		pub = node.advertise("ds/state", DriverStation.getDefaultInstance());
+	}
+
+	public void publish() {
+		pub.publish(DriverStation.newBuilder().setEnabled(enabled).setState(protoState).build());
+	}
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/EnableAction.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/EnableAction.java
new file mode 100644
index 0000000..f847568
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/EnableAction.java
@@ -0,0 +1,18 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class EnableAction implements ActionListener {
+	private DS ds;
+	
+	public EnableAction(DS ds) {
+		this.ds = ds;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		ds.toggleEnable();
+	}
+
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/FakeJoystick.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/FakeJoystick.java
new file mode 100644
index 0000000..4831a27
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/FakeJoystick.java
@@ -0,0 +1,19 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import org.gazebosim.transport.Node;
+
+
+public class FakeJoystick implements ISimJoystick {
+
+	public String getName() {
+		return "Empty Joystick";
+	}
+	
+	public String toString() {
+		return getName();
+	}
+
+	@Override public void advertise(Node node, int i) {}
+
+	@Override public void publish() {}
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ISimJoystick.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ISimJoystick.java
new file mode 100644
index 0000000..9263a1b
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ISimJoystick.java
@@ -0,0 +1,9 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import org.gazebosim.transport.Node;
+
+public interface ISimJoystick {
+	String getName();
+	void advertise(Node node, int i);
+	void publish();
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickList.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickList.java
new file mode 100644
index 0000000..f598a3d
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickList.java
@@ -0,0 +1,118 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.util.List;
+
+import javax.swing.DropMode;
+import javax.swing.JList;
+import javax.swing.TransferHandler;
+
+import edu.wpi.first.wpilibj.simulation.ds.ISimJoystick;
+import edu.wpi.first.wpilibj.simulation.ds.JoystickProvider;
+
+@SuppressWarnings("serial")
+public class JoystickList extends JList<ISimJoystick> {
+	private JoystickProvider joystickProvider;
+	List<ISimJoystick> joysticks;
+
+	public JoystickList(JoystickProvider joystickProvider) {
+		super();
+		this.joystickProvider = joystickProvider;
+
+		setDragEnabled(true);
+		setDropMode(DropMode.INSERT);
+
+		setTransferHandler(new DropHandler(this));
+		new DragListener(this);
+	}
+
+	public void moveElement(int index, int dropTargetIndex) {
+		ISimJoystick move = joysticks.get(index);
+		joysticks.add(dropTargetIndex, move);
+		joysticks.remove(index < dropTargetIndex ? index : index + 1);
+		setListData(joysticks);
+	}
+
+	public void setListData(List<ISimJoystick> sticks) {
+		joysticks = sticks;
+		setListData(sticks.toArray(new ISimJoystick[0]));
+		joystickProvider.setJoysticks(sticks);
+	}
+
+	class DragListener implements DragSourceListener, DragGestureListener {
+		JoystickList list;
+
+		DragSource ds = new DragSource();
+
+		public DragListener(JoystickList list) {
+			this.list = list;
+			ds.createDefaultDragGestureRecognizer(
+					list, DnDConstants.ACTION_MOVE, this);
+		}
+
+		public void dragGestureRecognized(DragGestureEvent dge) {
+			StringSelection transferable = new StringSelection(
+					Integer.toString(list.getSelectedIndex()));
+			ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, this);
+		}
+
+		public void dragEnter(DragSourceDragEvent dsde) {}
+		public void dragExit(DragSourceEvent dse) {}
+		public void dragOver(DragSourceDragEvent dsde) {}
+		public void dragDropEnd(DragSourceDropEvent dsde) {}
+		public void dropActionChanged(DragSourceDragEvent dsde) {}
+	}
+
+	class DropHandler extends TransferHandler {
+		JoystickList list;
+
+		public DropHandler(JoystickList list) {
+			this.list = list;
+		}
+
+		public boolean canImport(TransferHandler.TransferSupport support) {
+			if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+				return false;
+			}
+			JList.DropLocation dl = (JList.DropLocation) support
+					.getDropLocation();
+			if (dl.getIndex() == -1) {
+				return false;
+			} else {
+				return true;
+			}
+		}
+
+		public boolean importData(TransferHandler.TransferSupport support) {
+			if (!canImport(support)) {
+				return false;
+			}
+
+			Transferable transferable = support.getTransferable();
+			String indexString;
+			try {
+				indexString = (String) transferable.getTransferData(DataFlavor.stringFlavor);
+			} catch (Exception e) {
+				return false;
+			}
+
+			int index = Integer.parseInt(indexString);
+			JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
+			int dropTargetIndex = dl.getIndex();
+			
+			list.moveElement(index, dropTargetIndex);
+
+			return true;
+		}
+	}
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickProvider.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickProvider.java
new file mode 100644
index 0000000..4c22320
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/JoystickProvider.java
@@ -0,0 +1,44 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.wpi.first.wpilibj.simulation.ds.ISimJoystick;
+import edu.wpi.first.wpilibj.simulation.ds.SimJoystick;
+
+import net.java.games.input.Controller;
+import net.java.games.input.ControllerEnvironment;
+
+public class JoystickProvider {
+	List<ISimJoystick> joysticks;
+	
+	public JoystickProvider() {
+		scanForJoysticks();
+	}
+	
+	public List<ISimJoystick> scanForJoysticks() {
+		List<ISimJoystick> foundControllers = new ArrayList<>();
+		Controller[] controllers = ControllerEnvironment.getDefaultEnvironment().getControllers();
+
+        for(int i = 0; i < controllers.length; i++){
+            Controller controller = controllers[i];
+            if (controller.getType() == Controller.Type.STICK
+            		|| controller.getType() == Controller.Type.GAMEPAD 
+                    || controller.getType() == Controller.Type.WHEEL
+                    || controller.getType() == Controller.Type.FINGERSTICK) {
+                foundControllers.add(new SimJoystick(controller));
+            }
+        }
+        
+        joysticks = foundControllers;
+        return foundControllers;
+	}
+	
+	public List<ISimJoystick> getJoysticks() {
+        return joysticks;
+	}
+	
+	public void setJoysticks(List<ISimJoystick> joysticks) {
+		this.joysticks = joysticks;
+	}
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/Main.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/Main.java
new file mode 100644
index 0000000..2f5188a
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/Main.java
@@ -0,0 +1,61 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import gazebo.msgs.GzFloat64.Float64;
+
+import org.gazebosim.transport.Msgs;
+import org.gazebosim.transport.Node;
+import org.gazebosim.transport.Subscriber;
+import org.gazebosim.transport.SubscriberCallback;
+
+public class Main {
+	private static double simTime = 0;
+	private static Subscriber<Float64> sub;
+	
+	public static void main(String args[]) {
+		Node node = new Node("frc");
+		try {
+			node.waitForConnection();
+		} catch (Throwable thr) {
+			System.err.println("Could not connect to Gazebo.");
+			thr.printStackTrace();
+			System.exit(1);
+			return;
+		}
+
+		JoystickProvider provider = new JoystickProvider();
+		DS ds = new DS(provider);
+		ds.advertise(node);
+
+    	sub = node.subscribe("time", Msgs.Float64(),
+			new SubscriberCallback<Float64>() {
+				@Override
+				public void callback(Float64 msg) {
+					simTime = msg.getData();
+					synchronized(sub) {
+						sub.notifyAll();
+					}
+				}
+			}
+		);
+
+		while (true) {
+	    	final double start = simTime;
+			for (int i = 0; i < provider.getJoysticks().size(); i++) {
+				ISimJoystick joystick = provider.getJoysticks().get(i);
+				joystick.advertise(node, i);
+				joystick.publish();
+			}
+			ds.publish();
+
+	    	while ((simTime - start) < 0.020 /*20ms*/) {
+	    		synchronized(sub) {
+	    			try {
+	    				sub.wait(); // Block until time progresses
+	    			} catch (InterruptedException e) {
+	    				e.printStackTrace();
+	    			}
+	    		}
+			}
+		}
+	}
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ModeAction.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ModeAction.java
new file mode 100644
index 0000000..532ef67
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/ModeAction.java
@@ -0,0 +1,18 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class ModeAction implements ActionListener {
+	private DS ds;
+	
+	public ModeAction(DS ds) {
+		this.ds = ds;
+	}
+	
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		ds.setState(DS.State.valueOf(e.getActionCommand()));
+	}
+
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/RefreshAction.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/RefreshAction.java
new file mode 100644
index 0000000..5f264e0
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/RefreshAction.java
@@ -0,0 +1,18 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class RefreshAction implements ActionListener {
+	private DS ds;
+
+	public RefreshAction(DS ds) {
+		this.ds = ds;
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		ds.scanForJoysticks();
+	}
+
+}
diff --git a/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/SimJoystick.java b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/SimJoystick.java
new file mode 100644
index 0000000..23794ca
--- /dev/null
+++ b/simulation/SimDS/src/main/java/edu/wpi/first/wpilibj/simulation/ds/SimJoystick.java
@@ -0,0 +1,69 @@
+package edu.wpi.first.wpilibj.simulation.ds;
+
+import gazebo.msgs.GzJoystick.Joystick;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gazebosim.transport.Node;
+import org.gazebosim.transport.Publisher;
+
+import net.java.games.input.Component;
+import net.java.games.input.Controller;
+
+public class SimJoystick implements ISimJoystick {
+	private Controller controller;
+	private List<Component> axes, buttons;
+	private Publisher<Joystick> pub = null;
+	private int prevI = -1; private Node prevNode = null;
+
+	public SimJoystick(Controller controller) {
+		this.controller = controller;
+		axes = new ArrayList<>();
+		buttons = new ArrayList<>();
+        for(Component c : controller.getComponents()) {
+        	if (c.getIdentifier() instanceof Component.Identifier.Axis) {
+        		axes.add(c);
+        	} else if (c.getIdentifier() instanceof Component.Identifier.Button) {
+        		buttons.add(c);
+        	}
+        }
+	}
+
+	@Override
+	public String getName() {
+		return controller.getName();
+	}
+
+	@Override	
+	public String toString() {
+		return getName();
+	}
+
+	@Override
+	public void advertise(Node node, int i) {
+		if (pub == null) {
+			// I'm good
+		} else if (prevI != i || prevNode != node) {
+			// TODO: pub.close();
+		} else {
+			return; // No change
+		}
+		pub = node.advertise("ds/joysticks/"+i, Joystick.getDefaultInstance());
+		prevNode = node;
+		prevI = i;
+	}
+	
+	@Override
+	public void publish() {
+		controller.poll();
+		Joystick.Builder builder = Joystick.newBuilder();
+		for (Component a : axes) {
+			builder.addAxes(a.getPollData());
+		}
+		for (Component b : buttons) {
+			builder.addButtons(b.getPollData() > 0.5);
+		}
+		pub.publish(builder.build());
+	}
+}