diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java
index e3d22f3fc..ac02fbe3a 100644
--- a/app/src/processing/app/Base.java
+++ b/app/src/processing/app/Base.java
@@ -46,9 +46,9 @@ import processing.mode.java.JavaMode;
public class Base {
// Added accessors for 0218 because the UpdateCheck class was not properly
// updating the values, due to javac inlining the static final values.
- static private final int REVISION = 227;
+ static private final int REVISION = 228;
/** This might be replaced by main() if there's a lib/version.txt file. */
- static private String VERSION_NAME = "0227"; //$NON-NLS-1$
+ static private String VERSION_NAME = "0228"; //$NON-NLS-1$
/** Set true if this a proper release rather than a numbered revision. */
// static private boolean RELEASE = false;
@@ -207,13 +207,11 @@ public class Base {
// Prevent more than one copy of the PDE from running.
SingleInstance.startServer(base);
- } catch (Exception e) {
+ } catch (Throwable t) {
// Catch-all to hopefully pick up some of the weirdness we've been
// running into lately.
- StringWriter sw = new StringWriter();
- e.printStackTrace(new PrintWriter(sw));
- Base.showError("We're off on the wrong foot",
- "An error occurred during startup.\n" + sw, e);
+ showBadnessTrace("We're off on the wrong foot",
+ "An error occurred during startup.", t, true);
}
log("done creating base..."); //$NON-NLS-1$
}
@@ -921,79 +919,88 @@ public class Base {
// protected Editor handleOpen(String path, int[] location) {
// protected Editor handleOpen(String path, Rectangle bounds, int divider) {
protected Editor handleOpen(String path, boolean untitled, EditorState state) {
- // System.err.println("entering handleOpen " + path);
+ try {
+ // System.err.println("entering handleOpen " + path);
- final File file = new File(path);
- if (!file.exists()) {
- return null;
- }
-
- // System.err.println(" editors: " + editors);
- // Cycle through open windows to make sure that it's not already open.
- for (Editor editor : editors) {
- if (editor.getSketch().getMainFile().equals(file)) {
- editor.toFront();
- // move back to the top of the recent list
- handleRecent(editor);
- return editor;
- }
- }
-
- if (!Sketch.isSanitaryName(file.getName())) {
- Base.showWarning("You're tricky, but not tricky enough",
- file.getName() + " is not a valid name for a sketch.\n" +
- "Better to stick to ASCII, no spaces, and make sure\n" +
- "it doesn't start with a number.", null);
- return null;
- }
-
- if (!nextMode.canEdit(file)) {
- final Mode mode = selectMode(file);
- if (mode == null) {
+ final File file = new File(path);
+ if (!file.exists()) {
return null;
}
- nextMode = mode;
- }
+
+ // System.err.println(" editors: " + editors);
+ // Cycle through open windows to make sure that it's not already open.
+ for (Editor editor : editors) {
+ if (editor.getSketch().getMainFile().equals(file)) {
+ editor.toFront();
+ // move back to the top of the recent list
+ handleRecent(editor);
+ return editor;
+ }
+ }
+
+ if (!Sketch.isSanitaryName(file.getName())) {
+ Base.showWarning("You're tricky, but not tricky enough",
+ file.getName() + " is not a valid name for a sketch.\n" +
+ "Better to stick to ASCII, no spaces, and make sure\n" +
+ "it doesn't start with a number.", null);
+ return null;
+ }
+
+ if (!nextMode.canEdit(file)) {
+ final Mode mode = selectMode(file);
+ if (mode == null) {
+ return null;
+ }
+ nextMode = mode;
+ }
// Editor.State state = new Editor.State(editors);
- Editor editor = nextMode.createEditor(this, path, state);
- if (editor == null) {
- // if it's the last editor window
+ Editor editor = nextMode.createEditor(this, path, state);
+ if (editor == null) {
+ // if it's the last editor window
// if (editors.size() == 0 && defaultFileMenu == null) {
- // if it's not mode[0] already, then don't go into an infinite loop
- // trying to recreate a window with the default mode.
- if (nextMode == coreModes[0]) {
- Base.showError("Editor Problems",
- "An error occurred while trying to change modes.\n" +
- "We'll have to quit for now because it's an\n" +
- "unfortunate bit of indigestion.",
- null);
- } else {
- editor = coreModes[0].createEditor(this, path, state);
+ // if it's not mode[0] already, then don't go into an infinite loop
+ // trying to recreate a window with the default mode.
+ if (nextMode == coreModes[0]) {
+ Base.showError("Editor Problems",
+ "An error occurred while trying to change modes.\n" +
+ "We'll have to quit for now because it's an\n" +
+ "unfortunate bit of indigestion.",
+ null);
+ } else {
+ editor = coreModes[0].createEditor(this, path, state);
+ }
}
- }
- // Make sure that the sketch actually loaded
- if (editor.getSketch() == null) {
+ // Make sure that the sketch actually loaded
+ if (editor.getSketch() == null) {
// System.err.println("sketch was null, getting out of handleOpen");
- return null; // Just walk away quietly
- }
+ return null; // Just walk away quietly
+ }
// editor.untitled = untitled;
- editor.getSketch().setUntitled(untitled);
- editors.add(editor);
- handleRecent(editor);
+ editor.getSketch().setUntitled(untitled);
+ editors.add(editor);
+ handleRecent(editor);
- // now that we're ready, show the window
- // (don't do earlier, cuz we might move it based on a window being closed)
- editor.setVisible(true);
+ // now that we're ready, show the window
+ // (don't do earlier, cuz we might move it based on a window being closed)
+ editor.setVisible(true);
- return editor;
+ return editor;
+
+ } catch (Throwable t) {
+ showBadnessTrace("Terrible News",
+ "A serious error occurred while " +
+ "trying to create a new editor window.", t, false);
+ nextMode = coreModes[0];
+ return null;
+ }
}
+
private static class ModeInfo {
public final String title;
-
public final String id;
public ModeInfo(String id, String title) {
@@ -1002,6 +1009,7 @@ public class Base {
}
}
+
private static ModeInfo modeInfoFor(final File sketch) {
final File sketchFolder = sketch.getParentFile();
final File sketchProps = new File(sketchFolder, "sketch.properties");
@@ -1023,6 +1031,7 @@ public class Base {
return null;
}
+
private Mode promptForMode(final File sketch, final ModeInfo preferredMode) {
final String extension =
sketch.getName().substring(sketch.getName().lastIndexOf('.') + 1);
@@ -1065,6 +1074,7 @@ public class Base {
null, modes, modes[0]);
}
+
private Mode selectMode(final File sketch) {
final ModeInfo modeInfo = modeInfoFor(sketch);
final Mode specifiedMode = modeInfo == null ? null : findMode(modeInfo.id);
@@ -1074,6 +1084,7 @@ public class Base {
return promptForMode(sketch, modeInfo);
}
+
protected Mode findMode(String id) {
for (Mode mode : getModeList()) {
if (mode.getIdentifier().equals(id)) {
@@ -1083,6 +1094,7 @@ public class Base {
return null;
}
+
/**
* Close a sketch as specified by its editor window.
* @param editor Editor object of the sketch to be closed.
@@ -2255,6 +2267,35 @@ public class Base {
}
+ /**
+ * Testing a new warning window that includes the stack trace.
+ */
+ static private void showBadnessTrace(String title, String message,
+ Throwable t, boolean fatal) {
+ if (title == null) title = fatal ? "Error" : "Warning";
+
+ if (commandLine) {
+ System.err.println(title + ": " + message);
+ if (t != null) {
+ t.printStackTrace();
+ }
+
+ } else {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ // Necessary to replace \n with
(even if pre) otherwise Java
+ // treats it as a closed tag and reverts to plain formatting.
+ message = "" + message + "
" +
+ sw.toString().replaceAll("\n", "
");
+
+ JOptionPane.showMessageDialog(new Frame(), message, title,
+ fatal ?
+ JOptionPane.ERROR_MESSAGE :
+ JOptionPane.WARNING_MESSAGE);
+ }
+ }
+
+
// ...................................................................
@@ -2486,7 +2527,8 @@ public class Base {
//return "Contents/PlugIns/jdk1.7.0_40.jdk/Contents/Home/jre/bin/java";
File[] plugins = getContentFile("../PlugIns").listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
- return name.endsWith(".jdk") && dir.isDirectory();
+ return dir.isDirectory() &&
+ name.endsWith(".jdk") && !name.startsWith(".");
}
});
return new File(plugins[0], "Contents/Home/jre");
diff --git a/app/src/processing/app/Toolkit.java b/app/src/processing/app/Toolkit.java
index 357621714..34aa23834 100644
--- a/app/src/processing/app/Toolkit.java
+++ b/app/src/processing/app/Toolkit.java
@@ -24,6 +24,7 @@ package processing.app;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
+import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
@@ -152,12 +153,12 @@ public class Toolkit {
static ArrayList iconImages;
- // Removed in favor of Window being the base object, so that dialogs can
- // be supported as well. If this breaks tools/modes, we can bring it back,
- // but it was essentially an undocumented feature.
-// static public void setIcon(Frame frame) {
-// setIcon(frame);
-// }
+ // Deprecated version of the function, but can't get rid of it without
+ // breaking tools and modes (they'd only require a recompile, but they would
+ // no longer be backwards compatible.
+ static public void setIcon(Frame frame) {
+ setIcon((Window) frame);
+ }
/**
@@ -167,10 +168,6 @@ public class Toolkit {
*/
static public void setIcon(Window window) {
if (!Base.isMacOS()) {
-// // too low-res, prepping for nicer icons in 2.0 timeframe
-// Image image = awtToolkit.createImage(PApplet.ICON_IMAGE);
-// frame.setIconImage(image);
-
if (iconImages == null) {
iconImages = new ArrayList();
final int[] sizes = { 16, 32, 48, 64, 128, 256, 512 };
diff --git a/app/src/processing/app/contrib/AvailableContribution.java b/app/src/processing/app/contrib/AvailableContribution.java
index b4cb57cd4..a815ab6da 100644
--- a/app/src/processing/app/contrib/AvailableContribution.java
+++ b/app/src/processing/app/contrib/AvailableContribution.java
@@ -48,7 +48,10 @@ class AvailableContribution extends Contribution {
url = params.get("url");
sentence = params.get("sentence");
paragraph = params.get("paragraph");
- version = PApplet.parseInt(params.get("version"), 0);
+ String versionStr = params.get("version");
+ if (versionStr != null) {
+ version = PApplet.parseInt(versionStr, 0);
+ }
prettyVersion = params.get("prettyVersion");
}
diff --git a/app/src/processing/app/tools/Archiver.java b/app/src/processing/app/tools/Archiver.java
index ab2a3e424..4e34b9748 100644
--- a/app/src/processing/app/tools/Archiver.java
+++ b/app/src/processing/app/tools/Archiver.java
@@ -102,6 +102,11 @@ public class Archiver implements Tool {
public void fileSelected(File newbie) {
if (newbie != null) {
try {
+ // Force a .zip extension
+ // https://github.com/processing/processing/issues/2526
+ if (!newbie.getName().toLowerCase().endsWith(".zip")) {
+ newbie = new File(newbie.getAbsolutePath() + ".zip");
+ }
//System.out.println(newbie);
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
diff --git a/app/src/processing/mode/java/AutoFormat.java b/app/src/processing/mode/java/AutoFormat.java
index 935e2a903..91d8a7cec 100644
--- a/app/src/processing/mode/java/AutoFormat.java
+++ b/app/src/processing/mode/java/AutoFormat.java
@@ -38,56 +38,62 @@ import processing.core.PApplet;
*
* After some further digging, this code in fact appears to be a modified
* version of Jason Pell's GPLed "Java Beautifier" class found
- * here.
- * Which is itself based on code from Van Di-Han Ho from
- * here.
+ * here,
+ * which is itself based on code from Van Di-Han Ho from
+ * here.
* [Ben Fry, August 2009]
*/
public class AutoFormat implements Formatter {
private char[] chars;
private final StringBuilder buf = new StringBuilder();
-
private final StringBuilder result = new StringBuilder();
private int indentValue;
private boolean EOF;
- private boolean a_flg, e_flg, if_flg, s_flag, q_flg;
- private boolean s_if_flg[];
+ private boolean a_flg, if_flg, s_flag, elseFlag;
+
+ /** Number of ? entered without exiting at : of a?b:c structures. */
+ private int conditionalLevel;
+
private int pos;
-// private int lineNumber;
- private int s_level[];
private int c_level;
- private int sp_flg[][];
- private int s_ind[][];
- private int s_if_lev[];
- private int if_lev, level;
- private int ind[];
- private int paren;
- private int p_flg[];
+ private int[][] sp_flg;
+ private int[][] s_ind;
+ private int if_lev;
+
+ /** Number of curly brackets entered and not exited. */
+ private int level;
+
+ /** Number of parentheses entered and not exited. */
+ private int parenLevel;
+
+ private int[] ind;
+ private int[] p_flg;
private char l_char;
- private int ct;
- private int s_tabs[][];
+ private int[][] s_tabs;
private boolean jdoc_flag;
private char cc;
private int tabs;
private char c;
+ private char lastNonWhitespace = 0;
private final Stack castFlags = new Stack();
- private void comment() {
- final boolean save_s_flg = s_flag;
+ private void handleMultiLineComment() {
+ final boolean saved_s_flag = s_flag;
- buf.append(c = next()); // extra char
+ char ch;
+ buf.append(ch = nextChar()); // extra char
while (true) {
- buf.append(c = next());
- while ((c != '/')) {
- if (c == '\n') {
-// lineNumber++;
+ buf.append(ch = nextChar());
+ while (ch != '/') {
+ if (ch == '\n') {
+// lineNumber++;
writeIndentedComment();
s_flag = true;
}
- buf.append(c = next());
+ buf.append(ch = nextChar());
}
if (buf.length() >= 2 && buf.charAt(buf.length() - 2) == '*') {
jdoc_flag = false;
@@ -96,50 +102,65 @@ public class AutoFormat implements Formatter {
}
writeIndentedComment();
- s_flag = save_s_flg;
+ s_flag = saved_s_flag;
jdoc_flag = false;
return;
}
-
- private char get_string() {
- char ch;
- while (true) {
- buf.append(ch = next());
- if (ch == '\\') {
- buf.append(next());
- continue;
- }
- if (ch == '\'' || ch == '"') {
- buf.append(cc = next());
- while (!EOF && cc != ch) {
- if (cc == '\\') {
- buf.append(next());
- }
- buf.append(cc = next());
- }
- continue;
- }
- if (ch == '\n') {
- writeIndentedLine();
- a_flg = true;
- continue;
- }
- return ch;
+
+ private void handleSingleLineComment() {
+ char ch = nextChar();
+ while (ch != '\n') {
+ buf.append(ch);
+ ch = nextChar();
}
+// lineNumber++;
+ writeIndentedLine();
+ s_flag = true;
}
+
+// /**
+// * Transfers buf to result until a character is reached that
+// * is neither \, \n, or in a string. \n is not written, but
+// * writeIndentedLine is called on finding it.
+// * @return The first character not listed above.
+// */
+// private char get_string() {
+// char ch1, ch2;
+// while (true) {
+// buf.append(ch1 = nextChar());
+// if (ch1 == '\\') {
+// buf.append(nextChar());
+// } else if (ch1 == '\'' || ch1 == '\"') {
+// buf.append(ch2 = nextChar());
+// while (!EOF && ch2 != ch1) {
+// if (ch2 == '\\') {
+// // Next char is escaped, ignore.
+// buf.append(nextChar());
+// }
+// buf.append(ch2 = nextChar());
+// }
+// } else if (ch1 == '\n') {
+// writeIndentedLine();
+// a_flg = true;
+// } else {
+// return ch1;
+// }
+// }
+// }
+
private void writeIndentedLine() {
if (buf.length() == 0) {
if (s_flag) {
- s_flag = a_flg = e_flg = false;
+ s_flag = a_flg = elseFlag = false;
}
return;
}
if (s_flag) {
- final boolean shouldIndent = (tabs > 0) && (buf.charAt(0) != '{')
- && a_flg;
+ final boolean shouldIndent =
+ (tabs > 0) && (buf.charAt(0) != '{') && a_flg;
if (shouldIndent) {
tabs++;
}
@@ -150,23 +171,22 @@ public class AutoFormat implements Formatter {
}
a_flg = false;
}
- if (e_flg) {
+ if (elseFlag) {
if (lastNonSpaceChar() == '}') {
trimRight(result);
- result.append(" ");
+ result.append(' ');
}
- e_flg = false;
+ elseFlag = false;
}
result.append(buf);
buf.setLength(0);
}
-
+
private char lastNonSpaceChar() {
- for (int i=result.length()-1; i>=0; i--) {
+ for (int i = result.length() - 1; i >= 0; i--) {
char c_i = result.charAt(i);
- if (c_i == ' ' || c_i == '\n') continue;
- else return c_i;
+ if (c_i != ' ' && c_i != '\n') return c_i;
}
return 0;
}
@@ -187,7 +207,7 @@ public class AutoFormat implements Formatter {
jdoc_flag = true;
}
if (buf.charAt(i) == '/' && buf.charAt(i + 1) == '*') {
- if (saved_s_flag && prev() != ';') {
+ if (saved_s_flag && getLastNonWhitespace() != ';') {
result.append(buf.substring(i));
} else {
result.append(buf);
@@ -204,18 +224,6 @@ public class AutoFormat implements Formatter {
}
- private void handleSingleLineComment() {
- c = next();
- while (c != '\n') {
- buf.append(c);
- c = next();
- }
-// lineNumber++;
- writeIndentedLine();
- s_flag = true;
- }
-
-
private void printIndentation() {
if (tabs < 0) {
tabs = 0;
@@ -225,7 +233,7 @@ public class AutoFormat implements Formatter {
}
final int spaces = tabs * indentValue;
for (int k = 0; k < spaces; k++) {
- result.append(" ");
+ result.append(' ');
}
}
@@ -238,10 +246,7 @@ public class AutoFormat implements Formatter {
}
- private char lastNonWhitespace = 0;
-
-
- private int prev() {
+ private int getLastNonWhitespace() {
return lastNonWhitespace;
}
@@ -256,33 +261,32 @@ public class AutoFormat implements Formatter {
if (pos == chars.length - 1) {
EOF = true;
} else {
- pos--; // reset for next()
+ pos--; // reset for nextChar()
}
}
- private char next() {
+ private char nextChar() {
if (EOF) {
- return 0;
+ return '\0';
}
pos++;
- final char c;
+ char retVal;
if (pos < chars.length) {
- c = chars[pos];
- if (!Character.isWhitespace(c))
- lastNonWhitespace = c;
+ retVal = chars[pos];
+ if (!Character.isWhitespace(retVal))
+ lastNonWhitespace = retVal;
} else {
- c = 0;
+ retVal = '\0';
}
- if (pos == chars.length - 1) {
+ if (pos == chars.length-1) {
EOF = true;
}
- return c;
+ return retVal;
}
- /* else processing */
- private void gotelse() {
+ private void gotElse() {
tabs = s_tabs[c_level][if_lev];
p_flg[level] = sp_flg[c_level][if_lev];
ind[level] = s_ind[c_level][if_lev];
@@ -290,23 +294,22 @@ public class AutoFormat implements Formatter {
}
- /* read to new_line */
- private boolean getnl() {
+ private boolean readUntilNewLine() {
final int savedTabs = tabs;
char c = peek();
while (!EOF && (c == '\t' || c == ' ')) {
- buf.append(next());
+ buf.append(nextChar());
c = peek();
}
if (c == '/') {
- buf.append(next());
+ buf.append(nextChar());
c = peek();
if (c == '*') {
- buf.append(next());
- comment();
+ buf.append(nextChar());
+ handleMultiLineComment();
} else if (c == '/') {
- buf.append(next());
+ buf.append(nextChar());
handleSingleLineComment();
return true;
}
@@ -315,7 +318,7 @@ public class AutoFormat implements Formatter {
c = peek();
if (c == '\n') {
// eat it
- next();
+ nextChar();
// lineNumber++;
tabs = savedTabs;
return true;
@@ -344,24 +347,25 @@ public class AutoFormat implements Formatter {
public String format(final String source) {
final String normalizedText = source.replaceAll("\r", "");
- final String cleanText = normalizedText
- + (normalizedText.endsWith("\n") ? "" : "\n");
+ final String cleanText =
+ normalizedText + (normalizedText.endsWith("\n") ? "" : "\n");
result.setLength(0);
indentValue = Preferences.getInteger("editor.tabs.size");
-// lineNumber = 0;
- q_flg = e_flg = a_flg = if_flg = false;
+// lineNumber = 0;
+ boolean forFlag = a_flg = if_flg = false;
s_flag = true;
- c_level = if_lev = level = paren = 0;
+ int forParenthLevel = 0;
+ conditionalLevel = parenLevel = c_level = if_lev = level = 0;
tabs = 0;
jdoc_flag = false;
- s_level = new int[10];
+ int[] s_level = new int[10];
sp_flg = new int[20][10];
s_ind = new int[20][10];
- s_if_lev = new int[10];
- s_if_flg = new boolean[10];
+ int[] s_if_lev = new int[10];
+ boolean[] s_if_flg = new boolean[10];
ind = new int[10];
p_flg = new int[10];
s_tabs = new int[20][10];
@@ -369,10 +373,10 @@ public class AutoFormat implements Formatter {
chars = cleanText.toCharArray();
// lineNumber = 1;
- EOF = false; // set in next() when EOF
+ EOF = false; // set in nextChar() when EOF
while (!EOF) {
- c = next();
+ c = nextChar();
switch (c) {
default:
buf.append(c);
@@ -388,12 +392,13 @@ public class AutoFormat implements Formatter {
case ' ':
case '\t':
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
+ elseFlag = lookup("else");
+ if (elseFlag) {
+ gotElse();
if ((!s_flag) || buf.length() > 0) {
buf.append(c);
}
+
writeIndentedLine();
s_flag = false;
break;
@@ -408,9 +413,9 @@ public class AutoFormat implements Formatter {
if (EOF) {
break;
}
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
+ elseFlag = lookup("else");
+ if (elseFlag) {
+ gotElse();
}
if (lookup_com("//")) {
final char lastChar = buf.charAt(buf.length() - 1);
@@ -422,19 +427,18 @@ public class AutoFormat implements Formatter {
writeIndentedLine();
result.append("\n");
s_flag = true;
- if (e_flg) {
+ if (elseFlag) {
p_flg[level]++;
tabs++;
- } else if (prev() == l_char) {
+ } else if (getLastNonWhitespace() == l_char) {
a_flg = true;
}
break;
case '{':
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
- }
+ elseFlag = lookup("else");
+ if (elseFlag) gotElse();
+
if (s_if_lev.length == c_level) {
s_if_lev = PApplet.expand(s_if_lev);
s_if_flg = PApplet.expand(s_if_flg);
@@ -454,9 +458,9 @@ public class AutoFormat implements Formatter {
buf.append(" ");
buf.append(c);
writeIndentedLine();
- getnl();
+ readUntilNewLine();
writeIndentedLine();
- //fprintf(outfil,"\n");
+
result.append("\n");
tabs++;
s_flag = true;
@@ -489,11 +493,12 @@ public class AutoFormat implements Formatter {
printIndentation();
result.append(c);
if (peek() == ';') {
- result.append(next());
+ result.append(nextChar());
}
- getnl();
+
+ readUntilNewLine();
writeIndentedLine();
- result.append("\n");
+ result.append('\n');
s_flag = true;
if (c_level < s_level[level]) {
if (level > 0) {
@@ -511,21 +516,21 @@ public class AutoFormat implements Formatter {
case '"':
case '\'':
buf.append(c);
- cc = next();
+ cc = nextChar();
while (!EOF && cc != c) {
buf.append(cc);
if (cc == '\\') {
- buf.append(cc = next());
+ buf.append(cc = nextChar());
}
if (cc == '\n') {
// lineNumber++;
writeIndentedLine();
s_flag = true;
}
- cc = next();
+ cc = nextChar();
}
buf.append(cc);
- if (getnl()) {
+ if (readUntilNewLine()) {
l_char = cc;
// push a newline into the stream
chars[pos--] = '\n';
@@ -533,13 +538,21 @@ public class AutoFormat implements Formatter {
break;
case ';':
+ if (forFlag) {
+ // This is like a comma.
+ trimRight(buf);
+ buf.append("; ");
+ // Not non-whitespace: allow \n.
+ advanceToNonSpace();
+ break;
+ }
buf.append(c);
writeIndentedLine();
if (p_flg[level] > 0 && ind[level] == 0) {
tabs -= p_flg[level];
p_flg[level] = 0;
}
- getnl();
+ readUntilNewLine();
writeIndentedLine();
result.append("\n");
s_flag = true;
@@ -555,26 +568,39 @@ public class AutoFormat implements Formatter {
case '\\':
buf.append(c);
- buf.append(next());
+ buf.append(nextChar());
break;
case '?':
- q_flg = true;
+ conditionalLevel++;
buf.append(c);
break;
case ':':
- buf.append(c);
+ // Java 8 :: operator.
if (peek() == ':') {
writeIndentedLine();
- result.append(next());
+ result.append(c).append(nextChar());
break;
}
- if (q_flg) {
- q_flg = false;
+ // End a?b:c structures.
+ else if (conditionalLevel>0) {
+ conditionalLevel--;
+ buf.append(c);
break;
}
+
+ else if (forFlag) {
+ trimRight(buf);
+ buf.append(" : ");
+ // Not to non-whitespace: allow \n.
+ advanceToNonSpace();
+ break;
+ }
+
+ buf.append(c);
+
if (!lookup("default") && !lookup("case")) {
s_flag = false;
writeIndentedLine();
@@ -584,26 +610,27 @@ public class AutoFormat implements Formatter {
tabs++;
}
if (peek() == ';') {
- result.append(next());
+ result.append(nextChar());
}
- getnl();
+ readUntilNewLine();
writeIndentedLine();
- result.append("\n");
+ result.append('\n');
s_flag = true;
break;
case '/':
- final char la = peek();
- if (la == '/') {
- buf.append(c).append(next());
+ final char next = peek();
+ if (next == '/') {
+ // call nextChar to move on.
+ buf.append(c).append(nextChar());
handleSingleLineComment();
result.append("\n");
- } else if (la == '*') {
+ } else if (next == '*') {
if (buf.length() > 0) {
writeIndentedLine();
}
- buf.append(c).append(next());
- comment();
+ buf.append(c).append(nextChar());
+ handleMultiLineComment();
} else {
buf.append(c);
}
@@ -613,15 +640,23 @@ public class AutoFormat implements Formatter {
final boolean isCast = castFlags.isEmpty() ? false : castFlags.pop();
- paren--;
- if (paren < 0) {
- paren = 0;
+ parenLevel--;
+
+ // If we're further back than the start of a for loop, we've
+ // left it.
+ if (forFlag && forParenthLevel > parenLevel) {
+ forFlag = false;
}
+
+ if (parenLevel < 0) {
+ parenLevel = 0;
+ }
+
buf.append(c);
writeIndentedLine();
- if (getnl()) {
+ if (readUntilNewLine()) {
chars[pos--] = '\n';
- if (paren != 0) {
+ if (parenLevel != 0) {
a_flg = true;
} else if (tabs > 0 && !isCast) {
p_flg[level]++;
@@ -644,42 +679,16 @@ public class AutoFormat implements Formatter {
}
buf.append(c);
- paren++;
+ parenLevel++;
+ // isFor says "is it the start of a for?". If it is, we set forFlag and
+ // forParenthLevel. If it is not parenth_lvl was incremented above and
+ // that's it.
if (isFor) {
- // TODO(feinberg): handle new-style for loops
- c = get_string();
- while (c != ';' && c != ':') {
- c = get_string();
+ if (!forFlag) {
+ forParenthLevel = parenLevel;
+ forFlag = true;
}
- ct = 0;
- int for_done = 0;
- while (for_done == 0) {
- c = get_string();
- while (c != ')') {
- if (c == '(') {
- ct++;
- }
- c = get_string();
- }
- if (ct != 0) {
- ct--;
- } else {
- for_done = 1;
- }
- } // endwhile for_done
- paren--;
- if (paren < 0) {
- paren = 0;
- }
- writeIndentedLine();
- if (getnl()) {
- chars[pos--] = '\n';
- p_flg[level]++;
- tabs++;
- ind[level] = 0;
- }
- break;
} else if (isIf) {
writeIndentedLine();
s_tabs[c_level][if_lev] = tabs;
diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt
index 32f287df0..4b6516220 100644
--- a/build/shared/revisions.txt
+++ b/build/shared/revisions.txt
@@ -1,3 +1,47 @@
+PROCESSING 2.2.1 (REV 0227) - 19 May 2014
+
+A handful of bug fixes, the most prominent rolls back a change that broke
+PDE X and other Modes and Tools.
+
++ Bring back setIcon(Frame) for PDE X and others
+ https://github.com/processing/processing-experimental/issues/64
+
++ Add additional code for crashing when the Mode is changed or new editor
+ windows opened.
+
++ Use mouseReleased() instead of mousePressed() in the color selector,
+ otherwise it registers the release as a click in the color window
+ https://github.com/processing/processing/issues/2514
+
++ Missing 'version' in contribution properties file causes NullPointerException
+ https://github.com/processing/processing/issues/2517
+
++ A handful of fixes to Auto Format
+ https://github.com/processing/processing/pull/2271
+
++ Command line tools not working on OS X due to AppleDouble file boogers.
+ https://github.com/processing/processing/issues/2520
+
++ Make "Archive Sketch" Tool force a .zip file extension
+ https://github.com/processing/processing/issues/2526
+
++ Event handling modifications in video and serial libraries w/ Python Mode
+ https://github.com/processing/processing/pull/2527
+ https://github.com/processing/processing/pull/2528
+ https://github.com/processing/processing/pull/2529
+
++ Permit mouse PRESS to set mouseX/mouseY
+ https://github.com/processing/processing/pull/2509
+
++ Fix for video: the loop() method was broken in the last release.
+ https://github.com/processing/processing/issues/2524
+
++ Updated reference files included in the download.
+
+
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
PROCESSING 2.2 (REV 0226) - 12 May 2014
Major changes to, and improvements upon, how "Export to Application" works.
diff --git a/core/done.txt b/core/done.txt
index 99dda8671..694933b4b 100644
--- a/core/done.txt
+++ b/core/done.txt
@@ -1,3 +1,10 @@
+0227 core (2.2.1)
+X Permit mouse PRESS to set mouseX/mouseY
+X https://github.com/processing/processing/pull/2509
+A Fix for video, loop() broken in 2.2
+A https://github.com/processing/processing/issues/2524
+
+
0226 core (2.2)
X fix parsing with missing categorical values
X fix for splice() throwing a ClassCastException with other object types
diff --git a/core/todo.txt b/core/todo.txt
index abe9963fe..ea362845a 100644
--- a/core/todo.txt
+++ b/core/todo.txt
@@ -1,7 +1,11 @@
-0227 core
+0228 core
high
+_ pull for image resize and alpha issues
+_ https://github.com/processing/processing/pull/2324
+_ dataPath() not working when app is not run from app dir on Linux
+_ https://github.com/processing/processing/issues/2195
_ "Buffers have not been created" error for sketches w/o draw()
_ https://github.com/processing/processing/issues/2469
_ could not reproduce
diff --git a/done.txt b/done.txt
index 172d7230a..225f3aa3a 100644
--- a/done.txt
+++ b/done.txt
@@ -1,3 +1,29 @@
+0227 pde (2.2.1)
+X use mouseReleased() instead of mousePressed() in color selector
+X otherwise it registers the release as a click in the color window
+X https://github.com/processing/processing/issues/2514
+X missing 'version' in contrib causes NPE
+X https://github.com/processing/processing/issues/2517
+X bring back setIcon(Frame) for PDE X and others
+X https://github.com/processing/processing-experimental/issues/64
+X how was PDE X able to crash 2.2?
+X add additional code to rework how this is handled
+X Auto Format patch mess
+X https://github.com/processing/processing/pull/2271
+X why is the JDK path showing up as a ._ feller in OS X?
+X https://github.com/processing/processing/issues/2520
+X "Archive Sketch" Tool doesn't force a .zip file extension
+X https://github.com/processing/processing/issues/2526
+
+python
+J modifications for captureEvent and Python
+J https://github.com/processing/processing/pull/2527
+J Permit implementing movieEvent without having to link to Movie at build time
+J https://github.com/processing/processing/pull/2528
+J implement serial events without having to link to Serial at build time
+J https://github.com/processing/processing/pull/2529
+
+
0226 pde (2.2)
X sketches only starting once, or half-starting and hanging
X https://github.com/processing/processing/issues/2402
diff --git a/java/libraries/serial/src/processing/serial/Serial.java b/java/libraries/serial/src/processing/serial/Serial.java
index befad4afa..f473f863d 100644
--- a/java/libraries/serial/src/processing/serial/Serial.java
+++ b/java/libraries/serial/src/processing/serial/Serial.java
@@ -112,15 +112,21 @@ public class Serial implements SerialPortEventListener {
throw new RuntimeException("Error opening serial port " + e.getPortName() + ": " + e.getExceptionType());
}
- try {
- serialEventMethod = parent.getClass().getMethod("serialEvent", new Class[] { this.getClass() });
- } catch (Exception e) {
- }
+ serialEventMethod = findCallback("serialEvent");
+ serialAvailableMethod = findCallback("serialAvailable");
+ }
+ private Method findCallback(final String name) {
try {
- serialAvailableMethod = parent.getClass().getMethod("serialAvailable", new Class[] { this.getClass() });
+ return parent.getClass().getMethod(name, this.getClass());
} catch (Exception e) {
}
+ // Permit callback(Object) as alternative to callback(Serial).
+ try {
+ return parent.getClass().getMethod(name, Object.class);
+ } catch (Exception e) {
+ }
+ return null;
}
@@ -133,7 +139,7 @@ public class Serial implements SerialPortEventListener {
if (serialAvailableMethod != null && invokeSerialAvailable) {
invokeSerialAvailable = false;
try {
- serialAvailableMethod.invoke(parent, new Object[] { this });
+ serialAvailableMethod.invoke(parent, this);
} catch (Exception e) {
System.err.println("Error, disabling serialAvailable() for "+port.getPortName());
System.err.println(e.getLocalizedMessage());
@@ -392,7 +398,7 @@ public class Serial implements SerialPortEventListener {
// available() and read() inside draw - but this function has no
// thread-safety issues since it's being invoked during pre in the context
// of the Processing applet
- serialEventMethod.invoke(parent, new Object[] { this });
+ serialEventMethod.invoke(parent, this);
} catch (Exception e) {
System.err.println("Error, disabling serialEvent() for "+port.getPortName());
System.err.println(e.getLocalizedMessage());
diff --git a/java/libraries/video/src/processing/video/Capture.java b/java/libraries/video/src/processing/video/Capture.java
index 8f233b9c5..5d4221fb5 100644
--- a/java/libraries/video/src/processing/video/Capture.java
+++ b/java/libraries/video/src/processing/video/Capture.java
@@ -112,7 +112,7 @@ public class Capture extends PImage implements PConstants {
protected Method sinkCopyMethod;
protected Method sinkSetMethod;
protected Method sinkDisposeMethod;
- protected Method sinkGetMethod;
+ protected Method sinkGetMethod;
protected String copyMask;
protected Buffer natBuffer = null;
protected BufferDataAppSink natSink = null;
@@ -239,7 +239,7 @@ public class Capture extends PImage implements PConstants {
/**
* Disposes all the native resources associated to this capture device.
- *
+ *
* NOTE: This is not official API and may/will be removed at any time.
*/
public void dispose() {
@@ -271,10 +271,10 @@ public class Capture extends PImage implements PConstants {
pipeline.dispose();
pipeline = null;
-
+
parent.g.removeCache(this);
parent.unregisterMethod("dispose", this);
- parent.unregisterMethod("post", this);
+ parent.unregisterMethod("post", this);
}
}
@@ -308,11 +308,11 @@ public class Capture extends PImage implements PConstants {
/**
* ( begin auto-generated from Capture_start.xml )
- *
+ *
* Starts capturing frames from the selected device.
- *
+ *
* ( end auto-generated )
- *
+ *
* @webref capture
* @brief Starts capturing frames from the selected device
*/
@@ -425,7 +425,7 @@ public class Capture extends PImage implements PConstants {
newFrame = true;
}
-
+
public synchronized void loadPixels() {
super.loadPixels();
if (useBufferSink) {
@@ -441,24 +441,24 @@ public class Capture extends PImage implements PConstants {
try {
// sinkGetMethod will copy the latest buffer to the pixels array,
// and the pixels will be copied to the texture when the OpenGL
- // renderer needs to draw it.
- sinkGetMethod.invoke(bufferSink, new Object[] { pixels });
+ // renderer needs to draw it.
+ sinkGetMethod.invoke(bufferSink, new Object[] { pixels });
} catch (Exception e) {
e.printStackTrace();
- }
- }
+ }
+ }
- outdatedPixels = false;
+ outdatedPixels = false;
}
}
-
-
+
+
public int get(int x, int y) {
if (outdatedPixels) loadPixels();
return super.get(x, y);
}
-
-
+
+
protected void getImpl(int sourceX, int sourceY,
int sourceWidth, int sourceHeight,
PImage target, int targetX, int targetY) {
@@ -466,8 +466,8 @@ public class Capture extends PImage implements PConstants {
super.getImpl(sourceX, sourceY, sourceWidth, sourceHeight,
target, targetX, targetY);
}
-
-
+
+
////////////////////////////////////////////////////////////
// List methods.
@@ -966,7 +966,7 @@ public class Capture extends PImage implements PConstants {
/**
* Uses a generic object as handler of the capture. This object should have a
- * movieEvent method that receives a GSMovie argument. This method will
+ * captureEvent method that receives a Capture argument. This method will
* be called upon a new frame read event.
*
*/
@@ -974,8 +974,17 @@ public class Capture extends PImage implements PConstants {
eventHandler = obj;
try {
- captureEventMethod = parent.getClass().getMethod("captureEvent",
- new Class[] { Capture.class });
+ captureEventMethod = obj.getClass().getMethod("captureEvent", Capture.class);
+ return;
+ } catch (Exception e) {
+ // no such method, or an error.. which is fine, just ignore
+ }
+
+ // The captureEvent method may be declared as receiving Object, rather
+ // than Capture.
+ try {
+ captureEventMethod = obj.getClass().getMethod("captureEvent", Object.class);
+ return;
} catch (Exception e) {
// no such method, or an error.. which is fine, just ignore
}
@@ -1008,18 +1017,7 @@ public class Capture extends PImage implements PConstants {
copyPixels = null;
return;
}
-
- // Creates a movieEvent.
- if (captureEventMethod != null) {
- try {
- captureEventMethod.invoke(eventHandler, new Object[] { this });
- } catch (Exception e) {
- System.err.println(
- "error, disabling captureEvent() for capture object");
- e.printStackTrace();
- captureEventMethod = null;
- }
- }
+ fireCaptureEvent();
}
@@ -1028,20 +1026,23 @@ public class Capture extends PImage implements PConstants {
bufWidth = w;
bufHeight = h;
if (natBuffer != null) {
- // To handle the situation where read() is not called in the sketch, so
- // that the native buffers are not being sent to the sinke, and therefore, not disposed
- // by it.
- natBuffer.dispose();
- }
+ // To handle the situation where read() is not called in the sketch,
+ // so that the native buffers are not being sent to the sink,
+ // and therefore, not disposed by it.
+ natBuffer.dispose();
+ }
natBuffer = buffer;
+ fireCaptureEvent();
+ }
- // Creates a movieEvent.
+
+ private void fireCaptureEvent() {
if (captureEventMethod != null) {
try {
- captureEventMethod.invoke(eventHandler, new Object[] { this });
+ captureEventMethod.invoke(eventHandler, this);
+
} catch (Exception e) {
- System.err.println(
- "error, disabling captureEvent() for capture object");
+ System.err.println("error, disabling captureEvent()");
e.printStackTrace();
captureEventMethod = null;
}
@@ -1130,7 +1131,7 @@ public class Capture extends PImage implements PConstants {
* copy the frames to OpenGL.
*
* NOTE: This is not official API and may/will be removed at any time.
- *
+ *
* @param Object dest
*/
public void setBufferSink(Object sink) {
@@ -1141,7 +1142,7 @@ public class Capture extends PImage implements PConstants {
/**
* Sets the object to use as destination for the frames read from the stream.
- *
+ *
* NOTE: This is not official API and may/will be removed at any time.
*
* @param Object dest
@@ -1186,22 +1187,22 @@ public class Capture extends PImage implements PConstants {
throw new RuntimeException("Capture: provided sink object doesn't have "+
"a setBufferSource method.");
}
-
+
try {
- sinkDisposeMethod = bufferSink.getClass().getMethod("disposeSourceBuffer",
+ sinkDisposeMethod = bufferSink.getClass().getMethod("disposeSourceBuffer",
new Class[] { });
} catch (Exception e) {
throw new RuntimeException("Capture: provided sink object doesn't have " +
"a disposeSourceBuffer method.");
}
-
+
try {
- sinkGetMethod = bufferSink.getClass().getMethod("getBufferPixels",
+ sinkGetMethod = bufferSink.getClass().getMethod("getBufferPixels",
new Class[] { int[].class });
} catch (Exception e) {
throw new RuntimeException("Capture: provided sink object doesn't have " +
"a getBufferPixels method.");
- }
+ }
}
@@ -1212,8 +1213,8 @@ public class Capture extends PImage implements PConstants {
copyMask = "red_mask=(int)0xFF, green_mask=(int)0xFF00, blue_mask=(int)0xFF0000";
}
}
-
-
+
+
public synchronized void post() {
if (useBufferSink && sinkDisposeMethod != null) {
try {
@@ -1222,5 +1223,5 @@ public class Capture extends PImage implements PConstants {
e.printStackTrace();
}
}
- }
-}
\ No newline at end of file
+ }
+}
diff --git a/java/libraries/video/src/processing/video/Movie.java b/java/libraries/video/src/processing/video/Movie.java
index a98781059..958be1109 100644
--- a/java/libraries/video/src/processing/video/Movie.java
+++ b/java/libraries/video/src/processing/video/Movie.java
@@ -722,10 +722,19 @@ public class Movie extends PImage implements PConstants {
eventHandler = obj;
try {
- movieEventMethod = eventHandler.getClass().getMethod("movieEvent",
- new Class[] { Movie.class });
+ movieEventMethod = eventHandler.getClass().getMethod("movieEvent", Movie.class);
+ return;
} catch (Exception e) {
- // no such method, or an error.. which is fine, just ignore
+ // no such method, or an error... which is fine, just ignore
+ }
+
+ // movieEvent can alternatively be defined as receiving an Object, to allow
+ // Processing mode implementors to support the video library without linking
+ // to it at build-time.
+ try {
+ movieEventMethod = eventHandler.getClass().getMethod("movieEvent", Object.class);
+ } catch (Exception e) {
+ // no such method, or an error... which is fine, just ignore
}
}
@@ -808,20 +817,10 @@ public class Movie extends PImage implements PConstants {
}
if (playing) {
- // Creates a movieEvent.
- if (movieEventMethod != null) {
- try {
- movieEventMethod.invoke(eventHandler, new Object[] { this });
- } catch (Exception e) {
- System.err.println("error, disabling movieEvent() for " + filename);
- e.printStackTrace();
- movieEventMethod = null;
- }
- }
+ fireMovieEvent();
}
}
-
protected synchronized void invokeEvent(int w, int h, Buffer buffer) {
available = true;
bufWidth = w;
@@ -835,19 +834,22 @@ public class Movie extends PImage implements PConstants {
natBuffer = buffer;
if (playing) {
- // Creates a movieEvent.
- if (movieEventMethod != null) {
- try {
- movieEventMethod.invoke(eventHandler, new Object[] { this });
- } catch (Exception e) {
- System.err.println("error, disabling movieEvent() for " + filename);
- e.printStackTrace();
- movieEventMethod = null;
- }
- }
+ fireMovieEvent();
}
}
+ private void fireMovieEvent() {
+ // Creates a movieEvent.
+ if (movieEventMethod != null) {
+ try {
+ movieEventMethod.invoke(eventHandler, this);
+ } catch (Exception e) {
+ System.err.println("error, disabling movieEvent() for " + filename);
+ e.printStackTrace();
+ movieEventMethod = null;
+ }
+ }
+ }
protected void eosEvent() {
if (repeat) {
diff --git a/todo.txt b/todo.txt
index c69083e14..340c441f5 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,4 @@
-0227 pde
-X use mouseReleased() instead of mousePressed() in color selector
-X otherwise it registers the release as a click in the color window
-X https://github.com/processing/processing/issues/2514
+0228 pde
medium
@@ -26,8 +23,6 @@ _ add font fixes to the rest of the API
_ https://github.com/processing/processing/commit/eaff673d173b2d27f276cf5c59e3abf6c0fab86b
_ g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
_ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-_ dataPath() not working when app is not run from app dir on Linux
-_ https://github.com/processing/processing/issues/2195
_ should default to the local Java on Windows and Linux
_ have export apps default to the local JRE
_ Linux is probably using the system JRE if available