From ceae54308983bb5b50300c51cbace24ccd78d240 Mon Sep 17 00:00:00 2001 From: benfry Date: Mon, 19 Jan 2004 19:14:11 +0000 Subject: [PATCH] more working on changes to the build/run system --- processing/app/PdeCompiler.java | 30 +-- processing/app/PdeEditor.java | 77 +++----- processing/app/PdeRuntime.java | 4 +- processing/app/PdeSketch.java | 336 +++++++++++++++++++++----------- 4 files changed, 263 insertions(+), 184 deletions(-) diff --git a/processing/app/PdeCompiler.java b/processing/app/PdeCompiler.java index 6e97efe50..cb0b91a9b 100644 --- a/processing/app/PdeCompiler.java +++ b/processing/app/PdeCompiler.java @@ -29,17 +29,18 @@ import javax.swing.*; public class PdeCompiler implements PdeMessageConsumer { static final String BUGS_URL = - "http://Proce55ing.net/bugs/"; + "http://processing.org/bugs/"; static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL; - String buildPath; - String className; - File includeFolder; + //String buildPath; + //String className; + //File includeFolder; PdeException exception; - PdeEditor editor; + //PdeEditor editor; + /* public PdeCompiler(String buildPath, String className, File includeFolder, PdeEditor editor) { this.buildPath = buildPath; @@ -50,24 +51,27 @@ public class PdeCompiler implements PdeMessageConsumer { public boolean compile(PrintStream leechErr) { + */ + + public PdeCompiler() { } + + + public boolean compile(PdeSketch sketch) { String userdir = System.getProperty("user.dir") + File.separator; //System.out.println(userdir + "jikes"); //System.out.println(System.getProperty("sun.boot.class.path")); - String command[] = new String[] { -#ifdef MACOS + String command[] = new String[] { // linux doesn't seem to like this // though windows probably doesn't care - userdir + "jikes", -#else - "jikes", -#endif + ((PdeBase.platform == PdeBase.MACOSX) ? userdir + "jikes" : "jikes"), // necessary to make output classes compatible with 1.1 // i.e. so that exported applets can work with ms jvm on the web "-target", - "1.1", + PdePreferences.get("compiler.jdk_version"), //"1.1", + // let the incompatability headache begin // used when run without a vm ("expert" mode) "-bootclasspath", @@ -93,7 +97,7 @@ public class PdeCompiler implements PdeMessageConsumer { firstErrorFound = false; // haven't found any errors yet secondErrorFound = false; - int result=0; // pre-initialized to quiet a bogus warning from jikes + int result = 0; // pre-initialized to quiet a bogus warning from jikes try { // execute the compiler, and create threads to deal with the input diff --git a/processing/app/PdeEditor.java b/processing/app/PdeEditor.java index d96d46aba..9357dab64 100644 --- a/processing/app/PdeEditor.java +++ b/processing/app/PdeEditor.java @@ -1030,7 +1030,7 @@ public class PdeEditor extends JFrame throw new PdeException(re.getMessage(), re.getLine() - 1, re.getColumn()); - } catch (antlr.TokenStreamRecognitionException tsre) { + } catch (antlr.okenStreamRecognitionException tsre) { // while this seems to store line and column internally, // there doesn't seem to be a method to grab it.. // so instead it's done using a regexp @@ -1118,18 +1118,27 @@ public class PdeEditor extends JFrame //System.out.println("RUNNING"); buttons.run(); + // spew some blank lines so it's clear what's new on the console for (int i = 0; i < 10; i++) System.out.println(); presenting = present; - try { - if (presenting) { - // wipe everything out with a bulbous screen-covering window - presentationWindow.show(); - presentationWindow.toFront(); - } + if (presenting) { + // wipe everything out with a bulbous screen-covering window + presentationWindow.show(); + presentationWindow.toFront(); + } + try { sketch.run(); + } catch (PdeException e) { + error(e); + + } catch (Exception e) { + e.printStackTrace(); + } + } + /* String program = textarea.getText(); history.record(program, PdeHistory.RUN); @@ -1242,48 +1251,6 @@ public class PdeEditor extends JFrame //System.out.println("out of doRun()"); // required so that key events go to the panel and works //graphics.requestFocus(); // removed for pde - } - - - class RunButtonWatcher implements Runnable { - Thread thread; - - public RunButtonWatcher() { - thread = new Thread(this); - thread.start(); - } - - public void run() { - while (Thread.currentThread() == thread) { - if (runtime == null) { - stop(); - - } else { - if (runtime.applet != null) { - if (runtime.applet.finished) { - stop(); - } - //buttons.running(!runtime.applet.finished); - - } else if (runtime.process != null) { - //buttons.running(true); // ?? - - } else { - stop(); - } - } - try { - Thread.sleep(250); - } catch (InterruptedException e) { } - //System.out.println("still inside runner thread"); - } - } - - public void stop() { - buttons.running(false); - thread = null; - } - } public void handleStop() { // called by menu or buttons @@ -1295,6 +1262,9 @@ public class PdeEditor extends JFrame } + /** + * Stop the applet but don't kill its window. + */ public void doStop() { if (runtime != null) runtime.stop(); if (watcher != null) watcher.stop(); @@ -1311,9 +1281,10 @@ public class PdeEditor extends JFrame } - // this is the former 'kill' function - // may just roll this in with the other code - // -> keep this around for closing the external window + /** + * Stop the applet and kill its window. When running in presentation + * mode, this will always be called instead of doStop(). + */ public void doClose() { //System.out.println("doclose1"); if (presenting) { @@ -1666,7 +1637,7 @@ public class PdeEditor extends JFrame try { //System.out.println("handleSave: results of getText"); //System.out.print(s); - + BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(s.getBytes()))); PrintWriter writer = diff --git a/processing/app/PdeRuntime.java b/processing/app/PdeRuntime.java index b5f35fa36..6f40e6bbb 100644 --- a/processing/app/PdeRuntime.java +++ b/processing/app/PdeRuntime.java @@ -73,7 +73,7 @@ public class PdeRuntime implements PdeMessageConsumer { public void start(Point windowLocation, PrintStream leechErr) throws PdeException { - this.leechErr = leechErr; + this.leechErr = new PrintStream(new PdeMessageStream(this)); Point parentLoc = editor.getLocation(); Insets parentInsets = editor.getInsets(); @@ -85,7 +85,7 @@ public class PdeRuntime implements PdeMessageConsumer { if (externalRuntime) { String command[] = new String[] { "java", - "-Djava.library.path=" + libraryPath, + "-Djava.library.path=" + libraryPath, // might be "" "-cp", classPath, "BApplet", diff --git a/processing/app/PdeSketch.java b/processing/app/PdeSketch.java index 048b96980..b3180d8b8 100644 --- a/processing/app/PdeSketch.java +++ b/processing/app/PdeSketch.java @@ -31,7 +31,7 @@ public class PdeSketch { String path; // path to 'main' file for this sketch // the sketch folder - File directory; + File folder; static final int PDE = 0; static final int JAVA = 1; @@ -43,6 +43,9 @@ public class PdeSketch { int hiddenCount; PdeCode hidden[]; + // all these set each time build() is called + boolean externalRuntime; + String mainClassName; String classPath; String libraryPath; @@ -66,8 +69,8 @@ public class PdeSketch { } */ - directory = new File(path.getParent()); - System.out.println("sketch dir is " + directory); + folder = new File(path.getParent()); + System.out.println("sketch dir is " + folder); load(); } @@ -86,7 +89,7 @@ public class PdeSketch { */ public void load() { // get list of files in the sketch folder - String list[] = directory.list(); + String list[] = folder.list(); for (int i = 0; i < list.length; i++) { if (list[i].endsWith(".pde")) fileCount++; @@ -105,25 +108,25 @@ public class PdeSketch { if (list[i].endsWith(".pde")) { code[fileCounter++] = new PdeCode(list[i].substring(0, list[i].length() - 4), - new File(directory, list[i]), + new File(folder, list[i]), PDE); } else if (list[i].endsWith(".java")) { code[fileCounter++] = new PdeCode(list[i].substring(0, list[i].length() - 5), - new File(directory, list[i]), + new File(folder, list[i]), JAVA); } else if (list[i].endsWith(".pde.x")) { hidden[hiddenCounter++] = new PdeCode(list[i].substring(0, list[i].length() - 6), - new File(directory, list[i]), + new File(folder, list[i]), PDE); } else if (list[i].endsWith(".java.x")) { hidden[hiddenCounter++] = new PdeCode(list[i].substring(0, list[i].length() - 7), - new File(directory, list[i]), + new File(folder, list[i]), JAVA); } } @@ -174,6 +177,53 @@ public class PdeSketch { } + /** + * Prompt the user for a new file to the sketch. + * This could be .class or .jar files for the code folder, + * .pde or .java files for the project, + * or .dll, .jnilib, or .so files for the code folder + */ + public void addFile() { + // get a dialog, select a file to add to the sketch + String prompt = + "Select an image or other data file to copy to your sketch"; + FileDialog fd = new FileDialog(new Frame(), prompt, FileDialog.LOAD); + fd.show(); + + String directory = fd.getDirectory(); + String filename = fd.getFile(); + if (filename == null) return; + + // copy the file into the folder. if people would rather + // it move instead of copy, they can do it by hand + File sourceFile = new File(directory, filename); + + File destFile = null; + + // if the file appears to be code related, drop it + // into the code folder, instead of the data folder + if (filename.toLowerCase().endsWith(".class") || + filename.toLowerCase().endsWith(".jar") || + filename.toLowerCase().endsWith(".dll") || + filename.toLowerCase().endsWith(".jnilib") || + filename.toLowerCase().endsWith(".so")) { + File codeFolder = new File(this.folder, "code"); + if (!codeFolder.exists()) codeFolder.mkdirs(); + destFile = new File(codeFolder, filename); + + } else if (filename.toLowerCase().endsWith(".pde") || + filename.toLowerCase().endsWith(".java")) { + destFile = new File(this.folder, filename); + + } else { + File dataFolder = new File(this.folder, "data"); + if (!dataFolder.exists()) dataFolder.mkdirs(); + destFile = new File(dataFolder, filename); + } + PdeBase.copyFile(sourceFile, destFile); + } + + /** * Change what file is currently being edited. * 1. store the String for the text of the current file. @@ -207,109 +257,107 @@ public class PdeSketch { * or if more than one file is in the project * */ - public void run() { - try { - current.program = textarea.getText(); + public void run() throws PdeException { + current.program = textarea.getText(); - // TODO record history here - //current.history.record(program, PdeHistory.RUN); + // TODO record history here + //current.history.record(program, PdeHistory.RUN); - // if an external editor is being used, need to grab the - // latest version of the code from the file. - if (PdePreferences.getBoolean("editor.external")) { - // history gets screwed by the open.. - //String historySaved = history.lastRecorded; - //handleOpen(sketch); - //history.lastRecorded = historySaved; + // if an external editor is being used, need to grab the + // latest version of the code from the file. + if (PdePreferences.getBoolean("editor.external")) { + // history gets screwed by the open.. + //String historySaved = history.lastRecorded; + //handleOpen(sketch); + //history.lastRecorded = historySaved; - // nuke previous files and settings, just get things loaded - load(); - } + // nuke previous files and settings, just get things loaded + load(); + } - // temporary build folder is inside 'lib' - // this is added to the classpath by default - tempBuildPath = "lib" + File.separator + "build"; - File buildDir = new File(tempBuildPath); - if (!buildDir.exists()) { - buildDir.mkdirs(); - } + // temporary build folder is inside 'lib' + // this is added to the classpath by default + tempBuildPath = "lib" + File.separator + "build"; + File buildDir = new File(tempBuildPath); + if (!buildDir.exists()) { + buildDir.mkdirs(); + } - // copy contents of data dir into lib/build - // TODO write a file sync procedure here.. if the files - // already exist in the target, or haven't been modified - // don't' bother. this can waste a lot of time when running. - File dataDir = new File(directory, "data"); - if (dataDir.exists()) { - // just drop the files in the build folder (pre-68) - //PdeBase.copyDir(dataDir, buildDir); - // drop the files into a 'data' subfolder of the build dir - PdeBase.copyDir(dataDir, new File(buildDir, "data")); - } + // copy contents of data dir into lib/build + // TODO write a file sync procedure here.. if the files + // already exist in the target, or haven't been modified + // don't' bother. this can waste a lot of time when running. + File dataDir = new File(folder, "data"); + if (dataDir.exists()) { + // just drop the files in the build folder (pre-68) + //PdeBase.copyDir(dataDir, buildDir); + // drop the files into a 'data' subfolder of the build dir + PdeBase.copyDir(dataDir, new File(buildDir, "data")); + } - // start with the main + // start with the main - // make up a temporary class name to suggest - // only used if the code is not in ADVANCED mode - String suggestedClassName = - ("Temporary_" + String.valueOf((int) (Math.random() * 10000)) + - "_" + String.valueOf((int) (Math.random() * 10000))); + // make up a temporary class name to suggest + // only used if the code is not in ADVANCED mode + String suggestedClassName = + ("Temporary_" + String.valueOf((int) (Math.random() * 10000)) + + "_" + String.valueOf((int) (Math.random() * 10000))); - // handle preprocessing the main file's code - String mainClassName = build(tempBuildPath, suggestedClassName); - // externalPaths is magically set by build() + // handle preprocessing the main file's code + String mainClassName = build(tempBuildPath, suggestedClassName); + // externalPaths is magically set by build() - // if the compilation worked, run the applet - if (mainClassName != null) { - - if (externalPaths == null) { - externalPaths = - PdeCompiler.calcClassPath(null) + File.pathSeparator + - tempBuildPath; - } else { - externalPaths = - tempBuildPath + File.pathSeparator + - PdeCompiler.calcClassPath(null) + File.pathSeparator + - externalPaths; - } - - // get a useful folder name for the 'code' folder - // so that it can be included in the java.library.path - String codeFolderPath = ""; - if (externalCode != null) { - libraryPath = externalCode.getCanonicalPath(); - } - - // create a runtime object - runtime = new PdeRuntime(this, className, - externalRuntime, - libraryPath, classPath); - //codeFolderPath, externalPaths); - - // if programType is ADVANCED - // or the code/ folder is not empty -> or just exists (simpler) - // then set boolean for external to true - // include path to build in front, then path for code folder - // when passing the classpath through - // actually, build will already be in there, just prepend code - - // use the runtime object to consume the errors now - //messageStream.setMessageConsumer(runtime); - // no need to bother recycling the old guy - PdeMessageStream messageStream = new PdeMessageStream(runtime); - - // start the applet - runtime.start(presenting ? presentLocation : appletLocation, - new PrintStream(messageStream)); - //leechErr); - - // spawn a thread to update PDE GUI state - watcher = new RunButtonWatcher(); + // if the compilation worked, run the applet + if (mainClassName != null) { + if (externalPaths == null) { + externalPaths = + PdeCompiler.calcClassPath(null) + File.pathSeparator + + tempBuildPath; } else { - // [dmose] throw an exception here? - // [fry] iirc the exception will have already been thrown - cleanTempFiles(); //tempBuildPath); + externalPaths = + tempBuildPath + File.pathSeparator + + PdeCompiler.calcClassPath(null) + File.pathSeparator + + externalPaths; } + + // get a useful folder name for the 'code' folder + // so that it can be included in the java.library.path + String codeFolderPath = ""; + if (externalCode != null) { + libraryPath = externalCode.getCanonicalPath(); + } + + // create a runtime object + runtime = new PdeRuntime(this, className, + externalRuntime, + libraryPath, classPath); + + // if programType is ADVANCED + // or the code/ folder is not empty -> or just exists (simpler) + // then set boolean for external to true + // include path to build in front, then path for code folder + // when passing the classpath through + // actually, build will already be in there, just prepend code + + // use the runtime object to consume the errors now + // no need to bother recycling the old guy + //PdeMessageStream messageStream = new PdeMessageStream(runtime); + + // start the applet + runtime.start(presenting ? presentLocation : appletLocation); //, + //new PrintStream(messageStream)); + + // spawn a thread to update PDE GUI state + watcher = new RunButtonWatcher(); + + } else { + // [dmose] throw an exception here? + // [fry] iirc the exception will have already been thrown + cleanTempFiles(); //tempBuildPath); + } + + /* } catch (PdeException e) { // if it made it as far as creating a Runtime object, // call its stop method to unwind its thread @@ -331,6 +379,48 @@ public class PdeSketch { cleanTempFiles(); //tempBuildPath); } + */ + } + + + class RunButtonWatcher implements Runnable { + Thread thread; + + public RunButtonWatcher() { + thread = new Thread(this); + thread.start(); + } + + public void run() { + while (Thread.currentThread() == thread) { + if (runtime == null) { + stop(); + + } else { + if (runtime.applet != null) { + if (runtime.applet.finished) { + stop(); + } + //buttons.running(!runtime.applet.finished); + + } else if (runtime.process != null) { + //buttons.running(true); // ?? + + } else { + stop(); + } + } + try { + Thread.sleep(250); + } catch (InterruptedException e) { } + //System.out.println("still inside runner thread"); + } + } + + public void stop() { + buttons.running(false); + thread = null; + } } @@ -349,27 +439,27 @@ public class PdeSketch { * * In an advanced program, the returned classname could be different, * which is why the className is set based on the return value. - * @return null if compilation failed, className if not + * @return null if compilation failed, main class name if not */ protected String build(String buildPath, String suggestedClassName) throws PdeException, Exception { - String classPath; - String libraryPath; - - boolean externalRuntime = false; - //externalPaths = null; String additionalImports[] = null; - //String additionalClassPath = null; + classPath = buildPath; // figure out the contents of the code folder to see if there // are files that need to be added to the imports File codeFolder = new File(sketchDir, "code"); if (codeFolder.exists()) { externalRuntime = true; - classPath = PdeCompiler.contentsToClassPath(codeFolder); - additionalImports = PdeCompiler.magicImports(additionalClassPath); - libraryPath = codeFolder. + classPath += File.separator + + PdeCompiler.contentsToClassPath(codeFolder); + additionalImports = PdeCompiler.magicImports(classPath); + libraryPath = codeFolder.getCanonicalPath(); + } else { + externalRuntime = (codeCount > 1); // at least for now + additionalImports = null; + libraryPath = ""; } // first run preproc on the 'main' file, using the sugg class name @@ -379,8 +469,21 @@ public class PdeSketch { // if no class def'd for the pde file, then complain for (int i = 0; i < codeCount; i++) { + if (code[i].flavor == JAVA) { + // no pre-processing services necessary for java files + // just write the the contents of 'program' to a .java file + // into the build directory. uses byte stream and reader/writer + // shtuff so that unicode bunk is properly handled + String filename = code[i].name + ".java"; + PdeBase.saveFile(code[i].program, new File(buildPath, filename)); + code[i].preprocName = filename; + continue; + } + PdePreprocessor preprocessor = new PdePreprocessor(); try { + // if (i != 0) preproc will fail if a pde file is not + // java mode, since that's required String className = preprocessor.write(code[i].program, buildPath, (i == 0) ? suggestedClassName : null, @@ -394,7 +497,11 @@ public class PdeSketch { code[i].preprocName = className + ".java"; } - if (i == 0) { // check if the 'main' file is in java mode + if (i == 0) { + // store this for the compiler and the runtime + mainClassName = className; + + // check if the 'main' file is in java mode if (PdePreprocessor.programType == PdePreprocessor.JAVA) { externalRuntime = true; // we in advanced mode now, boy } @@ -439,14 +546,11 @@ public class PdeSketch { } } - if (codeCount > 1) { - externalRuntime = true; - } - // compile the program // - PdeCompiler compiler = - new PdeCompiler(buildPath, mainClassName, externalCode, this); + //PdeCompiler compiler = + //new PdeCompiler(buildPath, mainClassName, externalCode, this); + PdeCompiler compiler = new PdeCompiler(this); // run the compiler, and funnel errors to the leechErr // which is a wrapped around