mirror of
https://github.com/processing/processing4.git
synced 2026-02-15 19:35:37 +01:00
updated for processing 2.1.2
This commit is contained in:
@@ -38,56 +38,62 @@ import processing.core.PApplet;
|
||||
* <p/>
|
||||
* After some further digging, this code in fact appears to be a modified
|
||||
* version of Jason Pell's GPLed "Java Beautifier" class found
|
||||
* <a href="http://www.geocities.com/jasonpell/programs.html">here</a>.
|
||||
* Which is itself based on code from Van Di-Han Ho from
|
||||
* <a href="http://www.geocities.com/~starkville/vancbj_idx.html">here</a>.
|
||||
* <a href="http://web.archive.org/web/20091018220353/http://geocities.com/jasonpell/programs.html">here</a>,
|
||||
* which is itself based on code from Van Di-Han Ho from
|
||||
* <a href="http://web.archive.org/web/20091027043013/http://www.geocities.com/~starkville/vancbj_idx.html">here</a>.
|
||||
* [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<Boolean> castFlags = new Stack<Boolean>();
|
||||
|
||||
|
||||
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 = 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,9 +171,25 @@ public class AutoFormat implements Formatter {
|
||||
}
|
||||
a_flg = false;
|
||||
}
|
||||
if (elseFlag) {
|
||||
if (lastNonSpaceChar() == '}') {
|
||||
trimRight(result);
|
||||
result.append(' ');
|
||||
}
|
||||
elseFlag = false;
|
||||
}
|
||||
result.append(buf);
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
|
||||
private char lastNonSpaceChar() {
|
||||
for (int i = result.length() - 1; i >= 0; i--) {
|
||||
char c_i = result.charAt(i);
|
||||
if (c_i != ' ' && c_i != '\n') return c_i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private void writeIndentedComment() {
|
||||
@@ -170,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);
|
||||
@@ -187,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;
|
||||
@@ -208,7 +233,7 @@ public class AutoFormat implements Formatter {
|
||||
}
|
||||
final int spaces = tabs * indentValue;
|
||||
for (int k = 0; k < spaces; k++) {
|
||||
result.append(" ");
|
||||
result.append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,10 +246,7 @@ public class AutoFormat implements Formatter {
|
||||
}
|
||||
|
||||
|
||||
private char lastNonWhitespace = 0;
|
||||
|
||||
|
||||
private int prev() {
|
||||
private int getLastNonWhitespace() {
|
||||
return lastNonWhitespace;
|
||||
}
|
||||
|
||||
@@ -239,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];
|
||||
@@ -273,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;
|
||||
}
|
||||
@@ -298,7 +318,7 @@ public class AutoFormat implements Formatter {
|
||||
c = peek();
|
||||
if (c == '\n') {
|
||||
// eat it
|
||||
next();
|
||||
nextChar();
|
||||
// lineNumber++;
|
||||
tabs = savedTabs;
|
||||
return true;
|
||||
@@ -327,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];
|
||||
@@ -352,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);
|
||||
@@ -371,15 +392,12 @@ public class AutoFormat implements Formatter {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (lookup("else")) {
|
||||
gotelse();
|
||||
elseFlag = lookup("else");
|
||||
if (elseFlag) {
|
||||
gotElse();
|
||||
if ((!s_flag) || buf.length() > 0) {
|
||||
buf.append(c);
|
||||
}
|
||||
// // issue https://github.com/processing/processing/issues/364
|
||||
// s_flag = false;
|
||||
// trimRight(result);
|
||||
// result.append(" ");
|
||||
|
||||
writeIndentedLine();
|
||||
s_flag = false;
|
||||
@@ -395,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);
|
||||
@@ -409,18 +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 '{':
|
||||
if (lookup("else")) {
|
||||
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);
|
||||
@@ -440,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;
|
||||
@@ -475,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) {
|
||||
@@ -497,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';
|
||||
@@ -519,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;
|
||||
@@ -541,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();
|
||||
@@ -570,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);
|
||||
}
|
||||
@@ -599,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]++;
|
||||
@@ -630,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;
|
||||
|
||||
@@ -48,6 +48,7 @@ public class Commander implements RunnerListener {
|
||||
static final String forceArg = "--force";
|
||||
static final String outputArg = "--output=";
|
||||
static final String exportApplicationArg = "--export";
|
||||
static final String noJavaArg = "--no-java";
|
||||
static final String platformArg = "--platform=";
|
||||
static final String bitsArg = "--bits=";
|
||||
// static final String preferencesArg = "--preferences=";
|
||||
@@ -61,38 +62,19 @@ public class Commander implements RunnerListener {
|
||||
static final int EXPORT = 4;
|
||||
|
||||
Sketch sketch;
|
||||
|
||||
|
||||
PrintStream systemOut;
|
||||
PrintStream systemErr;
|
||||
|
||||
|
||||
static public void main(String[] args) {
|
||||
/*
|
||||
if (args == null || args.length == 0) {
|
||||
// System.out.println(System.getProperty("user.dir"));
|
||||
args = new String[] {
|
||||
"--export",
|
||||
// "--build",
|
||||
// "--run",
|
||||
// "--present",
|
||||
"--force",
|
||||
// "--platform=windows",
|
||||
"--platform=macosx",
|
||||
"--bits=64",
|
||||
"--sketch=/Users/fry/coconut/processing/java/examples/Basics/Lights/Directional",
|
||||
// "--sketch=/Users/fry/coconut/sketchbook/sketchbook_libraries_test",
|
||||
"--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();
|
||||
|
||||
|
||||
// launch command line handler
|
||||
new Commander(args);
|
||||
}
|
||||
@@ -107,20 +89,25 @@ public class Commander implements RunnerListener {
|
||||
boolean force = false; // replace that no good output folder
|
||||
// String preferencesPath = null;
|
||||
int platform = PApplet.platform; // default to this platform
|
||||
int platformBits = 0;
|
||||
// int platformBits = 0;
|
||||
int platformBits = Base.getNativeBits();
|
||||
int task = HELP;
|
||||
boolean embedJava = true;
|
||||
|
||||
// Turns out the output goes as MacRoman or something else useless.
|
||||
// http://code.google.com/p/processing/issues/detail?id=1418
|
||||
try {
|
||||
systemOut = new PrintStream(System.out, true, "UTF-8");
|
||||
systemErr = new PrintStream(System.err, true, "UTF-8");
|
||||
|
||||
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
// File preferencesFile = Base.getSettingsFile("preferences.txt");
|
||||
// System.out.println("Preferences file at " + preferencesFile.getAbsolutePath());
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg.length() == 0) {
|
||||
// ignore it, just the crappy shell script
|
||||
@@ -146,23 +133,28 @@ public class Commander implements RunnerListener {
|
||||
} else if (arg.equals(exportApplicationArg)) {
|
||||
task = EXPORT;
|
||||
|
||||
} else if (arg.equals(noJavaArg)) {
|
||||
embedJava = false;
|
||||
|
||||
} else if (arg.startsWith(platformArg)) {
|
||||
String platformStr = arg.substring(platformArg.length());
|
||||
platform = Base.getPlatformIndex(platformStr);
|
||||
if (platform == -1) {
|
||||
complainAndQuit(platformStr + " should instead be " +
|
||||
"'windows', 'macosx', or 'linux'.", true);
|
||||
}
|
||||
complainAndQuit("The --platform option has been removed from Processing 2.1.", false);
|
||||
// String platformStr = arg.substring(platformArg.length());
|
||||
// platform = Base.getPlatformIndex(platformStr);
|
||||
// if (platform == -1) {
|
||||
// complainAndQuit(platformStr + " should instead be " +
|
||||
// "'windows', 'macosx', or 'linux'.", true);
|
||||
// }
|
||||
|
||||
} 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, true);
|
||||
}
|
||||
complainAndQuit("The --bits option has been removed from Processing 2.1.", false);
|
||||
// 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, true);
|
||||
// }
|
||||
|
||||
} else if (arg.startsWith(sketchArg)) {
|
||||
sketchPath = arg.substring(sketchArg.length());
|
||||
@@ -212,7 +204,7 @@ public class Commander implements RunnerListener {
|
||||
Base.removeDir(outputFolder);
|
||||
} else {
|
||||
complainAndQuit("The output folder already exists. " +
|
||||
"Use --force to remove it.", false);
|
||||
"Use --force to remove it.", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,11 +265,11 @@ public class Commander implements RunnerListener {
|
||||
// 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.", true);
|
||||
}
|
||||
success = build.exportApplication(outputFolder, platform, platformBits);
|
||||
// if (platformBits == 0 &&
|
||||
// Library.hasMultipleArch(platform, build.getImportedLibraries())) {
|
||||
// complainAndQuit("This sketch can be exported for 32- or 64-bit, please specify one.", true);
|
||||
// }
|
||||
success = build.exportApplication(outputFolder, platform, platformBits, embedJava);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,6 +281,7 @@ public class Commander implements RunnerListener {
|
||||
|
||||
} catch (SketchException re) {
|
||||
statusError(re);
|
||||
System.exit(1);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -316,15 +309,18 @@ public class Commander implements RunnerListener {
|
||||
if (codeIndex != -1) {
|
||||
// format the runner exception like emacs
|
||||
//blah.java:2:10:2:13: Syntax Error: This is a big error message
|
||||
// Emacs doesn't like the double line thing coming from Java
|
||||
// https://github.com/processing/processing/issues/2158
|
||||
String filename = sketch.getCode(codeIndex).getFileName();
|
||||
int line = re.getCodeLine() + 1;
|
||||
int column = re.getCodeColumn() + 1;
|
||||
//if (column == -1) column = 0;
|
||||
// TODO if column not specified, should just select the whole line.
|
||||
// But what's the correct syntax for that?
|
||||
systemErr.println(filename + ":" +
|
||||
line + ":" + column + ":" +
|
||||
line + ":" + column + ":" + " " + re.getMessage());
|
||||
|
||||
|
||||
} else { // no line number, pass the trace along to the user
|
||||
exception.printStackTrace();
|
||||
}
|
||||
@@ -363,11 +359,12 @@ public class Commander implements RunnerListener {
|
||||
out.println("--present Preprocess, compile, and run a sketch full screen.");
|
||||
out.println();
|
||||
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("--no-java Do not embed Java. Use at your own risk!");
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -391,4 +388,4 @@ public class Commander implements RunnerListener {
|
||||
public boolean isHalted() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,15 @@ import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DefaultLogger;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.ProjectHelper;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.exec.ProcessHelper;
|
||||
import processing.core.*;
|
||||
import processing.data.XML;
|
||||
import processing.mode.java.preproc.*;
|
||||
|
||||
// Would you believe there's a java.lang.Compiler class? I wouldn't.
|
||||
@@ -397,7 +404,7 @@ public class JavaBuild {
|
||||
throw new SketchException(ex.toString());
|
||||
}
|
||||
|
||||
// grab the imports from the code just preproc'd
|
||||
// grab the imports from the code just preprocessed
|
||||
|
||||
importedLibraries = new ArrayList<Library>();
|
||||
Library core = mode.getCoreLibrary();
|
||||
@@ -408,10 +415,21 @@ public class JavaBuild {
|
||||
|
||||
// System.out.println("extra imports: " + result.extraImports);
|
||||
for (String item : result.extraImports) {
|
||||
// System.out.println("item = '" + item + "'");
|
||||
// remove things up to the last dot
|
||||
int dot = item.lastIndexOf('.');
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=1145
|
||||
String entry = (dot == -1) ? item : item.substring(0, dot);
|
||||
// System.out.print(entry + " => ");
|
||||
|
||||
if (item.startsWith("static ")) {
|
||||
// import static - https://github.com/processing/processing/issues/8
|
||||
// Remove more stuff.
|
||||
int dot2 = item.lastIndexOf('.');
|
||||
entry = entry.substring(7, (dot2 == -1) ? entry.length() : dot2);
|
||||
// System.out.println(entry);
|
||||
}
|
||||
|
||||
// System.out.println("library searching for " + entry);
|
||||
Library library = mode.getLibrary(entry);
|
||||
// System.out.println(" found " + library);
|
||||
@@ -427,7 +445,7 @@ public class JavaBuild {
|
||||
// If someone insists on unnecessarily repeating the code folder
|
||||
// import, don't show an error for it.
|
||||
if (codeFolderPackages != null) {
|
||||
String itemPkg = item.substring(0, item.lastIndexOf('.'));
|
||||
String itemPkg = entry;
|
||||
for (String pkg : codeFolderPackages) {
|
||||
if (pkg.equals(itemPkg)) {
|
||||
found = true;
|
||||
@@ -435,7 +453,7 @@ public class JavaBuild {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ignorableImport(item)) {
|
||||
if (ignorableImport(entry + '.')) {
|
||||
found = true;
|
||||
}
|
||||
if (!found) {
|
||||
@@ -531,6 +549,8 @@ public class JavaBuild {
|
||||
if (pkg.startsWith("processing.data.")) return true;
|
||||
if (pkg.startsWith("processing.event.")) return true;
|
||||
if (pkg.startsWith("processing.opengl.")) return true;
|
||||
|
||||
// if (pkg.startsWith("com.jogamp.")) return true;
|
||||
|
||||
// // ignore core, data, and opengl packages
|
||||
// String[] coreImports = preprocessor.getCoreImports();
|
||||
@@ -1093,43 +1113,68 @@ public class JavaBuild {
|
||||
File folder = null;
|
||||
for (String platformName : PConstants.platformNames) {
|
||||
int platform = Base.getPlatformIndex(platformName);
|
||||
|
||||
// Can only embed Java on the native platform
|
||||
boolean embedJava = (platform == PApplet.platform) &&
|
||||
Preferences.getBoolean("export.application.embed_java");
|
||||
|
||||
if (Preferences.getBoolean("export.application.platform." + platformName)) {
|
||||
if (Library.hasMultipleArch(platform, importedLibraries)) {
|
||||
// export the 32-bit version
|
||||
folder = new File(sketch.getFolder(), "application." + platformName + "32");
|
||||
if (!exportApplication(folder, platform, 32)) {
|
||||
if (!exportApplication(folder, platform, 32, embedJava && Base.getNativeBits() == 32)) {
|
||||
return false;
|
||||
}
|
||||
// export the 64-bit version
|
||||
folder = new File(sketch.getFolder(), "application." + platformName + "64");
|
||||
if (!exportApplication(folder, platform, 64)) {
|
||||
if (!exportApplication(folder, platform, 64, embedJava && Base.getNativeBits() == 64)) {
|
||||
return false;
|
||||
}
|
||||
} else { // just make a single one for this platform
|
||||
folder = new File(sketch.getFolder(), "application." + platformName);
|
||||
if (!exportApplication(folder, platform, 0)) {
|
||||
if (!exportApplication(folder, platform, 0, embedJava)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
File folder = null;
|
||||
String platformName = Base.getPlatformName();
|
||||
boolean embedJava = Preferences.getBoolean("export.application.embed_java");
|
||||
if (Library.hasMultipleArch(PApplet.platform, importedLibraries)) {
|
||||
if (Base.getNativeBits() == 32) {
|
||||
// export the 32-bit version
|
||||
folder = new File(sketch.getFolder(), "application." + platformName + "32");
|
||||
if (!exportApplication(folder, PApplet.platform, 32, embedJava)) {
|
||||
return false;
|
||||
}
|
||||
} else if (Base.getNativeBits() == 64) {
|
||||
// export the 64-bit version
|
||||
folder = new File(sketch.getFolder(), "application." + platformName + "64");
|
||||
if (!exportApplication(folder, PApplet.platform, 64, embedJava)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else { // just make a single one for this platform
|
||||
folder = new File(sketch.getFolder(), "application." + platformName);
|
||||
if (!exportApplication(folder, PApplet.platform, 0, embedJava)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return true; // all good
|
||||
}
|
||||
|
||||
|
||||
// public boolean exportApplication(String destPath,
|
||||
// String platformName,
|
||||
// int exportBits) throws IOException, RunnerException {
|
||||
// return exportApplication(destPath, Base.getPlatformIndex(platformName), exportBits);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Export to application without GUI. Also called by the Commander.
|
||||
*/
|
||||
protected boolean exportApplication(File destFolder,
|
||||
int exportPlatform,
|
||||
int exportBits) throws IOException, SketchException {
|
||||
int exportBits,
|
||||
boolean embedJava) 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
|
||||
@@ -1160,13 +1205,53 @@ public class JavaBuild {
|
||||
/// on macosx, need to copy .app skeleton since that's
|
||||
/// also where the jar files will be placed
|
||||
File dotAppFolder = null;
|
||||
String jvmRuntime = "";
|
||||
String jdkPath = null;
|
||||
if (exportPlatform == PConstants.MACOSX) {
|
||||
dotAppFolder = new File(destFolder, sketch.getName() + ".app");
|
||||
// String APP_SKELETON = "skeleton.app";
|
||||
//File dotAppSkeleton = new File(folder, APP_SKELETON);
|
||||
File dotAppSkeleton = mode.getContentFile("application/template.app");
|
||||
Base.copyDir(dotAppSkeleton, dotAppFolder);
|
||||
|
||||
File contentsOrig = new File(Base.getJavaHome(), "../../../../..");
|
||||
|
||||
if (embedJava) {
|
||||
File jdkFolder = new File(Base.getJavaHome(), "../../..");
|
||||
String jdkFolderName = jdkFolder.getCanonicalFile().getName();
|
||||
jvmRuntime = "<key>JVMRuntime</key>\n <string>" + jdkFolderName + "</string>";
|
||||
jdkPath = new File(dotAppFolder, "Contents/PlugIns/" + jdkFolderName + ".jdk").getAbsolutePath();
|
||||
}
|
||||
|
||||
File contentsFolder = new File(dotAppFolder, "Contents");
|
||||
contentsFolder.mkdirs();
|
||||
|
||||
// Info.plist will be written later
|
||||
|
||||
// set the jar folder to a different location than windows/linux
|
||||
//jarFolder = new File(dotAppFolder, "Contents/Resources/Java");
|
||||
jarFolder = new File(contentsFolder, "Java");
|
||||
|
||||
File macosFolder = new File(contentsFolder, "MacOS");
|
||||
macosFolder.mkdirs();
|
||||
Base.copyFile(new File(contentsOrig, "MacOS/Processing"),
|
||||
new File(contentsFolder, "MacOS/" + sketch.getName()));
|
||||
|
||||
File pkgInfo = new File(contentsFolder, "PkgInfo");
|
||||
PrintWriter writer = PApplet.createWriter(pkgInfo);
|
||||
writer.println("APPL????");
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
// Use faster(?) native copy here (also to do sym links)
|
||||
if (embedJava) {
|
||||
Base.copyDirNative(new File(contentsOrig, "PlugIns"),
|
||||
new File(contentsFolder, "PlugIns"));
|
||||
}
|
||||
|
||||
File resourcesFolder = new File(contentsFolder, "Resources");
|
||||
Base.copyDir(new File(contentsOrig, "Resources/en.lproj"),
|
||||
new File(resourcesFolder, "en.lproj"));
|
||||
Base.copyFile(mode.getContentFile("application/sketch.icns"),
|
||||
new File(resourcesFolder, "sketch.icns"));
|
||||
|
||||
/*
|
||||
String stubName = "Contents/MacOS/JavaApplicationStub";
|
||||
// need to set the stub to executable
|
||||
// will work on osx or *nix, but just dies on windows, oh well..
|
||||
@@ -1189,17 +1274,25 @@ public class JavaBuild {
|
||||
String stubPath = stubFile.getAbsolutePath();
|
||||
Runtime.getRuntime().exec(new String[] { "chmod", "+x", stubPath });
|
||||
}
|
||||
|
||||
// set the jar folder to a different location than windows/linux
|
||||
jarFolder = new File(dotAppFolder, "Contents/Resources/Java");
|
||||
*/
|
||||
} else if (exportPlatform == PConstants.LINUX) {
|
||||
if (embedJava) {
|
||||
Base.copyDirNative(Base.getJavaHome(), new File(destFolder, "java"));
|
||||
}
|
||||
|
||||
} else if (exportPlatform == PConstants.WINDOWS) {
|
||||
if (embedJava) {
|
||||
Base.copyDir(Base.getJavaHome(), new File(destFolder, "java"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// make the jar folder (windows and linux)
|
||||
/// make the jar folder (all platforms)
|
||||
|
||||
if (!jarFolder.exists()) jarFolder.mkdirs();
|
||||
|
||||
|
||||
/*
|
||||
/// on windows, copy the exe file
|
||||
|
||||
if (exportPlatform == PConstants.WINDOWS) {
|
||||
@@ -1208,7 +1301,8 @@ public class JavaBuild {
|
||||
File batFile = new File(destFolder, sketch.getName() + ".bat");
|
||||
PrintWriter writer = PApplet.createWriter(batFile);
|
||||
writer.println("@echo off");
|
||||
writer.println("java -Djava.ext.dirs=lib -Djava.library.path=lib " + sketch.getName());
|
||||
String javaPath = embedJava ? ".\\java\\bin\\java.exe" : "java";
|
||||
writer.println(javaPath + " -Djna.nosys=true -Djava.ext.dirs=lib -Djava.library.path=lib " + sketch.getName());
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} else {
|
||||
@@ -1216,8 +1310,9 @@ public class JavaBuild {
|
||||
new File(destFolder, sketch.getName() + ".exe"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// start copying all jar files
|
||||
|
||||
Vector<String> jarListVector = new Vector<String>();
|
||||
@@ -1271,7 +1366,6 @@ public class JavaBuild {
|
||||
String includes = Base.contentsToClassPath(sketch.getCodeFolder());
|
||||
// Use tokens to get rid of extra blanks, which causes huge exports
|
||||
String[] codeList = PApplet.splitTokens(includes, File.pathSeparator);
|
||||
// String cp = "";
|
||||
for (int i = 0; i < codeList.length; i++) {
|
||||
if (codeList[i].toLowerCase().endsWith(".jar") ||
|
||||
codeList[i].toLowerCase().endsWith(".zip")) {
|
||||
@@ -1283,7 +1377,6 @@ public class JavaBuild {
|
||||
// cp += codeList[i] + File.pathSeparator;
|
||||
}
|
||||
}
|
||||
// packClassPathIntoZipFile(cp, zos, zipFileContents); // this was double adding the code folder prior to 2.0a2
|
||||
}
|
||||
|
||||
zos.flush();
|
||||
@@ -1292,15 +1385,6 @@ public class JavaBuild {
|
||||
jarListVector.add(sketch.getName() + ".jar");
|
||||
|
||||
|
||||
// /// add core.jar to the jar destination folder
|
||||
//
|
||||
// File bagelJar = Base.isMacOS() ?
|
||||
// Base.getContentFile("core.jar") :
|
||||
// Base.getContentFile("lib/core.jar");
|
||||
// Base.copyFile(bagelJar, new File(jarFolder, "core.jar"));
|
||||
// jarListVector.add("core.jar");
|
||||
|
||||
|
||||
/// add contents of 'library' folders to the export
|
||||
for (Library library : importedLibraries) {
|
||||
// add each item from the library folder / export list to the output
|
||||
@@ -1313,38 +1397,13 @@ public class JavaBuild {
|
||||
"a big fat lie and does not exist.");
|
||||
|
||||
} else if (exportFile.isDirectory()) {
|
||||
//System.err.println("Ignoring sub-folder \"" + exportList[i] + "\"");
|
||||
// if (exportPlatform == PConstants.MACOSX) {
|
||||
// // For OS X, copy subfolders to Contents/Resources/Java
|
||||
Base.copyDir(exportFile, new File(jarFolder, exportName));
|
||||
// } else {
|
||||
// // For other platforms, just copy the folder to the same directory
|
||||
// // as the application.
|
||||
// Base.copyDir(exportFile, new File(destFolder, exportName));
|
||||
// }
|
||||
|
||||
} else if (exportName.toLowerCase().endsWith(".zip") ||
|
||||
exportName.toLowerCase().endsWith(".jar")) {
|
||||
Base.copyFile(exportFile, new File(jarFolder, exportName));
|
||||
jarListVector.add(exportName);
|
||||
|
||||
// old style, prior to 2.0a2
|
||||
// } else if ((exportPlatform == PConstants.MACOSX) &&
|
||||
// (exportFile.getName().toLowerCase().endsWith(".jnilib"))) {
|
||||
// // jnilib files can be placed in Contents/Resources/Java
|
||||
// Base.copyFile(exportFile, new File(jarFolder, exportName));
|
||||
//
|
||||
// } else {
|
||||
// // copy the file to the main directory.. prolly a .dll or something
|
||||
// Base.copyFile(exportFile, new File(destFolder, exportName));
|
||||
// }
|
||||
|
||||
// first 2.0a2 attempt, until below...
|
||||
// } else if (exportPlatform == PConstants.MACOSX) {
|
||||
// Base.copyFile(exportFile, new File(jarFolder, exportName));
|
||||
//
|
||||
// } else {
|
||||
// Base.copyFile(exportFile, new File(destFolder, exportName));
|
||||
} else {
|
||||
// Starting with 2.0a2 put extra export files (DLLs, plugins folder,
|
||||
// anything else for libraries) inside lib or Contents/Resources/Java
|
||||
@@ -1380,31 +1439,30 @@ public class JavaBuild {
|
||||
|
||||
/// figure out run options for the VM
|
||||
|
||||
String runOptions = Preferences.get("run.options");
|
||||
List<String> runOptions = new ArrayList<String>();
|
||||
if (Preferences.getBoolean("run.options.memory")) {
|
||||
runOptions += " -Xms" +
|
||||
Preferences.get("run.options.memory.initial") + "m";
|
||||
runOptions += " -Xmx" +
|
||||
Preferences.get("run.options.memory.maximum") + "m";
|
||||
runOptions.add("-Xms" + Preferences.get("run.options.memory.initial") + "m");
|
||||
runOptions.add("-Xmx" + Preferences.get("run.options.memory.maximum") + "m");
|
||||
}
|
||||
// if (exportPlatform == PConstants.MACOSX) {
|
||||
// // If no bits specified (libs are all universal, or no native libs)
|
||||
// // then exportBits will be 0, and can be controlled via "Get Info".
|
||||
// // Otherwise, need to specify the bits as a VM option.
|
||||
// if (exportBits == 32) {
|
||||
// runOptions += " -d32";
|
||||
// } else if (exportBits == 64) {
|
||||
// runOptions += " -d64";
|
||||
// }
|
||||
// }
|
||||
// https://github.com/processing/processing/issues/2239
|
||||
runOptions.add("-Djna.nosys=true");
|
||||
|
||||
|
||||
/// macosx: write out Info.plist (template for classpath, etc)
|
||||
|
||||
if (exportPlatform == PConstants.MACOSX) {
|
||||
String PLIST_TEMPLATE = "template.plist";
|
||||
StringBuilder runOptionsXML = new StringBuilder();
|
||||
for (String opt : runOptions) {
|
||||
runOptionsXML.append(" <string>");
|
||||
runOptionsXML.append(opt);
|
||||
runOptionsXML.append("</string>");
|
||||
runOptionsXML.append('\n');
|
||||
}
|
||||
|
||||
String PLIST_TEMPLATE = "Info.plist.tmpl";
|
||||
File plistTemplate = new File(sketch.getFolder(), PLIST_TEMPLATE);
|
||||
if (!plistTemplate.exists()) {
|
||||
plistTemplate = mode.getContentFile("application/template.plist");
|
||||
plistTemplate = mode.getContentFile("application/" + PLIST_TEMPLATE);
|
||||
}
|
||||
File plistFile = new File(dotAppFolder, "Contents/Info.plist");
|
||||
PrintWriter pw = PApplet.createWriter(plistFile);
|
||||
@@ -1414,33 +1472,22 @@ public class JavaBuild {
|
||||
if (lines[i].indexOf("@@") != -1) {
|
||||
StringBuffer sb = new StringBuffer(lines[i]);
|
||||
int index = 0;
|
||||
while ((index = sb.indexOf("@@vmoptions@@")) != -1) {
|
||||
sb.replace(index, index + "@@vmoptions@@".length(),
|
||||
runOptions);
|
||||
while ((index = sb.indexOf("@@jvm_runtime@@")) != -1) {
|
||||
sb.replace(index, index + "@@jvm_runtime@@".length(),
|
||||
jvmRuntime);
|
||||
}
|
||||
while ((index = sb.indexOf("@@jvm_options_list@@")) != -1) {
|
||||
sb.replace(index, index + "@@jvm_options_list@@".length(),
|
||||
runOptionsXML.toString());
|
||||
}
|
||||
while ((index = sb.indexOf("@@sketch@@")) != -1) {
|
||||
sb.replace(index, index + "@@sketch@@".length(),
|
||||
sketch.getName());
|
||||
}
|
||||
while ((index = sb.indexOf("@@classpath@@")) != -1) {
|
||||
sb.replace(index, index + "@@classpath@@".length(),
|
||||
exportClassPath.toString());
|
||||
}
|
||||
while ((index = sb.indexOf("@@lsuipresentationmode@@")) != -1) {
|
||||
sb.replace(index, index + "@@lsuipresentationmode@@".length(),
|
||||
Preferences.getBoolean("export.application.fullscreen") ? "4" : "0");
|
||||
}
|
||||
while ((index = sb.indexOf("@@lsarchitecturepriority@@")) != -1) {
|
||||
// More about this mess: http://support.apple.com/kb/TS2827
|
||||
// First default to exportBits == 0 case
|
||||
String arch = "<string>x86_64</string>\n <string>i386</string>";
|
||||
if (exportBits == 32) {
|
||||
arch = "<string>i386</string>";
|
||||
} else if (exportBits == 64) {
|
||||
arch = "<string>x86_64</string>";
|
||||
}
|
||||
sb.replace(index, index + "@@lsarchitecturepriority@@".length(), arch);
|
||||
}
|
||||
|
||||
lines[i] = sb.toString();
|
||||
}
|
||||
@@ -1450,17 +1497,93 @@ public class JavaBuild {
|
||||
pw.flush();
|
||||
pw.close();
|
||||
|
||||
// attempt to code sign if the Xcode tools appear to be installed
|
||||
if (Base.isMacOS() && new File("/usr/bin/codesign_allocate").exists()) {
|
||||
if (embedJava) {
|
||||
ProcessHelper.ffs("codesign", "--force", "--sign", "-", jdkPath);
|
||||
}
|
||||
String appPath = dotAppFolder.getAbsolutePath();
|
||||
ProcessHelper.ffs("codesign", "--force", "--sign", "-", appPath);
|
||||
}
|
||||
|
||||
} else if (exportPlatform == PConstants.WINDOWS) {
|
||||
File argsFile = new File(destFolder + "/lib/args.txt");
|
||||
PrintWriter pw = PApplet.createWriter(argsFile);
|
||||
File buildFile = new File(destFolder, "launch4j-build.xml");
|
||||
File configFile = new File(destFolder, "launch4j-config.xml");
|
||||
|
||||
// Since this is only on Windows, make sure we use Windows CRLF
|
||||
pw.print(runOptions + "\r\n");
|
||||
pw.print(sketch.getName() + "\r\n");
|
||||
pw.print(exportClassPath);
|
||||
XML project = new XML("project");
|
||||
XML target = project.addChild("target");
|
||||
target.setString("name", "windows");
|
||||
|
||||
XML taskdef = target.addChild("taskdef");
|
||||
taskdef.setString("name", "launch4j");
|
||||
taskdef.setString("classname", "net.sf.launch4j.ant.Launch4jTask");
|
||||
String launchPath = mode.getContentFile("application/launch4j").getAbsolutePath();
|
||||
taskdef.setString("classpath", launchPath + "/launch4j.jar:" + launchPath + "/lib/xstream.jar");
|
||||
|
||||
XML launch4j = target.addChild("launch4j");
|
||||
// not all launch4j options are available when embedded inside the ant
|
||||
// build file (i.e. the icon param doesn't work), so use a config file
|
||||
//<launch4j configFile="windows/work/config.xml" />
|
||||
launch4j.setString("configFile", configFile.getAbsolutePath());
|
||||
|
||||
XML config = new XML("launch4jConfig");
|
||||
config.addChild("headerType").setContent("gui");
|
||||
config.addChild("dontWrapJar").setContent("true");
|
||||
config.addChild("downloadUrl").setContent("http://java.com/download");
|
||||
|
||||
File exeFile = new File(destFolder, sketch.getName() + ".exe");
|
||||
config.addChild("outfile").setContent(exeFile.getAbsolutePath());
|
||||
|
||||
File iconFile = mode.getContentFile("application/sketch.ico");
|
||||
config.addChild("icon").setContent(iconFile.getAbsolutePath());
|
||||
|
||||
pw.flush();
|
||||
pw.close();
|
||||
XML clazzPath = config.addChild("classPath");
|
||||
clazzPath.addChild("mainClass").setContent(sketch.getName());
|
||||
for (String jarName : jarList) {
|
||||
clazzPath.addChild("cp").setContent("lib/" + jarName);
|
||||
}
|
||||
XML jre = config.addChild("jre");
|
||||
if (embedJava) {
|
||||
jre.addChild("path").setContent("java");
|
||||
}
|
||||
jre.addChild("minVersion").setContent("1.7.0_40");
|
||||
for (String opt : runOptions) {
|
||||
jre.addChild("opt").setContent(opt);
|
||||
}
|
||||
|
||||
/*
|
||||
XML config = launch4j.addChild("config");
|
||||
config.setString("headerType", "gui");
|
||||
File exeFile = new File(destFolder, sketch.getName() + ".exe");
|
||||
config.setString("outfile", exeFile.getAbsolutePath());
|
||||
config.setString("dontWrapJar", "true");
|
||||
config.setString("jarPath", "lib\\" + jarList[0]);
|
||||
|
||||
File iconFile = mode.getContentFile("application/sketch.ico");
|
||||
config.addChild("icon").setContent(iconFile.getAbsolutePath());
|
||||
|
||||
XML clazzPath = config.addChild("classPath");
|
||||
clazzPath.setString("mainClass", sketch.getName());
|
||||
for (int i = 1; i < jarList.length; i++) {
|
||||
String jarName = jarList[i];
|
||||
clazzPath.addChild("cp").setContent("lib\\" + jarName);
|
||||
}
|
||||
XML jre = config.addChild("jre");
|
||||
jre.setString("minVersion", "1.7.0_40");
|
||||
//PApplet.join(runOptions.toArray(new String[0]), " ")
|
||||
for (String opt : runOptions) {
|
||||
jre.addChild("opt").setContent(opt);
|
||||
}
|
||||
*/
|
||||
|
||||
config.save(configFile);
|
||||
project.save(buildFile);
|
||||
if (!buildWindowsLauncher(buildFile, "windows")) {
|
||||
// don't delete the build file, might be useful for debugging
|
||||
return false;
|
||||
}
|
||||
configFile.delete();
|
||||
buildFile.delete();
|
||||
|
||||
} else {
|
||||
File shellScript = new File(destFolder, sketch.getName());
|
||||
@@ -1473,7 +1596,13 @@ public class JavaBuild {
|
||||
pw.print("APPDIR=$(dirname \"$0\")\n"); // more posix compliant
|
||||
// another fix for bug #234, LD_LIBRARY_PATH ignored on some platforms
|
||||
//ps.print("LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$APPDIR\n");
|
||||
pw.print("java " + Preferences.get("run.options") +
|
||||
if (embedJava) {
|
||||
// https://github.com/processing/processing/issues/2349
|
||||
pw.print("$APPDIR/java/bin/");
|
||||
}
|
||||
String runOptionsStr =
|
||||
PApplet.join(runOptions.toArray(new String[0]), " ");
|
||||
pw.print("java " + runOptionsStr +
|
||||
" -Djava.library.path=\"$APPDIR:$APPDIR/lib\"" +
|
||||
" -cp \"" + exportClassPath + "\"" +
|
||||
" " + sketch.getName() + " \"$@\"\n");
|
||||
@@ -1512,23 +1641,66 @@ public class JavaBuild {
|
||||
}
|
||||
|
||||
|
||||
/// remove the .class files from the export folder.
|
||||
// for (File file : classFiles) {
|
||||
// if (!file.delete()) {
|
||||
// Base.showWarning("Could not delete",
|
||||
// file.getName() + " could not \n" +
|
||||
// "be deleted from the applet folder. \n" +
|
||||
// "You'll need to remove it by hand.", null);
|
||||
// }
|
||||
// }
|
||||
// these will now be removed automatically via the temp folder deleteOnExit()
|
||||
|
||||
|
||||
/// goodbye
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the launch4j build.xml file through ant to create the exe.
|
||||
* Most of this code was lifted from Android mode.
|
||||
*/
|
||||
protected boolean buildWindowsLauncher(File buildFile, String target) {
|
||||
Project p = new Project();
|
||||
String path = buildFile.getAbsolutePath().replace('\\', '/');
|
||||
p.setUserProperty("ant.file", path);
|
||||
|
||||
// deals with a problem where javac error messages weren't coming through
|
||||
p.setUserProperty("build.compiler", "extJavac");
|
||||
|
||||
// too chatty
|
||||
/*
|
||||
// try to spew something useful to the console
|
||||
final DefaultLogger consoleLogger = new DefaultLogger();
|
||||
consoleLogger.setErrorPrintStream(System.err);
|
||||
consoleLogger.setOutputPrintStream(System.out);
|
||||
// WARN, INFO, VERBOSE, DEBUG
|
||||
consoleLogger.setMessageOutputLevel(Project.MSG_ERR);
|
||||
p.addBuildListener(consoleLogger);
|
||||
*/
|
||||
|
||||
DefaultLogger errorLogger = new DefaultLogger();
|
||||
ByteArrayOutputStream errb = new ByteArrayOutputStream();
|
||||
PrintStream errp = new PrintStream(errb);
|
||||
errorLogger.setErrorPrintStream(errp);
|
||||
ByteArrayOutputStream outb = new ByteArrayOutputStream();
|
||||
PrintStream outp = new PrintStream(outb);
|
||||
errorLogger.setOutputPrintStream(outp);
|
||||
errorLogger.setMessageOutputLevel(Project.MSG_INFO);
|
||||
p.addBuildListener(errorLogger);
|
||||
|
||||
try {
|
||||
p.fireBuildStarted();
|
||||
p.init();
|
||||
final ProjectHelper helper = ProjectHelper.getProjectHelper();
|
||||
p.addReference("ant.projectHelper", helper);
|
||||
helper.parse(p, buildFile);
|
||||
p.executeTarget(target);
|
||||
return true;
|
||||
|
||||
} catch (final BuildException e) {
|
||||
// Send a "build finished" event to the build listeners for this project.
|
||||
p.fireBuildFinished(e);
|
||||
|
||||
String out = new String(outb.toByteArray());
|
||||
String err = new String(errb.toByteArray());
|
||||
System.out.println(out);
|
||||
System.err.println(err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected void addManifest(ZipOutputStream zos) throws IOException {
|
||||
ZipEntry entry = new ZipEntry("META-INF/MANIFEST.MF");
|
||||
zos.putNextEntry(entry);
|
||||
|
||||
@@ -251,31 +251,33 @@ public class JavaEditor extends Editor {
|
||||
toolbar.deactivate(JavaToolbar.EXPORT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// JPanel presentColorPanel;
|
||||
// JTextField presentColorPanel;
|
||||
|
||||
protected boolean exportApplicationPrompt() throws IOException, SketchException {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
panel.add(Box.createVerticalStrut(6));
|
||||
|
||||
//Box panel = Box.createVerticalBox();
|
||||
|
||||
//Box labelBox = Box.createHorizontalBox();
|
||||
// Box panel = Box.createVerticalBox();
|
||||
// Box labelBox = Box.createHorizontalBox();
|
||||
// String msg = "<html>Click Export to Application to create a standalone, " +
|
||||
// "double-clickable application for the selected plaforms.";
|
||||
|
||||
// String msg = "Export to Application creates a standalone, \n" +
|
||||
// "double-clickable application for the selected plaforms.";
|
||||
String line1 = Language.text("export.description.line1");
|
||||
String line2 = Language.text("export.description.line2");
|
||||
//String line2 = "standalone application for the current plaform.";
|
||||
JLabel label1 = new JLabel(line1, SwingConstants.CENTER);
|
||||
JLabel label2 = new JLabel(line2, SwingConstants.CENTER);
|
||||
label1.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
label2.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
// label1.setAlignmentX();
|
||||
// label2.setAlignmentX(0);
|
||||
panel.add(label1);
|
||||
panel.add(label2);
|
||||
int wide = label2.getPreferredSize().width;
|
||||
// The longer line is different between Windows and OS X.
|
||||
// int wide = Math.max(label1.getPreferredSize().width,
|
||||
// label2.getPreferredSize().width);
|
||||
panel.add(Box.createVerticalStrut(12));
|
||||
|
||||
final JCheckBox windowsButton = new JCheckBox("Windows");
|
||||
@@ -288,7 +290,6 @@ public class JavaEditor extends Editor {
|
||||
});
|
||||
|
||||
final JCheckBox macosxButton = new JCheckBox("Mac OS X");
|
||||
//macosxButton.setMnemonic(KeyEvent.VK_M);
|
||||
macosxButton.setSelected(Preferences.getBoolean("export.application.platform.macosx"));
|
||||
macosxButton.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
@@ -315,14 +316,15 @@ public class JavaEditor extends Editor {
|
||||
platformPanel.setBorder(new TitledBorder(Language.text("export.platforms")));
|
||||
//Dimension goodIdea = new Dimension(wide, platformPanel.getPreferredSize().height);
|
||||
//platformPanel.setMaximumSize(goodIdea);
|
||||
wide = Math.max(wide, platformPanel.getPreferredSize().width);
|
||||
// wide = Math.max(wide, platformPanel.getPreferredSize().width);
|
||||
platformPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
panel.add(platformPanel);
|
||||
|
||||
// Box indentPanel = Box.createHorizontalBox();
|
||||
// indentPanel.add(Box.createHorizontalStrut(new JCheckBox().getPreferredSize().width));
|
||||
int divWidth = platformPanel.getPreferredSize().width;
|
||||
|
||||
//int indent = new JCheckBox().getPreferredSize().width;
|
||||
int indent = 0;
|
||||
|
||||
final JCheckBox showStopButton = new JCheckBox(Language.text("export.options.show_stop_button"));
|
||||
//showStopButton.setMnemonic(KeyEvent.VK_S);
|
||||
showStopButton.setSelected(Preferences.getBoolean("export.application.stop"));
|
||||
showStopButton.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
@@ -330,9 +332,7 @@ public class JavaEditor extends Editor {
|
||||
}
|
||||
});
|
||||
showStopButton.setEnabled(Preferences.getBoolean("export.application.fullscreen"));
|
||||
showStopButton.setBorder(new EmptyBorder(3, 13, 6, 13));
|
||||
// indentPanel.add(showStopButton);
|
||||
// indentPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
showStopButton.setBorder(new EmptyBorder(3, 13 + indent, 6, 13));
|
||||
|
||||
final JCheckBox fullScreenButton = new JCheckBox(Language.text("export.options.fullscreen"));
|
||||
//fullscreenButton.setMnemonic(KeyEvent.VK_F);
|
||||
@@ -346,63 +346,200 @@ public class JavaEditor extends Editor {
|
||||
});
|
||||
fullScreenButton.setBorder(new EmptyBorder(3, 13, 3, 13));
|
||||
|
||||
JPanel optionPanel = new JPanel();
|
||||
optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.Y_AXIS));
|
||||
optionPanel.add(fullScreenButton);
|
||||
optionPanel.add(showStopButton);
|
||||
// optionPanel.add(indentPanel);
|
||||
optionPanel.setBorder(new TitledBorder(Language.text("export.options")));
|
||||
wide = Math.max(wide, platformPanel.getPreferredSize().width);
|
||||
//goodIdea = new Dimension(wide, optionPanel.getPreferredSize().height);
|
||||
optionPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
//optionPanel.setMaximumSize(goodIdea);
|
||||
panel.add(optionPanel);
|
||||
JPanel presentPanel = new JPanel();
|
||||
presentPanel.setLayout(new BoxLayout(presentPanel, BoxLayout.Y_AXIS));
|
||||
Box fullScreenBox = Box.createHorizontalBox();
|
||||
fullScreenBox.add(fullScreenButton);
|
||||
|
||||
/*
|
||||
//run.present.stop.color
|
||||
// presentColorPanel = new JTextField();
|
||||
// presentColorPanel.setFocusable(false);
|
||||
// presentColorPanel.setEnabled(false);
|
||||
presentColorPanel = new JPanel() {
|
||||
public void paintComponent(Graphics g) {
|
||||
g.setColor(Preferences.getColor("run.present.bgcolor"));
|
||||
Dimension size = getSize();
|
||||
g.fillRect(0, 0, size.width, size.height);
|
||||
}
|
||||
};
|
||||
presentColorPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||
// presentColorPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
|
||||
presentColorPanel.setMaximumSize(new Dimension(30, 20));
|
||||
fullScreenBox.add(presentColorPanel);
|
||||
*/
|
||||
fullScreenBox.add(new ColorPreference("run.present.bgcolor"));
|
||||
//presentPanel.add(fullScreenButton);
|
||||
fullScreenBox.add(Box.createHorizontalStrut(10));
|
||||
fullScreenBox.add(Box.createHorizontalGlue());
|
||||
|
||||
Dimension good;
|
||||
//label1, label2, platformPanel, optionPanel
|
||||
good = new Dimension(wide, label1.getPreferredSize().height);
|
||||
label1.setMaximumSize(good);
|
||||
good = new Dimension(wide, label2.getPreferredSize().height);
|
||||
label2.setMaximumSize(good);
|
||||
good = new Dimension(wide, platformPanel.getPreferredSize().height);
|
||||
platformPanel.setMaximumSize(good);
|
||||
good = new Dimension(wide, optionPanel.getPreferredSize().height);
|
||||
optionPanel.setMaximumSize(good);
|
||||
|
||||
// JPanel actionPanel = new JPanel();
|
||||
// optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.X_AXIS));
|
||||
// optionPanel.add(Box.createHorizontalGlue());
|
||||
|
||||
// final JDialog frame = new JDialog(editor, "Export to Application");
|
||||
|
||||
// JButton cancelButton = new JButton("Cancel");
|
||||
// cancelButton.addActionListener(new ActionListener() {
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// frame.dispose();
|
||||
// return false;
|
||||
presentPanel.add(fullScreenBox);
|
||||
|
||||
// presentColorPanel.addMouseListener(new MouseAdapter() {
|
||||
// public void mousePressed(MouseEvent e) {
|
||||
// new ColorListener("run.present.bgcolor");
|
||||
// }
|
||||
// });
|
||||
|
||||
// Add the buttons in platform-specific order
|
||||
// if (PApplet.platform == PConstants.MACOSX) {
|
||||
// optionPanel.add(cancelButton);
|
||||
// optionPanel.add(exportButton);
|
||||
// } else {
|
||||
// optionPanel.add(exportButton);
|
||||
// optionPanel.add(cancelButton);
|
||||
// }
|
||||
Box showStopBox = Box.createHorizontalBox();
|
||||
showStopBox.add(showStopButton);
|
||||
showStopBox.add(new ColorPreference("run.present.stop.color"));
|
||||
showStopBox.add(Box.createHorizontalStrut(10));
|
||||
showStopBox.add(Box.createHorizontalGlue());
|
||||
presentPanel.add(showStopBox);
|
||||
|
||||
//presentPanel.add(showStopButton);
|
||||
// presentPanel.add(Box.createHorizontalStrut(10));
|
||||
// presentPanel.add(Box.createHorizontalGlue());
|
||||
presentPanel.setBorder(new TitledBorder("Full Screen"));
|
||||
// wide = Math.max(wide, platformPanel.getPreferredSize().width);
|
||||
presentPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
panel.add(presentPanel);
|
||||
|
||||
// Dimension good;
|
||||
// good = new Dimension(wide, label1.getPreferredSize().height);
|
||||
// label1.setMaximumSize(good);
|
||||
// good = new Dimension(wide, label2.getPreferredSize().height);
|
||||
// label2.setMaximumSize(good);
|
||||
// good = new Dimension(wide, presentPanel.getPreferredSize().height);
|
||||
|
||||
//
|
||||
|
||||
JPanel embedPanel = new JPanel();
|
||||
embedPanel.setLayout(new BoxLayout(embedPanel, BoxLayout.Y_AXIS));
|
||||
|
||||
String platformName = null;
|
||||
if (Base.isMacOS()) {
|
||||
platformName = "Mac OS X";
|
||||
} else if (Base.isWindows()) {
|
||||
platformName = "Windows (" + Base.getNativeBits() + "-bit)";
|
||||
} else if (Base.isLinux()) {
|
||||
platformName = "Linux (" + Base.getNativeBits() + "-bit)";
|
||||
}
|
||||
|
||||
boolean embed = Preferences.getBoolean("export.application.embed_java");
|
||||
final String embedWarning =
|
||||
"<html><div width=\"" + divWidth + "\"><font size=\"2\">" +
|
||||
// "<html><body><font size=2>" +
|
||||
"Embedding Java will make the " + platformName + " application " +
|
||||
"larger, but it will be far more likely to work. " +
|
||||
"Users on other platforms will need to <a href=\"\">install Java 7</a>.";
|
||||
final String nopeWarning =
|
||||
"<html><div width=\"" + divWidth + "\"><font size=\"2\">" +
|
||||
// "<html><body><font size=2>" +
|
||||
"Users on all platforms will have to install the latest " +
|
||||
"version of Java 7 from <a href=\"\">http://java.com/download</a>. " +
|
||||
"<br/> ";
|
||||
//"from <a href=\"http://java.com/download\">java.com/download</a>.";
|
||||
final JLabel warningLabel = new JLabel(embed ? embedWarning : nopeWarning);
|
||||
warningLabel.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent event) {
|
||||
Base.openURL("http://java.com/download");
|
||||
}
|
||||
});
|
||||
warningLabel.setBorder(new EmptyBorder(3, 13 + indent, 3, 13));
|
||||
|
||||
final JCheckBox embedJavaButton =
|
||||
new JCheckBox("Embed Java for " + platformName);
|
||||
embedJavaButton.setSelected(embed);
|
||||
embedJavaButton.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
boolean selected = embedJavaButton.isSelected();
|
||||
Preferences.setBoolean("export.application.embed_java", selected);
|
||||
if (selected) {
|
||||
warningLabel.setText(embedWarning);
|
||||
} else {
|
||||
warningLabel.setText(nopeWarning);
|
||||
}
|
||||
}
|
||||
});
|
||||
embedJavaButton.setBorder(new EmptyBorder(3, 13, 3, 13));
|
||||
|
||||
embedPanel.add(embedJavaButton);
|
||||
embedPanel.add(warningLabel);
|
||||
embedPanel.setBorder(new TitledBorder("Embed Java"));
|
||||
panel.add(embedPanel);
|
||||
|
||||
//
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
JPanel signPanel = new JPanel();
|
||||
signPanel.setLayout(new BoxLayout(signPanel, BoxLayout.Y_AXIS));
|
||||
signPanel.setBorder(new TitledBorder("Code Signing"));
|
||||
|
||||
// gatekeeper: http://support.apple.com/kb/ht5290
|
||||
// for developers: https://developer.apple.com/developer-id/
|
||||
String thePain =
|
||||
//"<html><body><font size=2>" +
|
||||
"In recent versions of OS X, Apple has introduced the \u201CGatekeeper\u201D system, " +
|
||||
"which makes it more difficult to run applications like those exported from Processing. ";
|
||||
|
||||
if (new File("/usr/bin/codesign_allocate").exists()) {
|
||||
thePain +=
|
||||
"This application will be \u201Cself-signed\u201D which means that Finder may report that the " +
|
||||
"application is from an \u201Cunidentified developer\u201D. If the application will not " +
|
||||
"run, try right-clicking the app and selecting Open from the pop-up menu. Or you can visit " +
|
||||
"System Preferences \u2192 Security & Privacy and select Allow apps downloaded from: anywhere. ";
|
||||
} else {
|
||||
thePain +=
|
||||
"Gatekeeper requires applications to be \u201Csigned\u201D, or they will be reported as damaged. " +
|
||||
"To prevent this message, install Xcode (and the Command Line Tools) from the App Store, or visit " +
|
||||
"System Preferences \u2192 Security & Privacy and select Allow apps downloaded from: anywhere. ";
|
||||
}
|
||||
thePain +=
|
||||
"To avoid the messages entirely, manually code sign your app. " +
|
||||
"For more information: <a href=\"\">https://developer.apple.com/developer-id/</a>";
|
||||
|
||||
// xattr -d com.apple.quarantine thesketch.app
|
||||
|
||||
//signPanel.add(new JLabel(thePain));
|
||||
//JEditorPane area = new JEditorPane("text/html", thePain);
|
||||
//JTextPane area = new JEditorPane("text/html", thePain);
|
||||
|
||||
// JTextArea area = new JTextArea(thePain);
|
||||
// area.setBackground(null);
|
||||
// area.setFont(new Font("Dialog", Font.PLAIN, 10));
|
||||
// area.setLineWrap(true);
|
||||
// area.setWrapStyleWord(true);
|
||||
// Are you f-king serious, Java API developers?
|
||||
JLabel area = new JLabel("<html><div width=\"" + divWidth + "\"><font size=\"2\">" + thePain + "</div></html>");
|
||||
|
||||
area.setBorder(new EmptyBorder(3, 13, 3, 13));
|
||||
// area.setPreferredSize(new Dimension(embedPanel.getPreferredSize().width, 100));
|
||||
// area.setPreferredSize(new Dimension(300, 200));
|
||||
signPanel.add(area);
|
||||
// signPanel.add(Box.createHorizontalGlue());
|
||||
signPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
|
||||
area.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent event) {
|
||||
Base.openURL("https://developer.apple.com/developer-id/");
|
||||
}
|
||||
});
|
||||
|
||||
panel.add(signPanel);
|
||||
}
|
||||
//System.out.println(panel.getPreferredSize());
|
||||
// panel.setMinimumSize(new Dimension(316, 461));
|
||||
// panel.setPreferredSize(new Dimension(316, 461));
|
||||
// panel.setMaximumSize(new Dimension(316, 461));
|
||||
|
||||
//
|
||||
|
||||
String[] options = { Language.text("prompt.export"), Language.text("prompt.cancel") };
|
||||
|
||||
final JOptionPane optionPane = new JOptionPane(panel,
|
||||
JOptionPane.PLAIN_MESSAGE,
|
||||
//JOptionPane.QUESTION_MESSAGE,
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
null,
|
||||
options,
|
||||
options[0]);
|
||||
|
||||
|
||||
final JDialog dialog = new JDialog(this, Language.text("export"), true);
|
||||
dialog.setContentPane(optionPane);
|
||||
|
||||
// System.out.println(optionPane.getLayout());
|
||||
|
||||
optionPane.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
String prop = e.getPropertyName();
|
||||
@@ -410,20 +547,24 @@ public class JavaEditor extends Editor {
|
||||
if (dialog.isVisible() &&
|
||||
(e.getSource() == optionPane) &&
|
||||
(prop.equals(JOptionPane.VALUE_PROPERTY))) {
|
||||
//If you were going to check something
|
||||
//before closing the window, you'd do
|
||||
//it here.
|
||||
// If you were going to check something before
|
||||
// closing the window, you'd do it here.
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
dialog.pack();
|
||||
// System.out.println("after pack: " + panel.getPreferredSize());
|
||||
// dialog.setSize(optionPane.getPreferredSize());
|
||||
dialog.setResizable(false);
|
||||
|
||||
|
||||
// Center the window in the middle of the editor
|
||||
Rectangle bounds = getBounds();
|
||||
dialog.setLocation(bounds.x + (bounds.width - dialog.getSize().width) / 2,
|
||||
bounds.y + (bounds.height - dialog.getSize().height) / 2);
|
||||
dialog.setVisible(true);
|
||||
|
||||
//System.out.println(panel.getSize());
|
||||
|
||||
Object value = optionPane.getValue();
|
||||
if (value.equals(options[0])) {
|
||||
@@ -435,7 +576,90 @@ public class JavaEditor extends Editor {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Color bgcolor = Preferences.getColor("run.present.bgcolor");
|
||||
final ColorChooser c = new ColorChooser(JavaEditor.this, true, bgcolor,
|
||||
"Select", new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Preferences.setColor("run.present.bgcolor", c.getColor());
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
class ColorListener implements ActionListener {
|
||||
ColorChooser chooser;
|
||||
String prefName;
|
||||
|
||||
public ColorListener(String prefName) {
|
||||
this.prefName = prefName;
|
||||
Color color = Preferences.getColor(prefName);
|
||||
chooser = new ColorChooser(JavaEditor.this, true, color, "Select", this);
|
||||
chooser.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Color color = chooser.getColor();
|
||||
Preferences.setColor(prefName, color);
|
||||
// presentColorPanel.setBackground(color);
|
||||
presentColorPanel.repaint();
|
||||
chooser.hide();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
class ColorPreference extends JPanel implements ActionListener {
|
||||
ColorChooser chooser;
|
||||
String prefName;
|
||||
|
||||
public ColorPreference(String pref) {
|
||||
prefName = pref;
|
||||
|
||||
setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
|
||||
setPreferredSize(new Dimension(30, 20));
|
||||
setMaximumSize(new Dimension(30, 20));
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
Color color = Preferences.getColor(prefName);
|
||||
chooser = new ColorChooser(JavaEditor.this, true, color, "Select", ColorPreference.this);
|
||||
chooser.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void paintComponent(Graphics g) {
|
||||
g.setColor(Preferences.getColor(prefName));
|
||||
Dimension size = getSize();
|
||||
g.fillRect(0, 0, size.width, size.height);
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Color color = chooser.getColor();
|
||||
Preferences.setColor(prefName, color);
|
||||
//presentColorPanel.repaint();
|
||||
repaint();
|
||||
chooser.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// protected void selectColor(String prefName) {
|
||||
// Color color = Preferences.getColor(prefName);
|
||||
// final ColorChooser chooser = new ColorChooser(JavaEditor.this, true, color,
|
||||
// "Select", new ActionListener() {
|
||||
//
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// Preferences.setColor(prefName, c.getColor());
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if the sketch has been modified, and if so,
|
||||
* asks the user to save the sketch or cancel the export.
|
||||
|
||||
@@ -123,11 +123,7 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
|
||||
|
||||
// public void launch(String appletClassName, boolean presenting) {
|
||||
// this.appletClassName = appletClassName;
|
||||
public boolean launchVirtualMachine(boolean presenting) {
|
||||
// this.presenting = presenting;
|
||||
|
||||
String[] vmParams = getMachineParams();
|
||||
String[] sketchParams = getSketchParams(presenting);
|
||||
int port = 8000 + (int) (Math.random() * 1000);
|
||||
@@ -139,10 +135,15 @@ public class Runner implements MessageConsumer {
|
||||
// Newer (Java 1.5+) version that uses JVMTI
|
||||
String jdwpArg = "-agentlib:jdwp=transport=dt_socket,address=" + portStr + ",server=y,suspend=y";
|
||||
|
||||
// Everyone works the same under Java 7 (also on OS X)
|
||||
String[] commandArgs = new String[] { Base.getJavaPath(), jdwpArg };
|
||||
|
||||
/*
|
||||
String[] commandArgs = null;
|
||||
if (!Base.isMacOS()) {
|
||||
commandArgs = new String[] {
|
||||
"java", jdwpArg
|
||||
Base.getJavaPath(),
|
||||
jdwpArg
|
||||
};
|
||||
} else {
|
||||
// Decided to just set this to 1.6 only, because otherwise it's gonna
|
||||
@@ -160,7 +161,7 @@ public class Runner implements MessageConsumer {
|
||||
// OS X at this point, because we require 10.6.8 and higher. That also
|
||||
// means we don't need to check for any other OS versions, the user is
|
||||
// a douchebag and modifies Info.plist to get around the restriction.
|
||||
if (true) {
|
||||
if (false) {
|
||||
if (System.getProperty("os.version").startsWith("10.6")) {
|
||||
commandArgs = new String[] {
|
||||
"/usr/libexec/java_home",
|
||||
@@ -183,41 +184,19 @@ public class Runner implements MessageConsumer {
|
||||
} else {
|
||||
// testing jdk-7u40
|
||||
commandArgs = new String[] {
|
||||
"/Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk/Contents/Home/bin/java",
|
||||
//"/Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk/Contents/Home/bin/java",
|
||||
Base.getJavaPath(),
|
||||
jdwpArg
|
||||
};
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
commandArgs = PApplet.concat(commandArgs, vmParams);
|
||||
commandArgs = PApplet.concat(commandArgs, sketchParams);
|
||||
// PApplet.println(commandArgs);
|
||||
// commandArg.setValue(commandArgs);
|
||||
launchJava(commandArgs);
|
||||
// try {
|
||||
// Thread.sleep(2000);
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// boolean available = false;
|
||||
// while (!available) {
|
||||
// try {
|
||||
// Socket socket = new Socket((String) null, port);
|
||||
//// socket.close();
|
||||
// // this should mean we're all set?
|
||||
// available = true;
|
||||
//
|
||||
// } catch (IOException e) {
|
||||
// System.out.println("waiting");
|
||||
// //e.printStackTrace();
|
||||
// try {
|
||||
// Thread.sleep(100);
|
||||
// } catch (InterruptedException e1) {
|
||||
// e1.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
AttachingConnector connector = (AttachingConnector)
|
||||
findConnector("com.sun.jdi.SocketAttach");
|
||||
@@ -467,7 +446,7 @@ public class Runner implements MessageConsumer {
|
||||
// PApplet.println("launchJava stderr:");
|
||||
// PApplet.println(errorStrings);
|
||||
// PApplet.println("launchJava stdout:");
|
||||
PApplet.println(inputStrings);
|
||||
PApplet.printArray(inputStrings);
|
||||
|
||||
if (errorStrings != null && errorStrings.length > 1) {
|
||||
if (errorStrings[0].indexOf("Invalid maximum heap size") != -1) {
|
||||
@@ -699,7 +678,9 @@ public class Runner implements MessageConsumer {
|
||||
|
||||
for (Event event : eventSet) {
|
||||
// System.out.println("EventThread.handleEvent -> " + event);
|
||||
if (event instanceof ExceptionEvent) {
|
||||
if (event instanceof VMStartEvent) {
|
||||
vm.resume();
|
||||
} else if (event instanceof ExceptionEvent) {
|
||||
// for (ThreadReference thread : vm.allThreads()) {
|
||||
// System.out.println("thread : " + thread);
|
||||
//// thread.suspend();
|
||||
@@ -731,8 +712,6 @@ public class Runner implements MessageConsumer {
|
||||
errThread.start();
|
||||
outThread.start();
|
||||
|
||||
vm.resume();
|
||||
|
||||
// Shutdown begins when event thread terminates
|
||||
try {
|
||||
if (eventThread != null) eventThread.join(); // is this the problem?
|
||||
@@ -944,7 +923,7 @@ public class Runner implements MessageConsumer {
|
||||
ObjectReference ref = (ObjectReference)val;
|
||||
method = ((ClassType) ref.referenceType()).concreteMethodByName("getFileName", "()Ljava/lang/String;");
|
||||
StringReference strref = (StringReference) ref.invokeMethod(thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
|
||||
String filename = strref.value();
|
||||
String filename = strref == null ? "Unknown Source" : strref.value();
|
||||
method = ((ClassType) ref.referenceType()).concreteMethodByName("getLineNumber", "()I");
|
||||
IntegerValue intval = (IntegerValue) ref.invokeMethod(thread, method, new ArrayList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
|
||||
int lineNumber = intval.intValue() - 1;
|
||||
|
||||
Reference in New Issue
Block a user