Initial checkin of unified hierarchy of WPILib 2015

This commit is contained in:
Brad Miller
2013-12-15 18:30:16 -05:00
commit 3178911eef
1560 changed files with 410007 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>edu.wpi.first.wpilib.plugins.core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,34 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: edu.wpi.first.wpilib.plugins.core
Bundle-SymbolicName: edu.wpi.first.wpilib.plugins.core;singleton:=true
Bundle-Version: 0.1.0.qualifier
Bundle-Activator: edu.wpi.first.wpilib.plugins.core.WPILibCore
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.jface.text,
org.eclipse.core.resources,
org.eclipse.ui.editors,
org.eclipse.ui.ide,
org.eclipse.ant.core;bundle-version="3.2.400",
org.eclipse.ant.launching;bundle-version="1.0.200",
org.eclipse.debug.core;bundle-version="3.7.100",
org.eclipse.core.externaltools;bundle-version="1.0.100",
org.eclipse.debug.ui;bundle-version="3.8.1",
org.eclipse.ui.externaltools;bundle-version="3.2.100",
org.eclipse.ant.ui;bundle-version="3.5.300",
org.eclipse.ui.console;bundle-version="3.5.100",
org.eclipse.ui.navigator;bundle-version="3.5.200",
org.eclipse.ui.navigator.resources;bundle-version="3.4.400",
org.eclipse.ui.intro,
org.eclipse.ui.intro.universal,
org.eclipse.core.expressions;bundle-version="3.4.400"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: edu.wpi.first.wpilib.plugins.core,
edu.wpi.first.wpilib.plugins.core.ant,
edu.wpi.first.wpilib.plugins.core.installer,
edu.wpi.first.wpilib.plugins.core.launching,
edu.wpi.first.wpilib.plugins.core.nature,
edu.wpi.first.wpilib.plugins.core.preferences,
edu.wpi.first.wpilib.plugins.core.wizards

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,3 @@
a#WPILibRobotDevelopment-introLink img { background-image : url(graphics/sample.gif); }
a#WPILibRobotDevelopment-introLink:hover img { background-image : url(graphics/sample_hov.gif); }

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<introContent>
<extensionContent id="WPILibRobotDevelopment-introExtension" style="css/sample.css" name="Sample Extension" path="overview/@">
<group style-id="content-group" id="WPILibRobotDevelopment-introLink-group">
<link label="WPILib Documentation" url="http://wpilib.screenstepslive.com/s/3120" id="WPILibRobotDevelopment-introLink" style-id="content-link">
<text>Documentation of how WPILib and it's associated tools work. (Internet Connection Needed)</text>
</link>
</group>
</extensionContent>
</introContent>

View File

@@ -0,0 +1,10 @@
source.. = src/main/java/
output.. = bin/
bin.includes = plugin.xml,\
META-INF/,\
.,\
icons/,\
resources/
buildDirectory = build/
plugin.destination = ${basedir}/repository
eclipse.home = /usr/lib/eclipse

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
id="edu.wpi.first.wpilib.plugins.core.nature.FRCProjectNature"
name="FRCProjectNature"
point="org.eclipse.core.resources.natures">
<runtime>
<run
class="edu.wpi.first.wpilib.plugins.core.nature.FRCProjectNature">
</run>
</runtime>
</extension>
<extension
point="org.eclipse.ui.actionSets">
<actionSet
id="edu.wpi.first.wpilib.plugins.core.actionSet"
label="WPILib Action Set"
visible="true">
<menu
id="edu.wpi.first.wpilib.plugins.core.menu"
label="WPI&amp;Lib">
<separator
name="edu.wpi.first.wpilib.plugins.core.actions">
</separator>
</menu>
<action
class="edu.wpi.first.wpilib.plugins.core.actions.RunSmartDashboardAction"
icon="icons/smartdashboard16x16.png"
id="edu.wpi.first.wpilib.plugins.core.actions.RunSmartDashboardAction"
label="Run &amp;SmartDashboard"
menubarPath="edu.wpi.first.wpilib.plugins.core.menu/edu.wpi.first.wpilib.plugins.core.actions"
toolbarPath="WPILib"
tooltip="Launch the SmartDashboard to get feedback from the robot.">
</action>
<action
class="edu.wpi.first.wpilib.plugins.core.actions.RunRobotBuilderAction"
icon="icons/robotbuilder16x16.png"
id="edu.wpi.first.wpilib.plugins.core.actions.RunRobotBuilderAction"
label="Run &amp;RobotBuilder"
menubarPath="edu.wpi.first.wpilib.plugins.core.menu/edu.wpi.first.wpilib.plugins.core.actions"
toolbarPath="WPILib"
tooltip="Launch the RobotBuilder to help develop command-based programs.">
</action>
<action
class="edu.wpi.first.wpilib.plugins.core.actions.RunSFXDashboardAction"
icon="icons/sfxdashboard16x16.png"
id="edu.wpi.first.wpilib.plugins.core.actions.RunSFXDashboardAction"
label="Run &amp;SFX Dashboard"
menubarPath="edu.wpi.first.wpilib.plugins.core.menu/edu.wpi.first.wpilib.plugins.core.actions"
toolbarPath="WPILib"
tooltip="Launch the SFX Dashboard to get feedback from the robot.">
</action>
<action
class="edu.wpi.first.wpilib.plugins.core.actions.RunOutlineViewerAction"
icon="icons/outlineviewer16x16.png"
id="edu.wpi.first.wpilib.plugins.core.actions.RunOutlineViewerAction"
label="Run &amp;Outline Viewer"
menubarPath="edu.wpi.first.wpilib.plugins.core.menu/edu.wpi.first.wpilib.plugins.core.actions"
toolbarPath="WPILib"
tooltip="Launch the Outline Viewer to see the raw feedback from the robot.">
</action>
</actionSet>
</extension>
<extension
point="org.eclipse.ui.preferencePages">
<page
class="edu.wpi.first.wpilib.plugins.core.preferences.WPILibPreferencePage"
id="edu.wpi.first.wpilib.plugins.core.preferences.WPILibPreferencePage"
name="WPILib Preferences">
</page>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">
<initializer
class="edu.wpi.first.wpilib.plugins.core.preferences.PreferenceInitializer">
</initializer>
</extension>
<extension
point="org.eclipse.ui.intro.configExtension">
<configExtension
configId="org.eclipse.ui.intro.universalConfig"
content="WPILib Intro/sample.xml">
</configExtension>
</extension>
</plugin>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>edu.wpi.first.wpilib.plugins.core</artifactId>
<packaging>eclipse-plugin</packaging>
<parent>
<groupId>edu.wpi.first.wpilib.plugins</groupId>
<artifactId>edu.wpi.first.wpilib.plugins</artifactId>
<version>0.1.0.qualifier</version>
<relativePath>..</relativePath>
</parent>
</project>

View File

@@ -0,0 +1,130 @@
package edu.wpi.first.wpilib.plugins.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import edu.wpi.first.wpilib.plugins.core.ant.AntPropertiesParser;
import edu.wpi.first.wpilib.plugins.core.installer.ToolsInstaller;
import edu.wpi.first.wpilib.plugins.core.preferences.PreferenceConstants;
/**
* The activator class controls the plug-in life cycle
*/
public class WPILibCore extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "edu.wpi.first.wpilib.plugins.core"; //$NON-NLS-1$
// The shared instance
private static WPILibCore plugin;
/**
* The constructor
*/
public WPILibCore() {
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
new ToolsInstaller(getDefaultVersion()).installIfNecessary();
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static WPILibCore getDefault() {
return plugin;
}
/**
* Returns an image descriptor for the image file at the given
* plug-in relative path
*
* @param path the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
public Properties getProjectProperties(IProject project) {
List<InputStream> streams = new ArrayList<InputStream>();
try {
if (project != null) {
try {
streams.add(project.getFile("build.properties").getContents());
} catch (CoreException e) {} // No properties file
}
File file = new File(getWPILibBaseDir()+"/wpilib.properties");
streams.add(new FileInputStream(file));
return new AntPropertiesParser(streams).getProperties();
} catch (Exception e) {
e.printStackTrace();
return new Properties();
}
}
public void saveGlobalProperties(Properties props) {
try {
props.store(new FileOutputStream(new File(WPILibCore.getDefault().getWPILibBaseDir()+"/wpilib.properties")),
"Don't add new properties, they will be deleted by the eclipse plugin.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int getTeamNumber(IProject project) {
return Integer.parseInt(getProjectProperties(project).getProperty("team-number", "0"));
}
public String getTargetIP(IProject project) {
String target = getProjectProperties(project).getProperty("target");
if (target != null) return target;
else {
int teamNumber = getTeamNumber(project);
return "10."+(teamNumber/100)+"."+(teamNumber%100)+".2";
}
}
public String getWPILibBaseDir() {
return System.getProperty("user.home")+"/wpilib";
}
public String getDefaultVersion() {
return "2013-test-0.4";
}
public String getCurrentVersion() {
return getPreferenceStore().getString(PreferenceConstants.TOOLS_VERSION);
}
}

View File

@@ -0,0 +1,71 @@
package edu.wpi.first.wpilib.plugins.core.actions;
import java.io.File;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Our sample action implements workbench action delegate.
* The action proxy will be created by the workbench and
* shown in the UI. When the user tries to use the action,
* this delegate will be created and execution will be
* delegated to it.
* @see IWorkbenchWindowActionDelegate
*/
public class RunOutlineViewerAction implements IWorkbenchWindowActionDelegate {
/**
* The constructor.
*/
public RunOutlineViewerAction() {
}
/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* @see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
String jarFile = WPILibCore.getDefault().getWPILibBaseDir()+File.separator+"tools"+File.separator
+WPILibCore.getDefault().getCurrentVersion()+File.separator+"OutlineViewer-with-dependencies.jar";
String[] cmd = {"java", "-jar", jarFile};
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Selection in the workbench has been changed. We
* can change the state of the 'real' action here
* if we want, but this can only happen after
* the delegate has been created.
* @see IWorkbenchWindowActionDelegate#selectionChanged
*/
public void selectionChanged(IAction action, ISelection selection) {
}
/**
* We can use this method to dispose of any system
* resources we previously allocated.
* @see IWorkbenchWindowActionDelegate#dispose
*/
public void dispose() {
}
/**
* We will cache window object in order to
* be able to provide parent shell for the message dialog.
* @see IWorkbenchWindowActionDelegate#init
*/
public void init(IWorkbenchWindow window) {
}
}

View File

@@ -0,0 +1,78 @@
package edu.wpi.first.wpilib.plugins.core.actions;
import java.io.File;
import java.io.FilenameFilter;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Our sample action implements workbench action delegate.
* The action proxy will be created by the workbench and
* shown in the UI. When the user tries to use the action,
* this delegate will be created and execution will be
* delegated to it.
* @see IWorkbenchWindowActionDelegate
*/
public class RunRobotBuilderAction implements IWorkbenchWindowActionDelegate {
/**
* The constructor.
*/
public RunRobotBuilderAction() {
}
/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* @see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
File dir = new File(WPILibCore.getDefault().getWPILibBaseDir()+File.separator+"tools"+File.separator
+WPILibCore.getDefault().getCurrentVersion());
File[] files = dir.listFiles(new FilenameFilter() {
@Override public boolean accept(File dir, String name) {
return name.startsWith("RobotBuilder") && name.endsWith(".jar");
}
});
if (files.length < 1) return;
String[] cmd = {"java", "-jar", files[0].getAbsolutePath()};
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Selection in the workbench has been changed. We
* can change the state of the 'real' action here
* if we want, but this can only happen after
* the delegate has been created.
* @see IWorkbenchWindowActionDelegate#selectionChanged
*/
public void selectionChanged(IAction action, ISelection selection) {
}
/**
* We can use this method to dispose of any system
* resources we previously allocated.
* @see IWorkbenchWindowActionDelegate#dispose
*/
public void dispose() {
}
/**
* We will cache window object in order to
* be able to provide parent shell for the message dialog.
* @see IWorkbenchWindowActionDelegate#init
*/
public void init(IWorkbenchWindow window) {
}
}

View File

@@ -0,0 +1,71 @@
package edu.wpi.first.wpilib.plugins.core.actions;
import java.io.File;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Our sample action implements workbench action delegate.
* The action proxy will be created by the workbench and
* shown in the UI. When the user tries to use the action,
* this delegate will be created and execution will be
* delegated to it.
* @see IWorkbenchWindowActionDelegate
*/
public class RunSFXDashboardAction implements IWorkbenchWindowActionDelegate {
/**
* The constructor.
*/
public RunSFXDashboardAction() {
}
/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* @see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
String jarFile = WPILibCore.getDefault().getWPILibBaseDir()+File.separator+"tools"+File.separator
+WPILibCore.getDefault().getCurrentVersion()+File.separator+"sfx.jar";
String[] cmd = {"java", "-jar", jarFile};
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Selection in the workbench has been changed. We
* can change the state of the 'real' action here
* if we want, but this can only happen after
* the delegate has been created.
* @see IWorkbenchWindowActionDelegate#selectionChanged
*/
public void selectionChanged(IAction action, ISelection selection) {
}
/**
* We can use this method to dispose of any system
* resources we previously allocated.
* @see IWorkbenchWindowActionDelegate#dispose
*/
public void dispose() {
}
/**
* We will cache window object in order to
* be able to provide parent shell for the message dialog.
* @see IWorkbenchWindowActionDelegate#init
*/
public void init(IWorkbenchWindow window) {
}
}

View File

@@ -0,0 +1,71 @@
package edu.wpi.first.wpilib.plugins.core.actions;
import java.io.File;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Our sample action implements workbench action delegate.
* The action proxy will be created by the workbench and
* shown in the UI. When the user tries to use the action,
* this delegate will be created and execution will be
* delegated to it.
* @see IWorkbenchWindowActionDelegate
*/
public class RunSmartDashboardAction implements IWorkbenchWindowActionDelegate {
/**
* The constructor.
*/
public RunSmartDashboardAction() {
}
/**
* The action has been activated. The argument of the
* method represents the 'real' action sitting
* in the workbench UI.
* @see IWorkbenchWindowActionDelegate#run
*/
public void run(IAction action) {
String jarFile = WPILibCore.getDefault().getWPILibBaseDir()+File.separator+"tools"+File.separator
+WPILibCore.getDefault().getCurrentVersion()+File.separator+"SmartDashboard.jar";
String[] cmd = {"java", "-jar", jarFile};
try {
DebugPlugin.exec(cmd, new File(System.getProperty("user.home")));
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Selection in the workbench has been changed. We
* can change the state of the 'real' action here
* if we want, but this can only happen after
* the delegate has been created.
* @see IWorkbenchWindowActionDelegate#selectionChanged
*/
public void selectionChanged(IAction action, ISelection selection) {
}
/**
* We can use this method to dispose of any system
* resources we previously allocated.
* @see IWorkbenchWindowActionDelegate#dispose
*/
public void dispose() {
}
/**
* We will cache window object in order to
* be able to provide parent shell for the message dialog.
* @see IWorkbenchWindowActionDelegate#init
*/
public void init(IWorkbenchWindow window) {
}
}

View File

@@ -0,0 +1,82 @@
package edu.wpi.first.wpilib.plugins.core.ant;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
public class AntPropertiesParser {
List<InputStream> files;
public AntPropertiesParser(List<InputStream> files) {
this.files = files;
}
@SuppressWarnings("serial")
public AntPropertiesParser(final InputStream file) {
this(new ArrayList<InputStream>() {{add(file);}});
}
public Properties getProperties() throws CoreException {
return getProperties(null);
}
public Properties getProperties(Properties defaults) throws CoreException {
Properties props = defaults;
for (int i = files.size()-1; i >= 0; i--) {
props = getPropertyFile(files.get(i), props);
}
return props;
}
public Properties getPropertyFile(InputStream resource, Properties defaults) throws CoreException {
Properties props;
if (defaults == null) props = new Properties();
else props = new Properties(defaults);
try {
props.load(resource);
} catch (IOException e1) {
System.out.println("Issue loading file: "+resource);
e1.printStackTrace();
return null;
}
// TODO: Improve parsing of ant properties
boolean overflow = false;
for (Object key : props.keySet().toArray()) {
int count = 0;
while (props.getProperty((String) key).toString().contains("$") && count < 10) {
Pattern pattern = Pattern.compile( "\\$\\{(.*?)\\}" );
Matcher matcher = pattern.matcher( props.getProperty((String) key).toString() );
StringBuffer sb = new StringBuffer();
while ( matcher.find() ) {
String prop = matcher.group().substring(2, matcher.group().length()-1);
if (props.getProperty(prop) != null) {
matcher.appendReplacement(sb, Matcher.quoteReplacement(props.getProperty(prop)));
} else if (prop.equals("user.home")) {
matcher.appendReplacement(sb, Matcher.quoteReplacement(System.getProperty("user.home")));
} else {
throw new CoreException(new Status(0, "WPI", "Could not parse build.properties file, unsupported property: "+prop));
}
}
matcher.appendTail( sb );
props.setProperty((String) key, sb.toString());
count++;
}
if (count >= 50) overflow = true;
}
if (overflow) throw new CoreException(new Status(0, "WPI", "Could not parse build.properties file"));
return props;
}
}

View File

@@ -0,0 +1,178 @@
package edu.wpi.first.wpilib.plugins.core.installer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.swing.JOptionPane;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.omg.CORBA.Environment;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
public abstract class AbstractInstaller {
protected File installLocation;
protected String version;
public AbstractInstaller(String version) {
this.installLocation = new File(WPILibCore.getDefault().getWPILibBaseDir()
+ File.separator + getFeatureName() + File.separator + version);
this.version = version;
}
/**
* @return The name of the feature being installed.
*/
protected abstract String getFeatureName();
/**
* Update the installed version to the latest version.
* @param version The latest version installed.
*/
protected abstract void updateInstalledVersion(String version);
/**
* @return The input stream to the zip file being installed.
*/
protected abstract InputStream getInstallResourceStream();
public void installIfNecessary() {
System.out.println("Installing "+getFeatureName()+" if necessary");
try {
System.out.println("Install Location: "
+ installLocation.getCanonicalPath());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (!isInstalled()) {
System.out.println("Install necessary");
try {
install();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
updateInstalledVersion(version);
System.out.println("Installed");
}
/**
* This function has been updated to guarantee that the wpilib folder date
* is older than the jar file being run, which ensures up to date tools.
*
* @return True for is there and newer, false otherwise.
*/
public boolean isInstalled() {
if(installLocation.exists())
{
File coreJar = new File(AbstractInstaller.class.getProtectionDomain()
.getCodeSource().getLocation().getPath());
if(installLocation.lastModified() <= coreJar.lastModified())
{
return false;
}
else return true;
}
else return false;
}
/**
* This function will delete an old wpilib subfolder if necessary and then copy
* the resource stream to the intended directory.
*
* @throws IOException if bad things happen ...
*/
public void install() throws IOException {
if(installLocation.exists()) {
if(!removeFileHandler(installLocation, true)) {
JOptionPane.showMessageDialog(null,
String.format("Could not update the old wpilib folder.%n"
+ "Please close any WPILib tools and restart Eclipse."));
}
else
removeFileHandler(installLocation, false);
}
installLocation.mkdirs();
if (System.getProperty("os.name").startsWith("Mac OS X")) { // MACs are special...
InputStream zip = getInstallResourceStream();
File tmpFile = File.createTempFile(getFeatureName()+"-", ".zip");
FileOutputStream fout = new FileOutputStream(tmpFile);
copyStreams(zip, fout);
zip.close();
fout.close();
String[] cmd = {"unzip", tmpFile.getAbsolutePath(), "-d", installLocation.getAbsolutePath()};
System.out.println("unzip "+tmpFile.getAbsolutePath()+" -d "+installLocation.getAbsolutePath());
try {
InputStream is = DebugPlugin.exec(cmd, installLocation).getInputStream();
copyStreams(is, System.out);
} catch (CoreException e) {
e.printStackTrace();
}
} else {
ZipInputStream zip = new ZipInputStream(getInstallResourceStream());
ZipEntry entry = zip.getNextEntry();
while (entry != null) {
System.out.println("\tZipEntry " + entry + ": " + entry.getSize());
File f = new File(installLocation, entry.getName());
if (entry.isDirectory()) {
f.mkdirs();
} else {
FileOutputStream fo = new FileOutputStream(f);
copyStreams(zip, fo);
fo.close();
}
zip.closeEntry();
entry = zip.getNextEntry();
}
zip.close();
}
}
private static void copyStreams(InputStream source, OutputStream destination) throws IOException {
byte[] buffer = new byte[1024];
int len;
while((len = source.read(buffer)) >= 0){
destination.write(buffer,0,len);
}
}
/**
* Recursively remove all of the files and folders described by this file handler.
*
* @param file The file to remove
* @param testRun True to just test if the files can be deleted
* @return True if this and all subFiles were removed, false otherwise.
*/
private static boolean removeFileHandler(File file, boolean testRun) {
// if normal files (data files and the like)
if(file.isFile()) {
if(testRun) return file.getParentFile().canWrite();
else return file.delete();
}
// if folders
else if(file.isDirectory()) {
for(File f : file.listFiles()) {
if(!removeFileHandler(f, testRun))
return false;
}
if(testRun) return file.getParentFile().canWrite();
else return file.delete();
}
// I'm not sure what to do if the file is not normal or a directory ...
else return false;
}
}

View File

@@ -0,0 +1,38 @@
package edu.wpi.first.wpilib.plugins.core.installer;
import java.io.InputStream;
import java.util.Properties;
import org.eclipse.jface.preference.IPreferenceStore;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
import edu.wpi.first.wpilib.plugins.core.preferences.PreferenceConstants;
public class ToolsInstaller extends AbstractInstaller {
public ToolsInstaller(String version) {
super(version);
}
@Override
protected String getFeatureName() {
return "tools";
}
@Override
protected void updateInstalledVersion(String version) {
IPreferenceStore prefs = WPILibCore.getDefault().getPreferenceStore();
if (prefs.getBoolean(PreferenceConstants.UPDATE_TOOLS_VERSION)) {
System.out.println("Forcing library version to "+version);
Properties props = WPILibCore.getDefault().getProjectProperties(null);
props.setProperty("version", version);
WPILibCore.getDefault().saveGlobalProperties(props);
prefs.setValue(PreferenceConstants.TOOLS_VERSION, version);
}
}
@Override
protected InputStream getInstallResourceStream() {
return ToolsInstaller.class.getResourceAsStream("/resources/tools.zip");
}
}

View File

@@ -0,0 +1,144 @@
package edu.wpi.first.wpilib.plugins.core.launching;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.ant.internal.ui.launchConfigurations.AntLaunchShortcut;
import org.eclipse.ant.launching.IAntLaunchConstants;
import org.eclipse.core.externaltools.internal.IExternalToolConstants;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IConsoleConstants;
/**
* Contains functions to launch ant scripts while having the output sent to the
* console. Allows for the use of arguments, the specification of targets, and
* the choice of launch modes
*
* @author Ryan O'Meara
*/
@SuppressWarnings("restriction")
public class AntLauncher {
private static boolean installing = false;
/**
* Runs an ant script's target's with the given arguments, in the given launch mode
* @param antScript A java.io.File representation of the ant file to execute
* @param targets A String of the ant targets to run. For multiple targets,
* format if "target1,target2". For no targets, this argument can be null. This
* method will assume output should be sent to the console, same as calling
* runAntFile(antScript, targets, arguments, mode, true)
* @param arguments A String of arguments to run the file with. Format is
* "-argument1 -argument2". For no arguments, this argument can be null
* @param mode String, either "run" or "debug". If an invalid input is given,
* defaults to "run"
* @return The ILaunch started, or null if it failed to start
*/
public static ILaunch runAntFile(File antScript, String targets, String arguments, String mode){
return runAntFile(antScript, targets, arguments, mode, true);
}
/**
* Runs an ant script's target's with the given arguments, in the given launch mode
* @param antScript A java.io.File representation of the ant file to execute
* @param targets A String of the ant targets to run. For multiple targets,
* format if "target1,target2". For no targets, this argument can be null. Allows
* choice of outputting to the console
* @param arguments A String of arguments to run the file with. Format is
* "-argument1 -argument2". For no arguments, this argument can be null
* @param mode String, either "run" or "debug". If an invalid input is given,
* defaults to "run"
* @param outputToConsole If true, output will be sent to console, if false it will not
* @return The ILaunch started, or null if it failed to start
*/
public static ILaunch runAntFile(File antScript, String targets, String arguments, String mode, boolean outputToConsole){
//Input error checking
if((mode == null)||(!mode.equalsIgnoreCase(ILaunchManager.DEBUG_MODE))){mode = ILaunchManager.RUN_MODE;} //Launcher only accepts run or debug
if((targets != null)&&(targets.equalsIgnoreCase(""))){targets = null;} //Standardize representation of "none"
if((arguments != null)&&(arguments.equalsIgnoreCase(""))){arguments = null;}
if(antScript.getAbsolutePath().indexOf("install.xml") != -1){
installing = true;
}else{
installing = false;
}
ILaunch ret = null;
try{
//Show the console
if(outputToConsole){
try{
final IWorkbenchPage activePage = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getActivePage();
activePage.showView(IConsoleConstants.ID_CONSOLE_VIEW);
}catch(Exception e){}
}
//Get an ant launch config setup to use eclipse VM - which users will setup to be the jdk,
//allowing the use of javac. Also sets the location of the file to execute
ILaunchConfiguration launcher = AntLaunchShortcut.createDefaultLaunchConfiguration(new Path(antScript.getAbsolutePath()), null);
//Get copy that can be edited
ILaunchConfigurationWorkingCopy workingCopy = launcher.getWorkingCopy();
//Prevent this configuration from appearing in history or dialogs
workingCopy.setAttribute(ILaunchManager.ATTR_PRIVATE, false);
//Setup to show output on console
if(outputToConsole){
workingCopy.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, true);
workingCopy.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, true);
}else{
workingCopy.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, false);
workingCopy.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, false);
}
workingCopy.setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, true);
if(targets != null){
workingCopy.setAttribute(IAntLaunchConstants.ATTR_ANT_TARGETS, targets);
}
if(arguments != null){
workingCopy.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);
}
if(mode.equals(ILaunchManager.DEBUG_MODE)){
Set<String> modes = new HashSet<String>();
modes.add(ILaunchManager.DEBUG_MODE);
workingCopy.addModes(modes);
}
//Save/assert all changes
launcher = workingCopy.doSave();
//Launch the modified configuration in the specified mode
try{ret = launcher.launch(mode, null, true, true);}catch(Exception e){
//Does not need Output, handled and resolved internally
e.printStackTrace();
return null;
}
}catch(Exception e){
e.printStackTrace();
return null;
}
return ret;
}
public static boolean isInstalling(){
return installing;
}
}

View File

@@ -0,0 +1,97 @@
package edu.wpi.first.wpilib.plugins.core.nature;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Project nature which configures any project which is given it to be an
* FRC Project, and designates it so FRC options will be enabled to act on
* it
*
*/
public class FRCProjectNature implements IProjectNature {
public static final String FRC_PROJECT_NATURE =
"edu.wpi.first.wpilib.plugins.core.nature.FRCProjectNature";
private IProject internalProject;
/**
* IStatus representing a failed configuration attempt
*
* @author Ryan O'Meara
*/
private class FRCProjectFailedStatus implements IStatus{
String message;
public FRCProjectFailedStatus(String message){
this.message = message;
}
@Override
public IStatus[] getChildren() {return null;}
@Override
public int getCode() {return 0;}
@Override
public Throwable getException() {return null;}
@Override
public String getMessage() {return message;}
@Override
public String getPlugin() {return WPILibCore.PLUGIN_ID;}
@Override
public int getSeverity() {return ERROR;}
@Override
public boolean isMultiStatus() {return false;}
@Override
public boolean isOK() {return false;}
@Override
public boolean matches(int severityMask) {
if((severityMask & ERROR) == ERROR){return true;}
return false;
}
}
public FRCProjectNature(){
internalProject = null;
}
@Override
public void configure() throws CoreException {
if(internalProject == null){
throw new CoreException(
new FRCProjectFailedStatus("No project set"));
}
}
@Override
public void deconfigure() throws CoreException {
if(internalProject == null){
throw new CoreException(
new FRCProjectFailedStatus("No project set"));
}
}
@Override
public IProject getProject() {
return internalProject;
}
@Override
public void setProject(IProject project) {
internalProject = project;
}
}

View File

@@ -0,0 +1,69 @@
package edu.wpi.first.wpilib.plugins.core.preferences;
import java.util.List;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
public class ComboFieldEditor extends FieldEditor {
private List<String> choices;
private Composite parent;
Combo comboDropDown;
public ComboFieldEditor(String preference, String label, Composite parent, List<String> choices) {
super(preference, label, parent);
this.choices = choices;
for (String choice : choices) {
comboDropDown.add(choice);
}
}
public void setChoice(String item) {
comboDropDown.select(choices.indexOf(item));
}
public String getChoice() {
return choices.get(comboDropDown.getSelectionIndex());
}
@Override protected void adjustForNumColumns(int numColumns) {
((GridData) parent.getLayoutData()).horizontalSpan = numColumns;
}
@Override protected void doFillIntoGrid(Composite parent, int numColumns) {
this.parent = parent;
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = numColumns;
parent.setLayoutData(gd);
Label label = getLabelControl(parent);
label.setText(getLabelText());
comboDropDown = new Combo(parent, SWT.DROP_DOWN | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
comboDropDown.setLayoutData(gd);
}
@Override protected void doLoad() {
String item = getPreferenceStore().getString(getPreferenceName());
setChoice(item);
}
@Override protected void doLoadDefault() {
String item = getPreferenceStore().getDefaultString(getPreferenceName());
setChoice(item);
}
@Override protected void doStore() {
getPreferenceStore().setValue(getPreferenceName(), getChoice());
}
@Override public int getNumberOfControls() {
return 2;
}
}

View File

@@ -0,0 +1,10 @@
package edu.wpi.first.wpilib.plugins.core.preferences;
/**
* Constant definitions for plug-in preferences
*/
public class PreferenceConstants {
public static final String TEAM_NUMBER = "teamNumberPreference";
public static final String TOOLS_VERSION = "toolsVersionPreference";
public static final String UPDATE_TOOLS_VERSION = "udpateToolsVersionPreference";
}

View File

@@ -0,0 +1,25 @@
package edu.wpi.first.wpilib.plugins.core.preferences;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* Class used to initialize default preference values.
*/
public class PreferenceInitializer extends AbstractPreferenceInitializer {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
*/
public void initializeDefaultPreferences() {
IPreferenceStore store = WPILibCore.getDefault().getPreferenceStore();
store.setDefault(PreferenceConstants.TEAM_NUMBER,
WPILibCore.getDefault().getProjectProperties(null).getProperty("team-number", "0"));
store.setDefault(PreferenceConstants.TOOLS_VERSION, WPILibCore.getDefault().getDefaultVersion());
store.setDefault(PreferenceConstants.UPDATE_TOOLS_VERSION, true);
}
}

View File

@@ -0,0 +1,98 @@
package edu.wpi.first.wpilib.plugins.core.preferences;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
/**
* This class represents a preference page that
* is contributed to the Preferences dialog. By
* subclassing <samp>FieldEditorPreferencePage</samp>, we
* can use the field support built into JFace that allows
* us to create a page that is small and knows how to
* save, restore and apply itself.
* <p>
* This page is used to modify preferences only. They
* are stored in the preference store that belongs to
* the main plug-in class. That way, preferences can
* be accessed directly via the preference store.
*/
public class WPILibPreferencePage
extends FieldEditorPreferencePage
implements IWorkbenchPreferencePage {
IntegerFieldEditor teamNumberEditor;
private ComboFieldEditor toolsVersionEditor;
private BooleanFieldEditor autoUpdateEditor;
public WPILibPreferencePage() {
super(GRID);
setPreferenceStore(WPILibCore.getDefault().getPreferenceStore());
setDescription("A preference page for changing all workspace level settings.");
}
/**
* Creates the field editors. Field editors are abstractions of
* the common GUI blocks needed to manipulate various types
* of preferences. Each field editor knows how to save and
* restore itself.
*/
public void createFieldEditors() {
teamNumberEditor = new IntegerFieldEditor(PreferenceConstants.TEAM_NUMBER,
"&Team Number:", getFieldEditorParent());
addField(teamNumberEditor);
toolsVersionEditor = new ComboFieldEditor(PreferenceConstants.TOOLS_VERSION,
"&Tools Version:", getFieldEditorParent(), getInstalledVersions());
addField(toolsVersionEditor);
autoUpdateEditor = new BooleanFieldEditor(PreferenceConstants.UPDATE_TOOLS_VERSION,
"&Auto Update Tools Version", getFieldEditorParent());
addField(autoUpdateEditor);
}
private List<String> getInstalledVersions() {
File[] dirs = new File(WPILibCore.getDefault().getWPILibBaseDir()+File.separator+"tools")
.listFiles(new FileFilter() {
@Override public boolean accept(File f) {
return f.isDirectory();
}
});
List<String> versions = new ArrayList<String>();
for (File dir : dirs) {
versions.add(dir.getName());
}
Collections.sort(versions);
return versions;
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
System.out.println("Preferences initialized.");
Properties props = WPILibCore.getDefault().getProjectProperties(null);
getPreferenceStore().setValue(PreferenceConstants.TEAM_NUMBER,
Integer.parseInt(props.getProperty("team-number", "0")));
}
@Override public void performApply() {
performOk();
}
@Override public boolean performOk() {
Properties props = WPILibCore.getDefault().getProjectProperties(null);
props.setProperty("team-number", teamNumberEditor.getStringValue());
WPILibCore.getDefault().saveGlobalProperties(props);
return super.performOk();
}
}

View File

@@ -0,0 +1,88 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.net.URL;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;
public abstract class ExampleWizard extends Wizard implements INewWizard {
private ExampleWizardChoicePage page1;
private IWizardPage page2;
protected ISelection selection;
private TeamNumberPage teamNumberPage;
/**
* Constructor for SampleNewWizard.
*/
public ExampleWizard() {
super();
setNeedsProgressMonitor(true);
}
/**
* The worker method. It will find the container, create the
* file if missing or just replace its contents, and open
* the editor on the newly created file.
*/
protected abstract void doFinish(IExampleProject ex, String teamNumber) throws CoreException;
protected abstract IWizardPage getDetailsPage();
public abstract IExampleProject makeExampleProject(String name, String description,
List<String> tags, List<String> folders, List<IExampleProject.ExportFile> files);
public abstract URL getResourceURL();
public abstract String getXMLFile();
protected TeamNumberPage getTeamNumberPage() {
return teamNumberPage;
}
/**
* Adding the page to the wizard.
*/
public void addPages() {
if (TeamNumberPage.needsTeamNumberPage()) {
teamNumberPage = new TeamNumberPage(selection);
addPage(teamNumberPage);
}
page1 = new ExampleWizardChoicePage(this, selection);
addPage(page1);
page2 = getDetailsPage();
addPage(page2);
}
/**
* This method is called when 'Finish' button is pressed in
* the wizard. We will create an operation and run it
* using wizard as execution context.
*/
public boolean performFinish() {
try {
doFinish(page1.getExampleProject(), TeamNumberPage.getTeamNumberFromPage(teamNumberPage));
} catch (CoreException e) {
e.printStackTrace();
MessageDialog.openError(getShell(), "Error", e.getMessage());
return false;
}
return true;
}
/**
* We will accept the selection in the workbench to see if
* we can initialize from it.
* @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
*/
public void init(IWorkbench workbench, IStructuredSelection selection) {
this.selection = selection;
}
}

View File

@@ -0,0 +1,238 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* The "New" wizard page allows setting the container for the new file as well
* as the file name. The page will only accept file name without the extension
* OR with the extension that matches the expected one (mpe).
*/
public class ExampleWizardChoicePage extends WizardPage {
private Tree exampleTree;
private Browser descriptionText;
private IExampleProject selectedExample;
private ExampleWizard parent;
/**
* Constructor for SampleNewWizardPage.
*
* @param pageName
*/
public ExampleWizardChoicePage(ExampleWizard parent, ISelection selection) {
super("wizardPage");
this.parent = parent;
setTitle("Select Example Project to Create");
setDescription("This wizard creates a new example project based on your selection.");
}
/**
* @see IDialogPage#createControl(Composite)
*/
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
layout.verticalSpacing = 9;
exampleTree = new Tree(container, SWT.BORDER);
GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
gd.heightHint = 400;
exampleTree.setLayoutData(gd);
exampleTree.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
dialogChanged();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
dialogChanged();
}
});
descriptionText = new Browser(container, SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
gd.heightHint = 400;
gd.widthHint = 300;
descriptionText.setLayoutData(gd);
initialize();
dialogChanged();
setControl(container);
}
/**
* Tests if the current workbench selection is a suitable container to use.
*/
private void initialize() {
Document doc = loadXMLResource(parent.getXMLFile());
// Generate all of the tags
List<Tag> tags = new ArrayList<Tag>();
NodeList nList = doc.getElementsByTagName("tagDescription");
for (int i = 0; i < nList.getLength(); i++) {
if (nList.item(i).getNodeType() == Node.ELEMENT_NODE) {
tags.add(generateTagFromElement((Element) nList.item(i)));
}
}
// Generate all of the example projects
List<IExampleProject> examples = new ArrayList<IExampleProject>();
nList = doc.getElementsByTagName("example");
for (int i = 0; i < nList.getLength(); i++) {
if (nList.item(i).getNodeType() == Node.ELEMENT_NODE) {
examples.add(generateExampleFromElement((Element) nList.item(i)));
}
}
System.out.println(examples);
System.out.println(tags);
// Generate the tags tree
for (Tag tag : tags) {
TreeItem tagItem = new TreeItem(exampleTree, SWT.NONE);
tagItem.setData(tag);
tagItem.setText(tag.getName());
for (IExampleProject ex : examples) {
if (ex.getTags().contains(tag.getName())) {
TreeItem exItem = new TreeItem(tagItem, SWT.NONE);
exItem.setData(ex);
exItem.setText(ex.getName());
}
}
tagItem.setExpanded(true);
}
}
/**
* Ensures that both text fields are set.
*/
private void dialogChanged() {
if (exampleTree.getSelection().length > 0) {
Object selectedData = exampleTree.getSelection()[0].getData();
if (selectedData instanceof IExampleProject) {
IExampleProject example = (IExampleProject) selectedData;
descriptionText.setText(example.getContent());
selectedExample = example;
} else if (selectedData instanceof Tag) {
Tag tag = (Tag) selectedData;
descriptionText.setText(tag.getContent());
selectedExample = null;
} else selectedExample = null;
}
if (selectedExample == null) {
updateStatus("Must select a valid example before continuing.");
return;
}
updateStatus(null);
}
private void updateStatus(String message) {
setErrorMessage(message);
setPageComplete(message == null);
}
private Document loadXMLResource(String filename) {
final URL installURL = parent.getResourceURL();
URL url = null;
try {
url = new URL(installURL, filename);
} catch (final MalformedURLException e) {
e.printStackTrace();
return null;
}
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
Document doc;
try {
dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(url.openStream());
} catch (ParserConfigurationException e) {
e.printStackTrace();
return null;
} catch (SAXException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
doc.getDocumentElement().normalize();
return doc;
}
private Tag generateTagFromElement(Element element) {
String name = element.getElementsByTagName("name").item(0).getTextContent();
String description = element.getElementsByTagName("description").item(0).getTextContent();
return new Tag(name, description);
}
private IExampleProject generateExampleFromElement(Element element) {
String name = element.getElementsByTagName("name").item(0).getTextContent();
String description = element.getElementsByTagName("description").item(0).getTextContent();
List<String> tags = new ArrayList<String>();
Node tagsElement = element.getElementsByTagName("tags").item(0);
if (tagsElement.getNodeType() == Node.ELEMENT_NODE) {
NodeList tagElementList = ((Element) tagsElement).getElementsByTagName("tag");
for (int i = 0; i < tagElementList.getLength(); i++) {
tags.add(tagElementList.item(i).getTextContent());
}
}
List<String> packages = new ArrayList<String>();
tagsElement = element.getElementsByTagName("packages").item(0);
if (tagsElement.getNodeType() == Node.ELEMENT_NODE) {
NodeList elementList = ((Element) tagsElement).getElementsByTagName("package");
for (int i = 0; i < elementList.getLength(); i++) {
packages.add(elementList.item(i).getTextContent());
}
}
List<IExampleProject.ExportFile> files = new ArrayList<IExampleProject.ExportFile>();
tagsElement = element.getElementsByTagName("files").item(0);
if (tagsElement.getNodeType() == Node.ELEMENT_NODE) {
NodeList elementList = ((Element) tagsElement).getElementsByTagName("file");
for (int i = 0; i < elementList.getLength(); i++) {
if (elementList.item(i).getNodeType() == Node.ELEMENT_NODE) {
element = (Element) elementList.item(i);
files.add(new IExampleProject.ExportFile(element.getAttribute("source"),
element.getAttribute("destination")));
}
}
}
return parent.makeExampleProject(name, description, tags, packages, files);
}
public IExampleProject getExampleProject() {
return selectedExample;
}
}

View File

@@ -0,0 +1,17 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.util.List;
public interface IExampleProject extends ProjectType {
public String getName();
public String getContent();
public List<String> getTags();
static class ExportFile {
public String source, destination;
public ExportFile(String source, String destination) {
this.source = source;
this.destination = destination;
}
}
}

View File

@@ -0,0 +1,60 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
/**
* An interface for providing hooks into the project creation
* process. It provides necessary information and can perform
* both initialization and finalization of the project
* creation process.
*
* @author Alex Henning
*/
public interface IProjectCreator {
/**
* @return The name of the project to create.
*/
String getName();
/**
* @return The main package to be created. Should be an
* empty string if irrelevant.
*/
String getPackageName();
/**
* @return Map of keys to be substituted with values
* during the creation process.
*/
Map<String, String> getValues();
/**
* @return The natures that this project should have.
*/
List<String> getNatures();
/**
* @return A project type object that provides files
* and directories to create.
*/
ProjectType getProjectType();
/**
* Run extra initialization code on the project.
* @param project The project being created
* @throws CoreException
*/
void initialize(IProject project) throws CoreException;
/**
* Run extra finalization code on the project.
* @param project The project being created
* @throws CoreException
*/
void finalize(IProject project) throws CoreException;
}

View File

@@ -0,0 +1,17 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import org.eclipse.core.resources.IProject;
/**
* A filter that can be used to select projects.
*
* @author alex
*
*/
public interface IProjectFilter {
/**
* @param project The project to check.
* @return Whether or to accept the project.
*/
boolean accept(IProject project);
}

View File

@@ -0,0 +1,197 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.util.Map;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/**
* The "New" wizard page allows setting the container for the new file as well
* as the file name. The page will only accept file name without the extension
* OR with the extension that matches the expected one (mpe).
*/
public class NewProjectMainPage extends WizardPage {
private Text projectNameText;
private Text packageText;
Map<String, ProjectType> types;
Button simpleRobot, iterativeRobot, commandRobot;
private boolean showPackage;
private boolean showProjectTypes;
private TeamNumberPage teamNumberPage;
/**
* Constructor for SampleNewWizardPage.
* @param teamNumberPage
*
* @param pageName
*/
public NewProjectMainPage(ISelection selection, TeamNumberPage teamNumberPage) {
super("wizardPage");
this.teamNumberPage = teamNumberPage;
showPackage = true;
showProjectTypes = false;
}
/**
* @see IDialogPage#createControl(Composite)
*/
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
layout.verticalSpacing = 9;
Label label = new Label(container, SWT.NULL);
label.setText("Project &Name:");
projectNameText = new Text(container, SWT.BORDER | SWT.SINGLE);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
projectNameText.setLayoutData(gd);
projectNameText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
dialogChanged();
}
});
if (showPackage) {
label = new Label(container, SWT.NULL);
label.setText("&Package:");
packageText = new Text(container, SWT.BORDER | SWT.SINGLE);
gd = new GridData(GridData.FILL_HORIZONTAL);
packageText.setLayoutData(gd);
packageText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
dialogChanged();
}
});
}
if (showProjectTypes) {
Group projectTypeGroup = new Group(container, SWT.BORDER);
projectTypeGroup.setText("Project Type");
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
projectTypeGroup.setLayoutData(gd);
GridLayout groupLayout = new GridLayout();
groupLayout.numColumns = 1;
projectTypeGroup.setLayout(groupLayout);
simpleRobot = new Button(projectTypeGroup, SWT.RADIO | SWT.WRAP);
//simpleRobot.setData( RWT.MARKUP_ENABLED, Boolean.TRUE );
simpleRobot.setText("Simple Robot: A flexible robot project intended for robots that implement basic functionality. Can also be used as a starting point for teams with a custom framework.");
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = 300;
simpleRobot.setLayoutData(gd);
simpleRobot.setSelection(true);
iterativeRobot = new Button(projectTypeGroup, SWT.RADIO | SWT.WRAP);
iterativeRobot.setText("Iterative Robot: A robot project that allows robots to be implemented in an iterative manner.");
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = 300;
iterativeRobot.setLayoutData(gd);
commandRobot = new Button(projectTypeGroup, SWT.RADIO | SWT.WRAP);
commandRobot.setText("Command-Based Robot: A robot project that allows robots to be implemented using the command based model to allow complex functionality to be developed from simpler functionality.");
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = 300;
commandRobot.setLayoutData(gd);
}
initialize();
dialogChanged();
setControl(container);
}
/**
* Tests if the current workbench selection is a suitable container to use.
*/
private void initialize() {
String teamNumber = TeamNumberPage.getTeamNumberFromPage(teamNumberPage);
if (showPackage) {
packageText.setText("com.first.team"+teamNumber+".robot");
if (teamNumberPage != null) {
teamNumberPage.registerChangeListener(new ChangeListener() {
@Override public void stateChanged(ChangeEvent e) {
String teamNumber = TeamNumberPage.getTeamNumberFromPage(teamNumberPage);
packageText.setText("com.first.team"+teamNumber+".robot");
}
});
}
}
}
/**
* Ensures that both text fields are set.
*/
private void dialogChanged() {
String projectName = getProjectName();
String packageString = "";
if (showPackage) packageString = getPackage();
if (projectName.length() == 0) {
updateStatus("Project name must be specified");
return;
}
if (showPackage && packageString.length() == 0) {
updateStatus("Package must be specified");
return;
}
if (showPackage && !packageString.matches("^([a-zA-Z_]{1}[a-zA-Z0-9_]*(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*)$")) {
updateStatus("Must be valid java package");
return;
}
updateStatus(null);
}
private void updateStatus(String message) {
setErrorMessage(message);
setPageComplete(message == null);
}
public String getProjectName() {
return projectNameText.getText();
}
public String getPackage() {
return packageText.getText();
}
public ProjectType getProjectType() {
if (!showProjectTypes) return null;
else if (simpleRobot.getSelection()) return types.get(ProjectType.SIMPLE);
else if (iterativeRobot.getSelection()) return types.get(ProjectType.ITERATIVE);
else return types.get(ProjectType.COMMAND_BASED);
}
public void setShowPackage(boolean bool) {
showPackage = bool;
}
public void setShowProjectTypes(boolean bool) {
showProjectTypes = bool;
}
public void setProjectTypes(Map<String, ProjectType> types) {
showProjectTypes = true;
this.types = types;
}
}

View File

@@ -0,0 +1,51 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.util.Arrays;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
public class ProjectComboField {
public static String NO_PROJECT = "No Project";
private Combo combo;
public ProjectComboField(Composite composite, int config, IProjectFilter filter) {
combo = new Combo(composite, config);
combo.add(NO_PROJECT);
combo.select(0);
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : projects) {
if (filter == null || filter.accept(project))
combo.add(project.getName());
}
}
public void setProject(IProject project) {
if (project != null)
combo.select(Arrays.binarySearch(combo.getItems(), project.getName()));
else combo.select(0);
}
public IProject getProject() {
return ResourcesPlugin.getWorkspace().getRoot().getProject(combo.getItem(combo.getSelectionIndex()));
}
public boolean isValid() {
return combo.getSelectionIndex() != 0;
}
public void setLayoutData(GridData gd) {
combo.setLayoutData(gd);
}
public void addModifyListener(ModifyListener modifyListener) {
combo.addModifyListener(modifyListener);
}
}

View File

@@ -0,0 +1,195 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* Utilities for creating a new project and files from templates. Uses
* IProjectCreator to provide hooks for generating the directory
* structure, initial files, initializing and finalizing the creation
* of the new project.
*
* @author Alex Henning
**/
public class ProjectCreationUtils {
/**
* Create a project using the given IProjectCreator.
*
* @param creator The creator that provides the necessary information
* to create the project.
* @return The newly created project.
*/
public static IProject createProject(IProjectCreator creator) {
IProject project = createBaseProject(creator.getName(), null);
try {
creator.initialize(project);
for (String nature : creator.getNatures()) {
addNature(project, nature);
}
addToProjectStructure(project, creator);
addFilesToProject(project, creator);
creator.finalize(project);
} catch (CoreException e) {
e.printStackTrace();
project = null;
}
return project;
}
private static IProject createBaseProject(String projectName, IPath location) {
IProject newProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
if (!newProject.exists()) {
IPath projectLocation = location;
IProjectDescription desc = newProject.getWorkspace().newProjectDescription(newProject.getName());
if (location != null &&
ResourcesPlugin.getWorkspace().getRoot().getLocation().equals(location)) {
projectLocation = null;
}
desc.setLocation(projectLocation);
try {
newProject.create(desc, null);
if (!newProject.isOpen()) {
newProject.open(null);
}
} catch (CoreException e) {
e.printStackTrace();
}
}
return newProject;
}
private static void addNature(IProject project, String nature_id) throws CoreException {
if (!project.hasNature(nature_id)) {
IProjectDescription desc = project.getDescription();
String[] prevNatures = desc.getNatureIds();
String[] newNatures = new String[prevNatures.length + 1];
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
newNatures[prevNatures.length] = nature_id;
desc.setNatureIds(newNatures);
project.setDescription(desc, null);
}
}
private static void addToProjectStructure(IProject project, IProjectCreator creator) throws CoreException {
String[] paths = creator.getProjectType().getFolders(creator.getPackageName());
for (String path : paths) {
IFolder etcFolders = project.getFolder(path);
createFolder(etcFolders);
}
}
private static void createFolder(IFolder folder) throws CoreException {
IContainer parent = folder.getParent();
if (parent instanceof IFolder) {
createFolder((IFolder) parent);
}
if (!folder.exists()) {
folder.create(false, true, null);
}
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
}
private static void addFilesToProject(IProject project, IProjectCreator creator) throws CoreException {
Map<String, String> files = creator.getProjectType().getFiles(creator.getPackageName());
for (Entry<String, String> e : files.entrySet()) {
try {
URL url = new URL(creator.getProjectType().getBaseURL(), e.getValue());
createTemplateFile(project, e.getKey(), url, creator.getValues());
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
/**
* Create a file in the project from a template. Substituting as required.
*
* @param project The project to use create the file in.
* @param filepath The path of the created file.
* @param filesource The source of the template to use.
* @param vals The map of values to use for substitution.
* @throws CoreException
*/
public static void createTemplateFile(IProject project, String filepath, URL url, Map<String, String> vals) throws CoreException {
IFile template = project.getFile(new Path(filepath));
if (!template.exists()) {
InputStream in = openTemplateContentStream(project, url, vals);
template.create(in, true, null);
}
}
private static InputStream openTemplateContentStream(IProject project, URL url, Map<String, String> vals) {
//http://eclipse-javacc.cvs.sourceforge.net/viewvc/eclipse-javacc/sf.eclipse.javacc/src-plugin/sf/eclipse/javacc/wizards/JJNewWizard.java?view=markup
//eclipse plugin distributing template files
try {
return makeTemplateInputStream(url.openStream(), vals);
} catch (final MalformedURLException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
return null;
}
private static InputStream makeTemplateInputStream(InputStream stream, Map<String, String> vals) {
String str;
try {
str = readInput(stream);
stream.close();
} catch (final IOException e) {
e.printStackTrace();
return null;
}
// Instantiate template
for (Entry<String, String> e : vals.entrySet())
str = str.replace(e.getKey(), e.getValue());
return new ByteArrayInputStream(str.getBytes());
}
private static String readInput(InputStream stream) {
StringBuffer buffer = new StringBuffer();
try {
InputStreamReader isr = new InputStreamReader(stream);
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1) {
buffer.append((char)ch);
}
System.out.print("\n");
in.close();
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,14 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import java.net.URL;
import java.util.Map;
public interface ProjectType {
String SIMPLE = "SIMPLE";
String ITERATIVE = "ITERATIVE";
String COMMAND_BASED = "COMMAND_BASED";
String[] getFolders(String packageName);
Map<String, String> getFiles(String packageName);
URL getBaseURL();
}

View File

@@ -0,0 +1,19 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
public class Tag {
private String name, description;
public Tag(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public String getContent() {
return "<h1>"+name+"</h1><p>"+description+"</p>";
}
}

View File

@@ -0,0 +1,111 @@
package edu.wpi.first.wpilib.plugins.core.wizards;
import javax.swing.event.ChangeListener;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import edu.wpi.first.wpilib.plugins.core.WPILibCore;
public class TeamNumberPage extends WizardPage {
private Text teamNumberText;
private ChangeListener listener;
/**
* Constructor for SampleNewWizardPage.
*
* @param pageName
*/
public TeamNumberPage(ISelection selection) {
super("wizardPage");
setTitle("Set Team Number");
setDescription("This page lets you set your team number so that code can be loaded onto the right robot.");
}
/**
* @see IDialogPage#createControl(Composite)
*/
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
layout.verticalSpacing = 9;
Label label = new Label(container, SWT.NULL);
label.setText("Team &Number:");
teamNumberText = new Text(container, SWT.BORDER | SWT.SINGLE);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
teamNumberText.setLayoutData(gd);
teamNumberText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
dialogChanged();
}
});
label = new Label(container, SWT.NULL);
label.setText("Team number is a global setting that can be changed in Window > Preferences > WPILib Preferences > Team Number");
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
label.setLayoutData(gd);
initialize();
dialogChanged();
setControl(container);
}
/**
* Tests if the current workbench selection is a suitable container to use.
*/
private void initialize() {
String teamNumber = Integer.toString(WPILibCore.getDefault().getTeamNumber(null));
teamNumberText.setText(teamNumber);
}
/**
* Ensures that both text fields are set.
*/
private void dialogChanged() {
String teamNumber = getTeamNumber();
if (listener != null) listener.stateChanged(null);
if (!teamNumber.matches("^([0-9]+)$")) {
updateStatus("Team number must be a valid integer.");
return;
}
updateStatus(null);
}
private void updateStatus(String message) {
setErrorMessage(message);
setPageComplete(message == null);
}
public String getTeamNumber() {
return teamNumberText.getText();
}
public static boolean needsTeamNumberPage() {
return WPILibCore.getDefault().getTeamNumber(null) == 0;
}
public static String getTeamNumberFromPage(TeamNumberPage teamNumberPage) {
if (teamNumberPage != null) {
return teamNumberPage.getTeamNumber();
} else {
return Integer.toString(WPILibCore.getDefault().getTeamNumber(null));
}
}
public void registerChangeListener(ChangeListener changeListener) {
listener = changeListener;
}
}