From 84a2b3f7c7053b5f9b88b44aa68219b317b5c5ef Mon Sep 17 00:00:00 2001 From: benfry Date: Tue, 24 Jul 2012 10:45:08 +0000 Subject: [PATCH] command line starting to work again --- app/src/processing/app/Base.java | 170 ++++++------ app/src/processing/app/Editor.java | 6 +- app/src/processing/app/Mode.java | 26 +- app/src/processing/app/Sketch.java | 41 ++- .../app/contrib/ContributionManager.java | 166 ++++++------ .../app/contrib/ModeContribution.java | 51 ++-- app/src/processing/mode/java/Commander.java | 252 ++++++++++++------ app/src/processing/mode/java/JavaBuild.java | 20 +- app/src/processing/mode/java/JavaMode.java | 26 -- todo.txt | 68 +++-- 10 files changed, 442 insertions(+), 384 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 43d1975c7..38aeb75ed 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -126,8 +126,8 @@ public class Base { private Recent recent; // private JMenu recentMenu; - protected File sketchbookFolder; - protected File toolsFolder; + static protected File sketchbookFolder; +// protected File toolsFolder; static public void main(final String[] args) { @@ -167,6 +167,9 @@ public class Base { // run static initialization that grabs all the prefs Preferences.init(null); + // Get the sketchbook path, and make sure it's set properly + locateSketchbookFolder(); + // String filename = args.length > 1 ? args[0] : null; if (!SingleInstance.alreadyRunning(args)) { // SingleInstance.startServer(platform); @@ -265,8 +268,12 @@ public class Base { getContentFile("modes/javascript")); coreModes = new Mode[] { javaMode, androidMode, javaScriptMode }; + for (Mode mode : coreModes) { + mode.setupGUI(); + } } + /** Instantiates and adds new contributed modes to the contribModes list. * Checks for duplicates so the same mode isn't instantiates twice. Does not * remove modes because modes can't be removed once they are instantiated */ @@ -286,8 +293,8 @@ public class Base { } public Base(String[] args) { - // Get the sketchbook path, and make sure it's set properly - determineSketchbookFolder(); +// // Get the sketchbook path, and make sure it's set properly +// determineSketchbookFolder(); // Delete all modes and tools that have been flagged for deletion before // they are initialized by an editor. @@ -362,11 +369,11 @@ public class Base { // menu works on Mac OS X (since it needs examplesFolder to be set). platform.init(this); - toolsFolder = getContentFile("tools"); +// toolsFolder = getContentFile("tools"); // // Check if there were previously opened sketches to be restored - boolean opened = restoreSketches(); -// boolean opened = false; +// boolean opened = restoreSketches(); + boolean opened = false; // Check if any files were passed in on the command line for (int i = 0; i < args.length; i++) { @@ -418,77 +425,77 @@ public class Base { // } - /** - * Post-constructor setup for the editor area. Loads the last - * sketch that was used (if any), and restores other Editor settings. - * The complement to "storePreferences", this is called when the - * application is first launched. - */ - protected boolean restoreSketches() { -// String lastMode = Preferences.get("last.sketch.mode"); -// log("setting mode to " + lastMode); -// if (lastMode != null) { -// for (Mode m : getModeList()) { -// if (m.getClass().getName().equals(lastMode)) { -// defaultMode = m; -// } -// } -// } -// log("default mode set to " + defaultMode.getClass().getName()); - - if (Preferences.getBoolean("last.sketch.restore")) { - return false; - } - - return true; - -// // figure out window placement -// Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); -// boolean windowPositionValid = true; +// /** +// * Post-constructor setup for the editor area. Loads the last +// * sketch that was used (if any), and restores other Editor settings. +// * The complement to "storePreferences", this is called when the +// * application is first launched. +// */ +// protected boolean restoreSketches() { +//// String lastMode = Preferences.get("last.sketch.mode"); +//// log("setting mode to " + lastMode); +//// if (lastMode != null) { +//// for (Mode m : getModeList()) { +//// if (m.getClass().getName().equals(lastMode)) { +//// defaultMode = m; +//// } +//// } +//// } +//// log("default mode set to " + defaultMode.getClass().getName()); // -// if (Preferences.get("last.screen.height") != null) { -// // if screen size has changed, the window coordinates no longer -// // make sense, so don't use them unless they're identical -// int screenW = Preferences.getInteger("last.screen.width"); -// int screenH = Preferences.getInteger("last.screen.height"); -// -// if ((screen.width != screenW) || (screen.height != screenH)) { -// windowPositionValid = false; -// } -// /* -// int windowX = Preferences.getInteger("last.window.x"); -// int windowY = Preferences.getInteger("last.window.y"); -// if ((windowX < 0) || (windowY < 0) || -// (windowX > screenW) || (windowY > screenH)) { -// windowPositionValid = false; -// } -// */ -// } else { -// windowPositionValid = false; +// if (Preferences.getBoolean("last.sketch.restore")) { +// return false; // } // -// // Iterate through all sketches that were open last time p5 was running. -// // If !windowPositionValid, then ignore the coordinates found for each. +// return true; // -// // Save the sketch path and window placement for each open sketch -// int count = Preferences.getInteger("last.sketch.count"); -// int opened = 0; -// for (int i = 0; i < count; i++) { -// String path = Preferences.get("last.sketch" + i + ".path"); -// int[] location; -// if (windowPositionValid) { -// String locationStr = Preferences.get("last.sketch" + i + ".location"); -// location = PApplet.parseInt(PApplet.split(locationStr, ',')); -// } else { -// location = nextEditorLocation(); -// } -// // If file did not exist, null will be returned for the Editor -// if (handleOpen(path, location) != null) { -// opened++; -// } -// } -// return (opened > 0); - } +//// // figure out window placement +//// Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); +//// boolean windowPositionValid = true; +//// +//// if (Preferences.get("last.screen.height") != null) { +//// // if screen size has changed, the window coordinates no longer +//// // make sense, so don't use them unless they're identical +//// int screenW = Preferences.getInteger("last.screen.width"); +//// int screenH = Preferences.getInteger("last.screen.height"); +//// +//// if ((screen.width != screenW) || (screen.height != screenH)) { +//// windowPositionValid = false; +//// } +//// /* +//// int windowX = Preferences.getInteger("last.window.x"); +//// int windowY = Preferences.getInteger("last.window.y"); +//// if ((windowX < 0) || (windowY < 0) || +//// (windowX > screenW) || (windowY > screenH)) { +//// windowPositionValid = false; +//// } +//// */ +//// } else { +//// windowPositionValid = false; +//// } +//// +//// // Iterate through all sketches that were open last time p5 was running. +//// // If !windowPositionValid, then ignore the coordinates found for each. +//// +//// // Save the sketch path and window placement for each open sketch +//// int count = Preferences.getInteger("last.sketch.count"); +//// int opened = 0; +//// for (int i = 0; i < count; i++) { +//// String path = Preferences.get("last.sketch" + i + ".path"); +//// int[] location; +//// if (windowPositionValid) { +//// String locationStr = Preferences.get("last.sketch" + i + ".location"); +//// location = PApplet.parseInt(PApplet.split(locationStr, ',')); +//// } else { +//// location = nextEditorLocation(); +//// } +//// // If file did not exist, null will be returned for the Editor +//// if (handleOpen(path, location) != null) { +//// opened++; +//// } +//// } +//// return (opened > 0); +// } // /** @@ -1823,8 +1830,9 @@ public class Base { // static public File getToolsFolder() { - public File getToolsFolder() { - return toolsFolder; + static public File getToolsFolder() { +// return toolsFolder; + return getContentFile("tools"); } @@ -1833,7 +1841,7 @@ public class Base { // } - protected void determineSketchbookFolder() { + static public void locateSketchbookFolder() { // If a value is at least set, first check to see if the folder exists. // If it doesn't, warn the user that the sketchbook folder is being reset. String sketchbookPath = Preferences.get("sketchbook.path"); @@ -1879,20 +1887,22 @@ public class Base { } - public File getSketchbookLibrariesFolder() { + static public File getSketchbookLibrariesFolder() { // return new File(getSketchbookFolder(), "libraries"); return new File(sketchbookFolder, "libraries"); } - public File getSketchbookToolsFolder() { + static public File getSketchbookToolsFolder() { return new File(sketchbookFolder, "tools"); } - public File getSketchbookModesFolder() { + + static public File getSketchbookModesFolder() { return new File(sketchbookFolder, "modes"); } + static protected File getDefaultSketchbookFolder() { File sketchbookFolder = null; try { diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 67848a08c..21d38aae0 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -904,8 +904,8 @@ public abstract class Editor extends JFrame implements RunnerListener { protected void rebuildToolList() { - coreTools = ToolContribution.list(base.getToolsFolder(), true); - contribTools = ToolContribution.list(base.getSketchbookToolsFolder(), true); + coreTools = ToolContribution.list(Base.getToolsFolder(), true); + contribTools = ToolContribution.list(Base.getSketchbookToolsFolder(), true); } @@ -2029,7 +2029,7 @@ public abstract class Editor extends JFrame implements RunnerListener { } try { - sketch = new Sketch(this, path); + sketch = new Sketch(path, this); } catch (IOException e) { Base.showWarning("Error", "Could not create the sketch.", e); return false; diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index ac0b0989d..71cb34fe5 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -50,6 +50,11 @@ public abstract class Mode { protected Library coreLibrary; +// public Mode(Base base, File folder) { +// this(base, folder, base.getSketchbookLibrariesFolder()); +// } + + public Mode(Base base, File folder) { this.base = base; this.folder = folder; @@ -62,7 +67,14 @@ public abstract class Mode { // rebuildToolbarMenu(); rebuildLibraryList(); // rebuildExamplesMenu(); + } + + /** + * Setup additional elements that are only required when running + * with a GUI, rather than from the command-line. + */ + public void setupGUI() { try { theme = new Settings(new File(folder, "theme/theme.txt")); @@ -129,20 +141,20 @@ public abstract class Mode { public void rebuildLibraryList() { -// System.out.println("rebuildLibraryList()"); - // reset the table mapping imports to libraries -// importToLibraryTable = new HashMap(); importToLibraryTable = new HashMap>(); coreLibraries = Library.list(librariesFolder); - contribLibraries = Library.list(base.getSketchbookLibrariesFolder()); - for (Library lib : coreLibraries) { lib.addPackageList(importToLibraryTable); } - for (Library lib : contribLibraries) { - lib.addPackageList(importToLibraryTable); + + File contribLibrariesFolder = Base.getSketchbookLibrariesFolder(); + if (contribLibrariesFolder != null) { + contribLibraries = Library.list(contribLibrariesFolder); + for (Library lib : contribLibraries) { + lib.addPackageList(importToLibraryTable); + } } } diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 76c6ba1a5..94e0898af 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -94,44 +94,37 @@ public class Sketch { // private File buildFolder; + /** + * Used by the command-line version to create a sketch object. + * @param path location of the main .pde file + * @param mode what flavor of sketch we're dealing with. + */ + public Sketch(String path, Mode mode) { + this.editor = null; + this.mode = mode; + load(path); + } + + /** * path is location of the main .pde file, because this is also * simplest to use when opening the file from the finder/explorer. */ - public Sketch(Editor editor, String path) throws IOException { + public Sketch(String path, Editor editor) throws IOException { this.editor = editor; this.mode = editor.getMode(); + load(path); + } + + protected void load(String path) { primaryFile = new File(path); - // get the name of the sketch by chopping .pde or .java // off of the main file name String mainFilename = primaryFile.getName(); int suffixLength = mode.getDefaultExtension().length() + 1; name = mainFilename.substring(0, mainFilename.length() - suffixLength); - - // lib/build must exist when the application is started - // it is added to the CLASSPATH by default, but if it doesn't - // exist when the application is started, then java will remove - // the entry from the CLASSPATH, causing Runner to fail. - // - /* - tempBuildFolder = new File(TEMP_BUILD_PATH); - if (!tempBuildFolder.exists()) { - tempBuildFolder.mkdirs(); - Base.showError("Required folder missing", - "A required folder was missing from \n" + - "from your installation of Processing.\n" + - "It has now been replaced, please restart \n" + - "the application to complete the repair.", null); - } - */ -// tempBuildFolder = Base.getBuildFolder(); - //Base.addBuildFolderToClassPath(); - folder = new File(new File(path).getParent()); - //System.out.println("sketch dir is " + folder); - load(); } diff --git a/app/src/processing/app/contrib/ContributionManager.java b/app/src/processing/app/contrib/ContributionManager.java index 0895735f3..003435e8a 100644 --- a/app/src/processing/app/contrib/ContributionManager.java +++ b/app/src/processing/app/contrib/ContributionManager.java @@ -20,15 +20,15 @@ interface ErrorWidget { } public class ContributionManager { - + static public final String DELETION_FLAG = "flagged_for_deletion"; - + static public final ContributionListing contribListing; static { contribListing = ContributionListing.getInstance(); } - + /** * Non-blocking call to remove a contribution in a new thread. */ @@ -38,17 +38,17 @@ public class ContributionManager { final ErrorWidget statusBar) { if (contribution == null) return; - + final ProgressMonitor progressMonitor = pm != null ? pm : new NullProgressMonitor(); - + new Thread(new Runnable() { - + public void run() { progressMonitor.startTask("Removing", ProgressMonitor.UNKNOWN); boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove"); if (ContributionManager.requiresRestart(contribution)) { - + if (!doBackup || (doBackup && backupContribution(editor, contribution, false, statusBar))) { if (ContributionManager.flagForDeletion(contribution)) { contribListing.replaceContribution(contribution, contribution); @@ -62,7 +62,7 @@ public class ContributionManager { Base.removeDir(contribution.getFolder()); success = !contribution.getFolder().exists(); } - + if (success) { Contribution advertisedVersion = contribListing .getAdvertisedContribution(contribution); @@ -76,7 +76,7 @@ public class ContributionManager { } else { // There was a failure backing up the folder if (doBackup) { - + } else { statusBar.setErrorMessage("Could not delete the contribution's files"); } @@ -91,7 +91,7 @@ public class ContributionManager { /** * Non-blocking call to download and install a contribution in a new thread. - * + * * @param url * Direct link to the contribution. * @param toBeReplaced @@ -114,27 +114,27 @@ public class ContributionManager { public void run() { FileDownloader.downloadFile(url, libDest, downloadProgressMonitor); - - + + if (!downloadProgressMonitor.isCanceled() && !downloadProgressMonitor.isError()) { - + installProgressMonitor.startTask("Installing", ProgressMonitor.UNKNOWN); - + InstalledContribution contribution = null; contribution = install(editor, libDest, ad, false, statusBar); - + if (contribution != null) { contribListing.replaceContribution(ad, contribution); refreshInstalled(editor); } - + installProgressMonitor.finished(); } } }).start(); } - + static public void refreshInstalled(Editor editor) { editor.getMode().rebuildImportMenu(); editor.rebuildToolMenu(); @@ -152,10 +152,10 @@ public class ContributionManager { case MODE: return ModeContribution.discover(tempDir); } - + return null; } - + static String getPropertiesFileName(Type type) { switch (type) { case LIBRARY: @@ -167,23 +167,23 @@ public class ContributionManager { case MODE: return ModeContribution.propertiesFileName; } - + return null; } - + static File getSketchbookContribFolder(Base base, Type type) { switch (type) { case LIBRARY: case LIBRARY_COMPILATION: - return base.getSketchbookLibrariesFolder(); + return Base.getSketchbookLibrariesFolder(); case TOOL: - return base.getSketchbookToolsFolder(); + return Base.getSketchbookToolsFolder(); case MODE: - return base.getSketchbookModesFolder(); + return Base.getSketchbookModesFolder(); } return null; } - + static InstalledContribution create(Base base, Type type, File folder) { switch (type) { case LIBRARY: @@ -195,10 +195,10 @@ public class ContributionManager { case MODE: return ModeContribution.getContributedMode(base, folder); } - + return null; } - + static ArrayList getContributions(Type type, Editor editor) { ArrayList contribs = new ArrayList(); switch (type) { @@ -217,7 +217,7 @@ public class ContributionManager { } return contribs; } - + static void initialize(InstalledContribution contribution) throws Exception { if (contribution instanceof ToolContribution) { ((ToolContribution) contribution).initializeToolClass(); @@ -243,11 +243,11 @@ public class ContributionManager { AdvertisedContribution ad, boolean confirmReplace, ErrorWidget statusBar) { - + File tempDir = ContributionManager.unzipFileToTemp(libFile, statusBar); - + ArrayList libfolders = ContributionManager.discover(ad.getType(), tempDir); - + if (libfolders.isEmpty()) { // Sometimes library authors place all their folders in the base // directory of a zip file instead of in single folder as the @@ -255,15 +255,15 @@ public class ContributionManager { // library by stepping up a directory and searching for libraries again. libfolders = ContributionManager.discover(ad.getType(), tempDir.getParentFile()); } - + if (libfolders != null && libfolders.size() == 1) { File libfolder = libfolders.get(0); File propFile = new File(libfolder, getPropertiesFileName(ad.getType())); - + if (writePropertiesFile(propFile, ad)) { InstalledContribution newcontrib = ContributionManager.create(editor .getBase(), ad.getType(), libfolder); - + return ContributionManager.installContribution(editor, newcontrib, confirmReplace, statusBar); @@ -285,10 +285,10 @@ public class ContributionManager { + "so we're ignoring it."); } } - + return null; } - + /** * @param confirmReplace * if true and the library is already installed, opens a prompt to @@ -297,20 +297,20 @@ public class ContributionManager { */ static public InstalledContribution installContribution(Editor editor, InstalledContribution newLib, boolean confirmReplace, ErrorWidget statusBar) { - + ArrayList oldLibs = getContributions(newLib.getType(), editor); - + String libFolderName = newLib.getFolder().getName(); - + File libraryDestination = ContributionManager .getSketchbookContribFolder(editor.getBase(), newLib.getType()); File newLibDest = new File(libraryDestination, libFolderName); - + for (InstalledContribution oldLib : oldLibs) { - + if ((oldLib.getFolder().exists() && oldLib.getFolder().equals(newLibDest)) || (oldLib.getId() != null && oldLib.getId().equals(newLib.getId()))) { - + if (ContributionManager.requiresRestart(oldLib)) { // XXX: We can't replace stuff, soooooo.... do something different if (!backupContribution(editor, oldLib, false, statusBar)) { @@ -350,11 +350,11 @@ public class ContributionManager { } } } - + if (newLibDest.exists()) { Base.removeDir(newLibDest); } - + // Move newLib to the sketchbook library folder if (newLib.getFolder().renameTo(newLibDest)) { InstalledContribution contrib = ContributionManager.create(editor @@ -365,7 +365,7 @@ public class ContributionManager { } catch (Exception e) { e.printStackTrace(); } - + // try { // FileUtils.copyDirectory(newLib.folder, libFolder); // FileUtils.deleteQuietly(newLib.folder); @@ -389,15 +389,15 @@ public class ContributionManager { } statusBar.setErrorMessage(errorMsg); } - + return null; } - + static public boolean writePropertiesFile(File propFile, AdvertisedContribution ad) { try { if (propFile.delete() && propFile.createNewFile() && propFile.setWritable(true)) { BufferedWriter bw = new BufferedWriter(new FileWriter(propFile)); - + bw.write("name=" + ad.getName() + "\n"); bw.write("category=" + ad.getCategory() + "\n"); bw.write("authorList=" + ad.getAuthorList() + "\n"); @@ -406,14 +406,14 @@ public class ContributionManager { bw.write("paragraph=" + ad.getParagraph() + "\n"); bw.write("version=" + ad.getVersion() + "\n"); bw.write("prettyVersion=" + ad.getPrettyVersion() + "\n"); - + bw.close(); } return true; } catch (FileNotFoundException e) { } catch (IOException e) { } - + return false; } @@ -427,9 +427,9 @@ public class ContributionManager { InstalledContribution contribution, boolean doDeleteOriginal, ErrorWidget statusBar) { - + File backupFolder = null; - + switch (contribution.getType()) { case LIBRARY: case LIBRARY_COMPILATION: @@ -441,19 +441,19 @@ public class ContributionManager { backupFolder = createToolBackupFolder(editor, statusBar); break; } - + if (backupFolder == null) return false; - + String libFolderName = contribution.getFolder().getName(); - + String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); final String backupName = prefix + "_" + libFolderName; File backupSubFolder = ContributionManager.getUniqueName(backupFolder, backupName); - + // try { // FileUtils.moveDirectory(lib.folder, backupFolderForLib); // return true; - + boolean success = false; if (doDeleteOriginal) { success = contribution.getFolder().renameTo(backupSubFolder); @@ -473,31 +473,29 @@ public class ContributionManager { static public File createLibraryBackupFolder(Editor editor, ErrorWidget logger) { - File libraryBackupFolder = new File(editor.getBase() - .getSketchbookLibrariesFolder(), "old"); + File libraryBackupFolder = new File(Base.getSketchbookLibrariesFolder(), "old"); return createBackupFolder(libraryBackupFolder, logger, "Could not create backup folder for library."); } static public File createToolBackupFolder(Editor editor, ErrorWidget logger) { - File libraryBackupFolder = new File(editor.getBase() - .getSketchbookToolsFolder(), "old"); + File libraryBackupFolder = new File(Base.getSketchbookToolsFolder(), "old"); return createBackupFolder(libraryBackupFolder, logger, "Could not create backup folder for tool."); } - + static private File createBackupFolder(File backupFolder, ErrorWidget logger, String errorMessage) { - + if (!backupFolder.exists() || !backupFolder.isDirectory()) { if (!backupFolder.mkdirs()) { logger.setErrorMessage(errorMessage); return null; } } - + return backupFolder; } @@ -505,7 +503,7 @@ public class ContributionManager { * Returns a file in the parent folder that does not exist yet. If * parent/fileName already exists, this will look for parent/fileName(2) * then parent/fileName(3) and so forth. - * + * * @return a file that does not exist yet */ public static File getUniqueName(File parentFolder, String fileName) { @@ -517,10 +515,10 @@ public class ContributionManager { folderName += "(" + i + ")"; } i++; - + backupFolderForLib = new File(parentFolder, folderName); } while (backupFolderForLib.exists()); - + return backupFolderForLib; } @@ -528,38 +526,38 @@ public class ContributionManager { ErrorWidget statusBar) { try { File tmpFolder = Base.createTempFolder("library", "download"); - + String[] segments = url.getFile().split("/"); File libFile = new File(tmpFolder, segments[segments.length - 1]); libFile.setWritable(true); - + return libFile; } catch (IOException e) { statusBar.setErrorMessage("Could not create a temp folder for download."); } - + return null; } /** * Creates a temporary folder and unzips a file to a subdirectory of the temp * folder. The subdirectory is the only file of the tempo folder. - * + * * e.g. if the contents of foo.zip are /hello and /world, then the resulting * files will be * /tmp/foo9432423uncompressed/foo/hello * /tmp/foo9432423uncompress/foo/world * ...and "/tmp/id9432423uncompress/foo/" will be returned. - * + * * @return the folder where the zips contents have been unzipped to (the * subdirectory of the temp folder). */ static public File unzipFileToTemp(File libFile, ErrorWidget statusBar) { - + String fileName = ContributionManager.getFileName(libFile); File tmpFolder = null; - + try { tmpFolder = Base.createTempFolder(fileName, "uncompressed"); tmpFolder = new File(tmpFolder, fileName); @@ -567,15 +565,15 @@ public class ContributionManager { } catch (IOException e) { statusBar.setErrorMessage("Could not create temp folder to uncompressed zip file."); } - + ContributionManager.unzip(libFile, tmpFolder); - + return tmpFolder; } /** * Returns the name of a file without its path or extension. - * + * * For example, * "/path/to/helpfullib.zip" returns "helpfullib" * "helpfullib-0.1.1.plb" returns "helpfullib-0.1.1" @@ -583,19 +581,19 @@ public class ContributionManager { static public String getFileName(File libFile) { String path = libFile.getPath(); int lastSeparator = path.lastIndexOf(File.separatorChar); - + String fileName; if (lastSeparator != -1) { fileName = path.substring(lastSeparator + 1); } else { fileName = path; } - + int lastDot = fileName.lastIndexOf('.'); if (lastDot != -1) { return fileName.substring(0, lastDot); } - + return fileName; } @@ -628,13 +626,13 @@ public class ContributionManager { } out.close(); } - + /** Returns true if the type of contribution requires the PDE to restart * when being removed. */ static public boolean requiresRestart(Contribution contrib) { return contrib.getType() == Type.TOOL || contrib.getType() == Type.MODE; } - + static public boolean flagForDeletion(InstalledContribution contrib) { // Only returns false if the file already exists, so we can // ignore the return value. @@ -649,7 +647,7 @@ public class ContributionManager { static public boolean removeFlagForDeletion(InstalledContribution contrib) { return new File(contrib.getFolder(), ContributionManager.DELETION_FLAG).delete(); } - + static public boolean isFlaggedForDeletion(Contribution contrib) { if (contrib instanceof InstalledContribution) { InstalledContribution installed = (InstalledContribution) contrib; @@ -657,5 +655,5 @@ public class ContributionManager { } return false; } - + } diff --git a/app/src/processing/app/contrib/ModeContribution.java b/app/src/processing/app/contrib/ModeContribution.java index 26a13a2de..c98ef07cf 100644 --- a/app/src/processing/app/contrib/ModeContribution.java +++ b/app/src/processing/app/contrib/ModeContribution.java @@ -37,15 +37,15 @@ import processing.app.Mode; public class ModeContribution extends InstalledContribution { private URLClassLoader loader; - + private String className; Base base; - + Mode mode; - + static String propertiesFileName = "mode.properties"; - + static public Mode getCoreMode(Base base, String classname, File folder) { try { Class c = Class.forName(classname); @@ -57,22 +57,22 @@ public class ModeContribution extends InstalledContribution { } return null; } - + static public ModeContribution getContributedMode(Base base, File folder) { ModeContribution mode = new ModeContribution(base, folder); if (mode.isValid()) return mode; - + return null; } - + private ModeContribution(Base base, File folder) { super(folder, ModeContribution.propertiesFileName); - + this.base = base; - + File modeDirectory = new File(folder, "mode"); - + // add .jar and .zip files to classpath File[] archives = modeDirectory.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { @@ -80,17 +80,17 @@ public class ModeContribution extends InstalledContribution { name.toLowerCase().endsWith(".zip")); } }); - + if (archives == null || archives.length == 0) return; - + try { URL[] urlList = new URL[archives.length]; for (int j = 0; j < urlList.length; j++) { urlList[j] = archives[j].toURI().toURL(); } loader = new URLClassLoader(urlList); - + for (int j = 0; j < archives.length; j++) { className = ToolContribution.findClassInZipFile( folder.getName(), archives[j] ); @@ -100,13 +100,13 @@ public class ModeContribution extends InstalledContribution { // Maybe log this } } - + private boolean isValid() { return className != null; } - + /** - * Creates and instance of the Mode object. Warning: this makes it impossible + * Creates an instance of the Mode object. Warning: this makes it impossible * (on Windows) to move the files in the mode's classpath without restarting * the PDE. */ @@ -115,14 +115,15 @@ public class ModeContribution extends InstalledContribution { Class modeClass = Class.forName(className, true, loader); Constructor contr = modeClass.getConstructor(Base.class, File.class); mode = (Mode) contr.newInstance(base, folder); + mode.setupGUI(); return true; } catch (Exception e) { e.printStackTrace(); } - + return false; } - + public Mode getMode() { return mode; } @@ -130,7 +131,7 @@ public class ModeContribution extends InstalledContribution { public Type getType() { return Type.MODE; } - + public boolean equals(Object o) { if (o == null || o instanceof ModeContribution) return false; @@ -138,11 +139,11 @@ public class ModeContribution extends InstalledContribution { ModeContribution other = (ModeContribution) o; return loader.equals(other.loader) && className.equals(other.className); } - + static public ArrayList list(Base base, File folder) { ArrayList modes = new ArrayList(); ArrayList modeFolders = discover(folder); - + for (File potentialModeFolder : modeFolders) { ModeContribution contrib = getContributedMode(base, potentialModeFolder); if (contrib != null) { @@ -151,15 +152,15 @@ public class ModeContribution extends InstalledContribution { } return modes; } - + static protected ArrayList discover(File folder) { ArrayList modeFolders = new ArrayList(); discover(folder, modeFolders); return modeFolders; } - + static protected void discover(File folder, ArrayList modeFolders) { - + File[] folders = folder.listFiles(new FileFilter() { public boolean accept(File potentialModeFolder) { if (!potentialModeFolder.isDirectory()) return false; @@ -170,7 +171,7 @@ public class ModeContribution extends InstalledContribution { if (folders == null || folders.length == 0) { return; } - + for (File potentialModeFolder : folders) { modeFolders.add(potentialModeFolder); } diff --git a/app/src/processing/mode/java/Commander.java b/app/src/processing/mode/java/Commander.java index 8133131a8..5bc459c26 100644 --- a/app/src/processing/mode/java/Commander.java +++ b/app/src/processing/mode/java/Commander.java @@ -3,7 +3,7 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2008-10 Ben Fry and Casey Reas + Copyright (c) 2008-12 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,20 +22,18 @@ package processing.mode.java; - -/* import java.io.File; import java.io.IOException; import java.io.PrintStream; import processing.app.Base; +import processing.app.Library; import processing.app.Preferences; import processing.app.SketchException; import processing.app.RunnerListener; import processing.app.Sketch; import processing.core.PApplet; import processing.mode.java.runner.*; -*/ /** @@ -52,16 +50,15 @@ import processing.mode.java.runner.*; * --run Preprocess, compile, and run a sketch. * --present Preprocess, compile, and run a sketch full screen. * - * --export-applet Export an applet. - * --export-application Export an application. + * --export Export an application. * --platform Specify the platform (export to application only). * Should be one of 'windows', 'macosx', or 'linux'. * --bits Must be specified if libraries are used that are * 32- or 64-bit specific such as the OpenGL library. * Otherwise specify 0 or leave it out. - * - * --preferences=<file> Specify a preferences file to use. Required if the - * sketch uses libraries found in your sketchbook folder. +// * +// * --preferences=<file> Specify a preferences file to use. Required if the +// * sketch uses libraries found in your sketchbook folder. * * * To build the command line version, first build for your platform, @@ -70,7 +67,6 @@ import processing.mode.java.runner.*; * * @author fry */ -/* public class Commander implements RunnerListener { static final String helpArg = "--help"; static final String preprocArg = "--preprocess"; @@ -78,8 +74,9 @@ public class Commander implements RunnerListener { static final String runArg = "--run"; static final String presentArg = "--present"; static final String sketchArg = "--sketch="; + static final String forceArg = "--force"; static final String outputArg = "--output="; - static final String exportAppletArg = "--export-applet"; +// static final String exportAppletArg = "--export-applet"; static final String exportApplicationArg = "--export-application"; static final String platformArg = "--platform="; static final String bitsArg = "--bits="; @@ -90,34 +87,46 @@ public class Commander implements RunnerListener { static final int BUILD = 1; static final int RUN = 2; static final int PRESENT = 3; - static final int EXPORT_APPLET = 4; +// static final int EXPORT_APPLET = 4; static final int EXPORT_APPLICATION = 5; Sketch sketch; static public void main(String[] args) { + if (args == null || args.length == 0) { +// System.out.println(System.getProperty("user.dir")); + args = new String[] { + "--export-application", + "--platform=windows", + "--bits=64", + "--sketch=/Users/fry/coconut/processing/java/examples/Basics/Lights/Directional", + "--output=/Users/fry/Desktop/test-build" + }; + } + // Do this early so that error messages go to the console Base.setCommandLine(); // init the platform so that prefs and other native code is ready to go Base.initPlatform(); // make sure a full JDK is installed Base.initRequirements(); - // run static initialization that grabs all the prefs - //Preferences.init(null); // launch command line handler new Commander(args); } public Commander(String[] args) { - String sketchFolder = null; + String sketchPath = null; + File sketchFolder = null; String pdePath = null; // path to the .pde file String outputPath = null; - String preferencesPath = null; - int platformIndex = PApplet.platform; // default to this platform + File outputFolder = null; + boolean force = false; // replace that no good output folder +// String preferencesPath = null; + int platform = PApplet.platform; // default to this platform int platformBits = 0; - int mode = HELP; + int task = HELP; for (String arg : args) { if (arg.length() == 0) { @@ -126,75 +135,103 @@ public class Commander implements RunnerListener { } else if (arg.equals(helpArg)) { // mode already set to HELP + } else if (arg.equals(preprocArg)) { + task = PREPROCESS; + } else if (arg.equals(buildArg)) { - mode = BUILD; + task = BUILD; } else if (arg.equals(runArg)) { - mode = RUN; + task = RUN; } else if (arg.equals(presentArg)) { - mode = PRESENT; + task = PRESENT; - } else if (arg.equals(preprocArg)) { - mode = PREPROCESS; - - } else if (arg.equals(exportAppletArg)) { - mode = EXPORT_APPLET; +// } else if (arg.equals(exportAppletArg)) { +// task = EXPORT_APPLET; } else if (arg.equals(exportApplicationArg)) { - mode = EXPORT_APPLICATION; + task = EXPORT_APPLICATION; } else if (arg.startsWith(platformArg)) { String platformStr = arg.substring(platformArg.length()); - platformIndex = Base.getPlatformIndex(platformStr); - if (platformIndex == -1) { + platform = Base.getPlatformIndex(platformStr); + if (platform == -1) { complainAndQuit(platformStr + " should instead be " + "'windows', 'macosx', or 'linux'."); } + + } else if (arg.startsWith(bitsArg)) { + String bitsStr = arg.substring(bitsArg.length()); + if (bitsStr.equals("32")) { + platformBits = 32; + } else if (bitsStr.equals("64")) { + platformBits = 64; + } else { + complainAndQuit("Bits should be either 32 or 64, not " + bitsStr); + } + } else if (arg.startsWith(sketchArg)) { - sketchFolder = arg.substring(sketchArg.length()); - File sketchy = new File(sketchFolder); - File pdeFile = new File(sketchy, sketchy.getName() + ".pde"); + sketchPath = arg.substring(sketchArg.length()); + sketchFolder = new File(sketchPath); + if (!sketchFolder.exists()) { + complainAndQuit(sketchFolder + " does not exist."); + } + File pdeFile = new File(sketchFolder, sketchFolder.getName() + ".pde"); + if (!pdeFile.exists()) { + complainAndQuit("Not a valid sketch folder. " + pdeFile + " does not exist."); + } pdePath = pdeFile.getAbsolutePath(); - } else if (arg.startsWith(preferencesArg)) { - preferencesPath = arg.substring(preferencesArg.length()); +// } else if (arg.startsWith(preferencesArg)) { +// preferencesPath = arg.substring(preferencesArg.length()); } else if (arg.startsWith(outputArg)) { outputPath = arg.substring(outputArg.length()); + } else if (arg.equals(forceArg)) { + force = true; + } else { complainAndQuit("I don't know anything about " + arg + "."); } } - if ((outputPath == null) && - (mode == PREPROCESS || mode == BUILD || - mode == RUN || mode == PRESENT)) { - complainAndQuit("An output path must be specified when using " + - preprocArg + ", " + buildArg + ", " + - runArg + ", or " + presentArg + "."); - } - - if (mode == HELP) { +// if ((outputPath == null) && +// (task == PREPROCESS || task == BUILD || +// task == RUN || task == PRESENT)) { +// complainAndQuit("An output path must be specified when using " + +// preprocArg + ", " + buildArg + ", " + +// runArg + ", or " + presentArg + "."); +// } + if (task == HELP) { printCommandLine(System.out); System.exit(0); } - // --present --platform=windows "--sketch=/Applications/Processing 0148/examples/Basics/Arrays/Array" --output=test-build - - File outputFolder = new File(outputPath); - if (!outputFolder.exists()) { - if (!outputFolder.mkdirs()) { - complainAndQuit("Could not create the output folder."); - } + if (outputPath == null) { + complainAndQuit("An output path must be specified."); } - // run static initialization that grabs all the prefs - // (also pass in a prefs path if that was specified) - Preferences.init(preferencesPath); + outputFolder = new File(outputPath); + if (outputFolder.exists() && !force) { + complainAndQuit("The output folder already exists. Use --force to overwrite it."); + } - if (sketchFolder == null) { + if (!outputFolder.mkdirs()) { + complainAndQuit("Could not create the output folder."); + } + +// // run static initialization that grabs all the prefs +// // (also pass in a prefs path if that was specified) +// if (preferencesPath != null) { +// Preferences.init(preferencesPath); +// } + + Preferences.init(null); + Base.locateSketchbookFolder(); + + if (sketchPath == null) { complainAndQuit("No sketch path specified."); } else if (outputPath.equals(pdePath)) { @@ -207,42 +244,57 @@ public class Commander implements RunnerListener { //Sketch sketch = null; boolean success = false; + JavaMode javaMode = + new JavaMode(null, Base.getContentFile("modes/java")); try { - sketch = new Sketch(null, pdePath); - if (mode == PREPROCESS) { + sketch = new Sketch(pdePath, javaMode); + /* + if (task == PREPROCESS) { + JavaBuild build = new JavaBuild(sketch); + build.preprocess(new File(sketchFolder), true); success = sketch.preprocess(new File(outputPath)) != null; - } else if (mode == BUILD) { - success = sketch.build(outputPath) != null; + } else*/ if (task == BUILD) { + JavaBuild build = new JavaBuild(sketch); + String mainClassName = + build.build(new File(sketchPath), outputFolder, true); + success = mainClassName != null; - } else if (mode == RUN || mode == PRESENT) { - String className = sketch.build(outputPath); + } else if (task == RUN || task == PRESENT) { + JavaBuild build = new JavaBuild(sketch); + String className = build.build(sketchFolder, outputFolder, true); if (className != null) { success = true; - Runner runner = new Runner(this, sketch); - runner.launch(className, mode == PRESENT); + Runner runner = new Runner(build, this); + runner.launch(task == PRESENT); } else { success = false; } - } else if (mode == EXPORT_APPLET) { - if (outputPath != null) { - success = sketch.exportApplet(outputPath); +// } else if (task == EXPORT_APPLET) { +// if (outputPath != null) { +// success = sketch.exportApplet(outputPath); +// } else { +// String target = sketchFolder + File.separatorChar + "applet"; +// success = sketch.exportApplet(target); +// } + } else if (task == EXPORT_APPLICATION) { + if (outputPath == null) { + javaMode.handleExportApplication(sketch); } else { - String target = sketchFolder + File.separatorChar + "applet"; - success = sketch.exportApplet(target); - } - } else if (mode == EXPORT_APPLICATION) { - if (outputPath != null) { - success = sketch.exportApplication(outputPath, platformIndex, platformBits); - } else { - //String sketchFolder = - // pdePath.substring(0, pdePath.lastIndexOf(File.separatorChar)); - outputPath = - sketchFolder + File.separatorChar + - "application." + Base.getPlatformName(platformIndex); - success = sketch.exportApplication(outputPath, platformIndex, platformBits); + JavaBuild build = new JavaBuild(sketch); + build.build(true); + if (build != null) { +// if (platformBits == 0) { +// platformBits = Base.getNativeBits(); +// } + if (platformBits == 0 && + Library.hasMultipleArch(platform, build.getImportedLibraries())) { + complainAndQuit("This sketch can be exported for 32- or 64-bit, please specify one."); + } + success = build.exportApplication(outputFolder, platform, platformBits); + } } } System.exit(success ? 0 : 1); @@ -257,10 +309,12 @@ public class Commander implements RunnerListener { } } + public void statusNotice(String message) { System.err.println(message); } + public void statusError(String message) { System.err.println(message); } @@ -294,29 +348,51 @@ public class Commander implements RunnerListener { static void printCommandLine(PrintStream out) { - out.println("Processing " + Base.VERSION_NAME + " rocks the console."); + out.println("Standard (Java) mode command line edition for Processing " + Base.VERSION_NAME); out.println(); - out.println("--help Show this help text."); + out.println("--help Show this help text. Congratulations."); out.println(); out.println("--sketch= Specify the sketch folder (required)"); out.println("--output= Specify the output folder (required and"); out.println(" cannot be the same as the sketch folder.)"); + out.println("--force The sketch will not build if the output"); + out.println(" folder already exists, because the contents"); + out.println(" will be replaced. This option overrides."); out.println(); out.println("--preprocess Preprocess a sketch into .java files."); out.println("--build Preprocess and compile a sketch into .class files."); out.println("--run Preprocess, compile, and run a sketch."); out.println("--present Preprocess, compile, and run a sketch full screen."); out.println(); - out.println("--export-applet Export an applet."); - out.println("--export-application Export an application."); + out.println("--export Export an application."); out.println("--platform Specify the platform (export to application only)."); out.println(" Should be one of 'windows', 'macosx', or 'linux'."); out.println("--bits Must be specified if libraries are used that are"); out.println(" 32- or 64-bit specific such as the OpenGL library."); - out.println(" Otherwise specify 0 or leave it out."); - out.println(); - out.println("--preferences= Specify a preferences file to use. Required if the"); - out.println(" sketch uses libraries found in your sketchbook folder."); + out.println(" Otherwise specify 0 or leave it out."); +// out.println(); +// out.println("--preferences= Specify a preferences file to use. Required if the"); +// out.println(" sketch uses libraries found in your sketchbook folder."); } -} -*/ \ No newline at end of file + + + @Override + public void startIndeterminate() { + } + + + @Override + public void stopIndeterminate() { + } + + + @Override + public void statusHalt() { + } + + + @Override + public boolean isHalted() { + return false; + } +} \ No newline at end of file diff --git a/app/src/processing/mode/java/JavaBuild.java b/app/src/processing/mode/java/JavaBuild.java index 2be00a44f..2e47f5f54 100644 --- a/app/src/processing/mode/java/JavaBuild.java +++ b/app/src/processing/mode/java/JavaBuild.java @@ -1115,23 +1115,23 @@ public class JavaBuild { /** - * Export to application without GUI. + * Export to application without GUI. Also called by the Commander. */ - private boolean exportApplication(File destFolder, - int exportPlatform, - int exportBits) throws IOException, SketchException { + protected boolean exportApplication(File destFolder, + int exportPlatform, + int exportBits) throws IOException, SketchException { // TODO this should probably be a dialog box instead of a warning // on the terminal. And the message should be written better than this. // http://code.google.com/p/processing/issues/detail?id=884 for (Library library : importedLibraries) { if (!library.supportsArch(exportPlatform, exportBits)) { String pn = PConstants.platformNames[exportPlatform]; - System.err.println("The application." + pn + exportBits + - " folder will not be created because no " + - exportBits + "-bit version of " + - library.getName() + - " is available for " + pn); - return true; // don't cancel export for this, just move along + Base.showWarning("Quibbles 'n Bits", + "The application." + pn + exportBits + + " folder will not be created\n" + + "because no " + exportBits + "-bit version of " + + library.getName() + " is available for " + pn, null); + return true; // don't cancel all exports for this, just move along } } diff --git a/app/src/processing/mode/java/JavaMode.java b/app/src/processing/mode/java/JavaMode.java index 2f27ebf85..80beaf738 100644 --- a/app/src/processing/mode/java/JavaMode.java +++ b/app/src/processing/mode/java/JavaMode.java @@ -60,32 +60,6 @@ public class JavaMode extends Mode { Base.showError("Problem loading keywords", "Could not load keywords.txt, please re-install Processing.", e); } - - /* - item = newJMenuItem("Export", 'E'); - if (editor != null) { - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.handleExport(); - } - }); - } else { - item.setEnabled(false); - } - fileMenu.add(item); - - item = newJMenuItemShift("Export Application", 'E'); - if (editor != null) { - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.handleExportApplication(); - } - }); - } else { - item.setEnabled(false); - } - fileMenu.add(item); - */ } diff --git a/todo.txt b/todo.txt index 5ef60d2b8..ded7c98fc 100644 --- a/todo.txt +++ b/todo.txt @@ -28,6 +28,9 @@ X add 64-bit Linux version to the next download X revisions.txt should have Windows line endings X change in SVN to be platform specific X didn't actually do it +o examples button on toolbar? open / recent / sketchbook? +X switch to using a warning dialog when bits aren't available +X http://code.google.com/p/processing/issues/detail?id=884 o don't use tmp folder for sketches? _ or restrict more things like "show sketch folder" @@ -55,33 +58,6 @@ o don't re-open new window on top of another X changing how this is handled X detect mode and library example folders for recent menu -_ consider window menu -_ http://code.google.com/p/processing/issues/detail?id=545 -_ multiple sketch windows.. having a windows menu? -_ examples button on toolbar? open / recent / sketchbook? - -restoring sketches -_ save window positions on quit, and restore them (w/ a preference?) -_ new windows use same mode and dimensions as topmost window -_ saved window position problematic with multiple monitors -_ http://code.google.com/p/processing/issues/detail?id=27 -_ Closing the last window doesn't cause PDE to save it's position/contents/etc -_ http://code.google.com/p/processing/issues/detail?id=103 -_ not remembering window size/placement preferences -_ http://dev.processing.org/bugs/show_bug.cgi?id=837 -_ Blank sketch opened even if opening an existing sketch by double-clicking -_ http://code.google.com/p/processing/issues/detail?id=179 -_ changing number of screens between run causes things to show up off-screen -_ so when running, check to make sure that things are out of the area -_ saved window positions.. if displays has changed, becomes a problem -_ record the display that it was on? -_ GraphicsDevice gd = frame.getGraphicsConfiguration().getDevice(); -_ make sure that the application is within the bounds of the current display? -_ (from 0, 0 to width, height) -_ messy since some displays have negative coords -_ http://code.google.com/p/processing/issues/detail?id=27 -Base.restoreSketches() has commented out code that checked for out of bounds windows with the preferences last.window.x and last.window.y. These prefs don't exist anymore, but it would be quick to implement it again using last.sketch.location instead. It would probably result in less code, because it would mean we could get rid of the windowPositionValid stuff. - http://code.google.com/p/processing/issues/list?can=2&q=owner%3Afry%40processing.org+Type%3ADefect&colspec=Stars+ID+Type+Status+Priority+Owner+Summary&cells=tiles with casey @@ -1561,17 +1537,8 @@ _ some reports of it not quitting properly, but not confirmed _ splash screen -WISH LIST +NOT FOR 2.0 -_ rename location is awkward, do it on the tab? - -_ Replace current editor with more advanced version -_ http://code.google.com/p/processing/issues/detail?id=1032 -_ Resurrect the Eclipse plug-in project -_ http://code.google.com/p/processing/issues/detail?id=1031 - - -3.0 _ better text editor / live debugging (integrate Eclipse JDT) _ line numbers _ it's too difficult for students to debug their code @@ -1585,3 +1552,30 @@ _ con: people love it, most of the books use it heavily _ add === for String.equals() _ might be problematic since it might be opposite the javascript meaning _ jer: it's a decent time to start talking abt references/vars +_ window menu +_ http://code.google.com/p/processing/issues/detail?id=545 +_ restoring sketches +_ save window positions on quit, and restore them (w/ a preference?) +_ new windows use same mode and dimensions as topmost window +_ saved window position problematic with multiple monitors +_ http://code.google.com/p/processing/issues/detail?id=27 +_ Closing the last window doesn't cause PDE to save it's position/contents/etc +_ http://code.google.com/p/processing/issues/detail?id=103 +_ not remembering window size/placement preferences +_ http://dev.processing.org/bugs/show_bug.cgi?id=837 +_ Blank sketch opened even if opening an existing sketch by double-clicking +_ http://code.google.com/p/processing/issues/detail?id=179 +_ changing number of screens between run causes things to show up off-screen +_ so when running, check to make sure that things are out of the area +_ saved window positions.. if displays has changed, becomes a problem +_ record the display that it was on? +_ GraphicsDevice gd = frame.getGraphicsConfiguration().getDevice(); +_ make sure the application is within the bounds of the current display? +_ (from 0, 0 to width, height) +_ messy since some displays have negative coords +_ http://code.google.com/p/processing/issues/detail?id=27 +_ rename location is awkward, do it on the tab? +_ Replace current editor with more advanced version +_ http://code.google.com/p/processing/issues/detail?id=1032 +_ Resurrect the Eclipse plug-in project +_ http://code.google.com/p/processing/issues/detail?id=1031