diff --git a/app/src/processing/app/legacy/PApplet.java b/app/src/processing/app/legacy/PApplet.java
new file mode 100644
index 000000000..c444a3b2f
--- /dev/null
+++ b/app/src/processing/app/legacy/PApplet.java
@@ -0,0 +1,729 @@
+package processing.app.legacy;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class PApplet {
+
+ /** Path to sketch folder */
+ public String sketchPath; //folder;
+
+ /**
+ * Full name of the Java version (i.e. 1.5.0_11).
+ * Prior to 0125, this was only the first three digits.
+ */
+ public static final String javaVersionName =
+ System.getProperty("java.version");
+
+ /**
+ * Version of Java that's in use, whether 1.1 or 1.3 or whatever,
+ * stored as a float.
+ *
+ * Note that because this is stored as a float, the values may
+ * not be exactly 1.3 or 1.4. Instead, make sure you're
+ * comparing against 1.3f or 1.4f, which will have the same amount
+ * of error (i.e. 1.40000001). This could just be a double, but
+ * since Processing only uses floats, it's safer for this to be a float
+ * because there's no good way to specify a double with the preproc.
+ */
+ public static final float javaVersion =
+ new Float(javaVersionName.substring(0, 3)).floatValue();
+
+ /**
+ * Current platform in use, one of the
+ * PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
+ */
+ static public int platform;
+
+ /**
+ * Name associated with the current 'platform' (see PConstants.platformNames)
+ */
+ //static public String platformName;
+
+ static {
+ String osname = System.getProperty("os.name");
+
+ if (osname.indexOf("Mac") != -1) {
+ platform = PConstants.MACOSX;
+
+ } else if (osname.indexOf("Windows") != -1) {
+ platform = PConstants.WINDOWS;
+
+ } else if (osname.equals("Linux")) { // true for the ibm vm
+ platform = PConstants.LINUX;
+
+ } else {
+ platform = PConstants.OTHER;
+ }
+ }
+
+ /**
+ * GIF image of the Processing logo.
+ */
+ static public final byte[] ICON_IMAGE = {
+ 71, 73, 70, 56, 57, 97, 16, 0, 16, 0, -60, 0, 0, 0, 0, 0,
+ 0, 0, -127, 0, -127, 0, 0, -127, -127, -127, 0, 0, -127, 0, -127, -127,
+ -127, 0, -127, -127, -127, -63, -63, -63, 0, 0, -1, 0, -1, 0, 0, -1,
+ -1, -1, 0, 0, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, -7, 4,
+ 9, 0, 0, 16, 0, 44, 0, 0, 0, 0, 16, 0, 16, 0, 0, 5,
+ 75, 32, 36, -118, -57, 96, 14, -57, -88, 66, -27, -23, -90, -86, 43, -97,
+ 99, 59, -65, -30, 125, -77, 3, -14, -4, 8, -109, 15, -120, -22, 61, 78,
+ 15, -124, 15, 25, 28, 28, 93, 63, -45, 115, -22, -116, 90, -83, 82, 89,
+ -44, -103, 61, 44, -91, -54, -89, 19, -111, 50, 18, -51, -55, 1, 73, -121,
+ -53, -79, 77, 43, -101, 12, -74, -30, -99, -24, -94, 16, 0, 59,
+ };
+
+ /**
+ * Split the provided String at wherever whitespace occurs. Multiple
+ * whitespace (extra spaces or tabs or whatever) between items will count as a
+ * single break.
+ *
+ * The whitespace characters are "\t\n\r\f", which are the defaults for
+ * java.util.StringTokenizer, plus the unicode non-breaking space character,
+ * which is found commonly on files created by or used in conjunction with Mac
+ * OS X (character 160, or 0x00A0 in hex).
+ *
+ *
+ * i.e. splitTokens("a b") -> { "a", "b" }
+ * splitTokens("a b") -> { "a", "b" }
+ * splitTokens("a\tb") -> { "a", "b" }
+ * splitTokens("a \t b ") -> { "a", "b" }
+ *
+ */
+ static public String[] splitTokens(String what) {
+ return splitTokens(what, PConstants.WHITESPACE);
+ }
+
+ /**
+ * Splits a string into pieces, using any of the chars in the String 'delim'
+ * as separator characters. For instance, in addition to white space, you
+ * might want to treat commas as a separator. The delimeter characters won't
+ * appear in the returned String array.
+ *
+ *
+ * i.e. splitTokens("a, b", " ,") -> { "a", "b" }
+ *
+ *
+ * To include all the whitespace possibilities, use the variable WHITESPACE,
+ * found in PConstants:
+ *
+ *
+ * i.e. splitTokens("a | b", WHITESPACE + "|"); -> { "a", "b" }
+ *
+ */
+ static public String[] splitTokens(String what, String delim) {
+ StringTokenizer toker = new StringTokenizer(what, delim);
+ String pieces[] = new String[toker.countTokens()];
+
+ int index = 0;
+ while (toker.hasMoreTokens()) {
+ pieces[index++] = toker.nextToken();
+ }
+ return pieces;
+ }
+
+ /**
+ * Split a string into pieces along a specific character. Most commonly used
+ * to break up a String along a space or a tab character.
+ *
+ * This operates differently than the others, where the single delimeter is
+ * the only breaking point, and consecutive delimeters will produce an empty
+ * string (""). This way, one can split on tab characters, but maintain the
+ * column alignments (of say an excel file) where there are empty columns.
+ */
+ static public String[] split(String what, char delim) {
+ // do this so that the exception occurs inside the user's
+ // program, rather than appearing to be a bug inside split()
+ if (what == null)
+ return null;
+
+ char chars[] = what.toCharArray();
+ int splitCount = 0; // 1;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] == delim)
+ splitCount++;
+ }
+ if (splitCount == 0) {
+ String splits[] = new String[1];
+ splits[0] = new String(what);
+ return splits;
+ }
+ String splits[] = new String[splitCount + 1];
+ int splitIndex = 0;
+ int startIndex = 0;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] == delim) {
+ splits[splitIndex++] = new String(chars, startIndex, i - startIndex);
+ startIndex = i + 1;
+ }
+ }
+ splits[splitIndex] = new String(chars, startIndex, chars.length
+ - startIndex);
+ return splits;
+ }
+
+ static public String[] subset(String list[], int start, int count) {
+ String output[] = new String[count];
+ System.arraycopy(list, start, output, 0, count);
+ return output;
+ }
+
+
+ /**
+ * Join an array of Strings together as a single String,
+ * separated by the whatever's passed in for the separator.
+ */
+ static public String join(String str[], char separator) {
+ return join(str, String.valueOf(separator));
+ }
+
+
+ /**
+ * Join an array of Strings together as a single String,
+ * separated by the whatever's passed in for the separator.
+ *
+ * To use this on numbers, first pass the array to nf() or nfs()
+ * to get a list of String objects, then use join on that.
+ *
+ * e.g. String stuff[] = { "apple", "bear", "cat" };
+ * String list = join(stuff, ", ");
+ * // list is now "apple, bear, cat"
+ */
+ static public String join(String str[], String separator) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < str.length; i++) {
+ if (i != 0) buffer.append(separator);
+ buffer.append(str[i]);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Parse a String into an int value. Returns 0 if the value is bad.
+ */
+ static final public int parseInt(String what) {
+ return parseInt(what, 0);
+ }
+
+ /**
+ * Parse a String to an int, and provide an alternate value that
+ * should be used when the number is invalid.
+ */
+ static final public int parseInt(String what, int otherwise) {
+ try {
+ int offset = what.indexOf('.');
+ if (offset == -1) {
+ return Integer.parseInt(what);
+ } else {
+ return Integer.parseInt(what.substring(0, offset));
+ }
+ } catch (NumberFormatException e) { }
+ return otherwise;
+ }
+
+ /**
+ * Make an array of int elements from an array of String objects.
+ * If the String can't be parsed as a number, it will be set to zero.
+ *
+ * String s[] = { "1", "300", "44" };
+ * int numbers[] = parseInt(s);
+ *
+ * numbers will contain { 1, 300, 44 }
+ */
+ static public int[] parseInt(String what[]) {
+ return parseInt(what, 0);
+ }
+
+ /**
+ * Make an array of int elements from an array of String objects.
+ * If the String can't be parsed as a number, its entry in the
+ * array will be set to the value of the "missing" parameter.
+ *
+ * String s[] = { "1", "300", "apple", "44" };
+ * int numbers[] = parseInt(s, 9999);
+ *
+ * numbers will contain { 1, 300, 9999, 44 }
+ */
+ static public int[] parseInt(String what[], int missing) {
+ int output[] = new int[what.length];
+ for (int i = 0; i < what.length; i++) {
+ try {
+ output[i] = Integer.parseInt(what[i]);
+ } catch (NumberFormatException e) {
+ output[i] = missing;
+ }
+ }
+ return output;
+ }
+
+ static public String[] loadStrings(File file) {
+ InputStream is = createInput(file);
+ if (is != null) return loadStrings(is);
+ return null;
+ }
+
+ static public String[] loadStrings(InputStream input) {
+ try {
+ BufferedReader reader =
+ new BufferedReader(new InputStreamReader(input, "UTF-8"));
+
+ String lines[] = new String[100];
+ int lineCount = 0;
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ if (lineCount == lines.length) {
+ String temp[] = new String[lineCount << 1];
+ System.arraycopy(lines, 0, temp, 0, lineCount);
+ lines = temp;
+ }
+ lines[lineCount++] = line;
+ }
+ reader.close();
+
+ if (lineCount == lines.length) {
+ return lines;
+ }
+
+ // resize array to appropriate amount for these lines
+ String output[] = new String[lineCount];
+ System.arraycopy(lines, 0, output, 0, lineCount);
+ return output;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ //throw new RuntimeException("Error inside loadStrings()");
+ }
+ return null;
+ }
+
+ public void saveStrings(String filename, String strings[]) {
+ saveStrings(saveFile(filename), strings);
+ }
+
+
+ static public void saveStrings(File file, String strings[]) {
+ saveStrings(createOutput(file), strings);
+ }
+
+
+ static public void saveStrings(OutputStream output, String strings[]) {
+ PrintWriter writer = createWriter(output);
+ for (int i = 0; i < strings.length; i++) {
+ writer.println(strings[i]);
+ }
+ writer.flush();
+ writer.close();
+ }
+
+
+ static public int[] expand(int list[]) {
+ return expand(list, list.length << 1);
+ }
+
+ static public int[] expand(int list[], int newSize) {
+ int temp[] = new int[newSize];
+ System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
+ return temp;
+ }
+
+ static final public String hex(int what, int digits) {
+ String stuff = Integer.toHexString(what).toUpperCase();
+
+ int length = stuff.length();
+ if (length > digits) {
+ return stuff.substring(length - digits);
+
+ } else if (length < digits) {
+ return "00000000".substring(8 - (digits-length)) + stuff;
+ }
+ return stuff;
+ }
+
+ static public final int constrain(int amt, int low, int high) {
+ return (amt < low) ? low : ((amt > high) ? high : amt);
+ }
+
+ static public final float constrain(float amt, float low, float high) {
+ return (amt < low) ? low : ((amt > high) ? high : amt);
+ }
+
+ /**
+ * Attempts to open an application or file using your platform's launcher. The file parameter is a String specifying the file name and location. The location parameter must be a full path name, or the name of an executable in the system's PATH. In most cases, using a full path is the best option, rather than relying on the system PATH. Be sure to make the file executable before attempting to open it (chmod +x).
+ *
+ * The args parameter is a String or String array which is passed to the command line. If you have multiple parameters, e.g. an application and a document, or a command with multiple switches, use the version that takes a String array, and place each individual item in a separate element.
+ *
+ * If args is a String (not an array), then it can only be a single file or application with no parameters. It's not the same as executing that String using a shell. For instance, open("jikes -help") will not work properly.
+ *
+ * This function behaves differently on each platform. On Windows, the parameters are sent to the Windows shell via "cmd /c". On Mac OS X, the "open" command is used (type "man open" in Terminal.app for documentation). On Linux, it first tries gnome-open, then kde-open, but if neither are available, it sends the command to the shell without any alterations.
+ *
+ * For users familiar with Java, this is not quite the same as Runtime.exec(), because the launcher command is prepended. Instead, the exec(String[]) function is a shortcut for Runtime.getRuntime.exec(String[]).
+ *
+ * @webref input:files
+ * @param filename name of the file
+ * @usage Application
+ */
+ static public void open(String filename) {
+ open(new String[] { filename });
+ }
+
+ static String openLauncher;
+
+ /**
+ * Launch a process using a platforms shell. This version uses an array
+ * to make it easier to deal with spaces in the individual elements.
+ * (This avoids the situation of trying to put single or double quotes
+ * around different bits).
+ *
+ * @param list of commands passed to the command line
+ */
+ static public Process open(String argv[]) {
+ String[] params = null;
+
+ if (platform == PConstants.WINDOWS) {
+ // just launching the .html file via the shell works
+ // but make sure to chmod +x the .html files first
+ // also place quotes around it in case there's a space
+ // in the user.dir part of the url
+ params = new String[] { "cmd", "/c" };
+
+ } else if (platform == PConstants.MACOSX) {
+ params = new String[] { "open" };
+
+ } else if (platform == PConstants.LINUX) {
+ if (openLauncher == null) {
+ // Attempt to use gnome-open
+ try {
+ Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
+ /*int result =*/ p.waitFor();
+ // Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
+ openLauncher = "gnome-open";
+ } catch (Exception e) { }
+ }
+ if (openLauncher == null) {
+ // Attempt with kde-open
+ try {
+ Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
+ /*int result =*/ p.waitFor();
+ openLauncher = "kde-open";
+ } catch (Exception e) { }
+ }
+ if (openLauncher == null) {
+ System.err.println("Could not find gnome-open or kde-open, " +
+ "the open() command may not work.");
+ }
+ if (openLauncher != null) {
+ params = new String[] { openLauncher };
+ }
+ //} else { // give up and just pass it to Runtime.exec()
+ //open(new String[] { filename });
+ //params = new String[] { filename };
+ }
+ if (params != null) {
+ // If the 'open', 'gnome-open' or 'cmd' are already included
+ if (params[0].equals(argv[0])) {
+ // then don't prepend those params again
+ return exec(argv);
+ } else {
+ params = concat(params, argv);
+ return exec(params);
+ }
+ } else {
+ return exec(argv);
+ }
+ }
+
+ static public Process exec(String[] argv) {
+ try {
+ return Runtime.getRuntime().exec(argv);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not open " + join(argv, ' '));
+ }
+ }
+
+ static public String[] concat(String a[], String b[]) {
+ String c[] = new String[a.length + b.length];
+ System.arraycopy(a, 0, c, 0, a.length);
+ System.arraycopy(b, 0, c, a.length, b.length);
+ return c;
+ }
+
+ /**
+ * Identical to match(), except that it returns an array of all matches in
+ * the specified String, rather than just the first.
+ */
+ static public String[][] matchAll(String what, String regexp) {
+ Pattern p = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL);
+ Matcher m = p.matcher(what);
+ ArrayList results = new ArrayList();
+ int count = m.groupCount() + 1;
+ while (m.find()) {
+ String[] groups = new String[count];
+ for (int i = 0; i < count; i++) {
+ groups[i] = m.group(i);
+ }
+ results.add(groups);
+ }
+ if (results.isEmpty()) {
+ return null;
+ }
+ String[][] matches = new String[results.size()][count];
+ for (int i = 0; i < matches.length; i++) {
+ matches[i] = (String[]) results.get(i);
+ }
+ return matches;
+ }
+
+ /**
+ * Match a string with a regular expression, and returns the match as an
+ * array. The first index is the matching expression, and array elements
+ * [1] and higher represent each of the groups (sequences found in parens).
+ *
+ * This uses multiline matching (Pattern.MULTILINE) and dotall mode
+ * (Pattern.DOTALL) by default, so that ^ and $ match the beginning and
+ * end of any lines found in the source, and the . operator will also
+ * pick up newline characters.
+ */
+ static public String[] match(String what, String regexp) {
+ Pattern p = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL);
+ Matcher m = p.matcher(what);
+ if (m.find()) {
+ int count = m.groupCount() + 1;
+ String[] groups = new String[count];
+ for (int i = 0; i < count; i++) {
+ groups[i] = m.group(i);
+ }
+ return groups;
+ }
+ return null;
+ }
+
+ /**
+ * Integer number formatter.
+ */
+ static private NumberFormat int_nf;
+ static private int int_nf_digits;
+ static private boolean int_nf_commas;
+
+ static public String[] nf(int num[], int digits) {
+ String formatted[] = new String[num.length];
+ for (int i = 0; i < formatted.length; i++) {
+ formatted[i] = nf(num[i], digits);
+ }
+ return formatted;
+ }
+
+ static public String nf(int num, int digits) {
+ if ((int_nf != null) &&
+ (int_nf_digits == digits) &&
+ !int_nf_commas) {
+ return int_nf.format(num);
+ }
+
+ int_nf = NumberFormat.getInstance();
+ int_nf.setGroupingUsed(false); // no commas
+ int_nf_commas = false;
+ int_nf.setMinimumIntegerDigits(digits);
+ int_nf_digits = digits;
+ return int_nf.format(num);
+ }
+
+ static final public String[] str(int x[]) {
+ String s[] = new String[x.length];
+ for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
+ return s;
+ }
+
+ /**
+ * I want to print lines to a file. I have RSI from typing these
+ * eight lines of code so many times.
+ */
+ static public PrintWriter createWriter(File file) {
+ try {
+ createPath(file); // make sure in-between folders exist
+ OutputStream output = new FileOutputStream(file);
+ if (file.getName().toLowerCase().endsWith(".gz")) {
+ output = new GZIPOutputStream(output);
+ }
+ return createWriter(output);
+
+ } catch (Exception e) {
+ if (file == null) {
+ throw new RuntimeException("File passed to createWriter() was null");
+ } else {
+ e.printStackTrace();
+ throw new RuntimeException("Couldn't create a writer for " +
+ file.getAbsolutePath());
+ }
+ }
+ //return null;
+ }
+
+
+ /**
+ * I want to print lines to a file. Why am I always explaining myself?
+ * It's the JavaSoft API engineers who need to explain themselves.
+ */
+ static public PrintWriter createWriter(OutputStream output) {
+ try {
+ OutputStreamWriter osw = new OutputStreamWriter(output, "UTF-8");
+ return new PrintWriter(osw);
+ } catch (UnsupportedEncodingException e) { } // not gonna happen
+ return null;
+ }
+
+ static public InputStream createInput(File file) {
+ if (file == null) {
+ throw new IllegalArgumentException("File passed to createInput() was null");
+ }
+ try {
+ InputStream input = new FileInputStream(file);
+ if (file.getName().toLowerCase().endsWith(".gz")) {
+ return new GZIPInputStream(input);
+ }
+ return input;
+
+ } catch (IOException e) {
+ System.err.println("Could not createInput() for " + file);
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Returns a path inside the applet folder to save to. Like sketchPath(),
+ * but creates any in-between folders so that things save properly.
+ *
+ * All saveXxxx() functions use the path to the sketch folder, rather than
+ * its data folder. Once exported, the data folder will be found inside the
+ * jar file of the exported application or applet. In this case, it's not
+ * possible to save data into the jar file, because it will often be running
+ * from a server, or marked in-use if running from a local file system.
+ * With this in mind, saving to the data path doesn't make sense anyway.
+ * If you know you're running locally, and want to save to the data folder,
+ * use saveXxxx("data/blah.dat").
+ */
+ public String savePath(String where) {
+ if (where == null) return null;
+ String filename = sketchPath(where);
+ createPath(filename);
+ return filename;
+ }
+
+
+ /**
+ * Identical to savePath(), but returns a File object.
+ */
+ public File saveFile(String where) {
+ return new File(savePath(where));
+ }
+
+ /**
+ * Similar to createInput() (formerly openStream), this creates a Java
+ * OutputStream for a given filename or path. The file will be created in
+ * the sketch folder, or in the same folder as an exported application.
+ *
+ * If the path does not exist, intermediate folders will be created. If an
+ * exception occurs, it will be printed to the console, and null will be
+ * returned.
+ *
+ * Future releases may also add support for handling HTTP POST via this
+ * method (for better symmetry with createInput), however that's maybe a
+ * little too clever (and then we'd have to add the same features to the
+ * other file functions like createWriter). Who you callin' bloated?
+ */
+ public OutputStream createOutput(String filename) {
+ return createOutput(saveFile(filename));
+ }
+
+
+ static public OutputStream createOutput(File file) {
+ try {
+ createPath(file); // make sure the path exists
+ FileOutputStream fos = new FileOutputStream(file);
+ if (file.getName().toLowerCase().endsWith(".gz")) {
+ return new GZIPOutputStream(fos);
+ }
+ return fos;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Prepend the sketch folder path to the filename (or path) that is
+ * passed in. External libraries should use this function to save to
+ * the sketch folder.
+ *
+ * Note that when running as an applet inside a web browser,
+ * the sketchPath will be set to null, because security restrictions
+ * prevent applets from accessing that information.
+ *
+ * This will also cause an error if the sketch is not inited properly,
+ * meaning that init() was never called on the PApplet when hosted
+ * my some other main() or by other code. For proper use of init(),
+ * see the examples in the main description text for PApplet.
+ */
+ public String sketchPath(String where) {
+ if (sketchPath == null) {
+ return where;
+// throw new RuntimeException("The applet was not inited properly, " +
+// "or security restrictions prevented " +
+// "it from determining its path.");
+ }
+ // isAbsolute() could throw an access exception, but so will writing
+ // to the local disk using the sketch path, so this is safe here.
+ // for 0120, added a try/catch anyways.
+ try {
+ if (new File(where).isAbsolute()) return where;
+ } catch (Exception e) { }
+
+ return sketchPath + File.separator + where;
+ }
+
+ /**
+ * Takes a path and creates any in-between folders if they don't
+ * already exist. Useful when trying to save to a subfolder that
+ * may not actually exist.
+ */
+ static public void createPath(String path) {
+ createPath(new File(path));
+ }
+
+
+ static public void createPath(File file) {
+ try {
+ String parent = file.getParent();
+ if (parent != null) {
+ File unit = new File(parent);
+ if (!unit.exists()) unit.mkdirs();
+ }
+ } catch (SecurityException se) {
+ System.err.println("You don't have permissions to create " +
+ file.getAbsolutePath());
+ }
+ }
+
+
+}
diff --git a/app/src/processing/app/legacy/PConstants.java b/app/src/processing/app/legacy/PConstants.java
new file mode 100644
index 000000000..3b1d491d5
--- /dev/null
+++ b/app/src/processing/app/legacy/PConstants.java
@@ -0,0 +1,22 @@
+package processing.app.legacy;
+
+public class PConstants {
+
+ // platform IDs for PApplet.platform
+
+ public static final int OTHER = 0;
+ public static final int WINDOWS = 1;
+ public static final int MACOSX = 2;
+ public static final int LINUX = 3;
+
+ public static final String[] platformNames = {
+ "other", "windows", "macosx", "linux"
+ };
+
+
+ // used by split, all the standard whitespace chars
+ // (also includes unicode nbsp, that little bostage)
+
+ static final String WHITESPACE = " \t\n\r\f\u00A0";
+
+}
diff --git a/app/src/processing/app/tools/ColorSelector.java b/app/src/processing/app/tools/ColorSelector.java
deleted file mode 100644
index de1402239..000000000
--- a/app/src/processing/app/tools/ColorSelector.java
+++ /dev/null
@@ -1,609 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2006-08 Ben Fry and Casey Reas
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.app.tools;
-
-import processing.app.*;
-import processing.core.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.event.*;
-import javax.swing.text.*;
-
-
-/**
- * Color selector tool for the Tools menu.
- *
- * Using the keyboard shortcuts, you can copy/paste the values for the
- * colors and paste them into your program. We didn't do any sort of
- * auto-insert of colorMode() or fill() or stroke() code cuz we couldn't
- * decide on a good way to do this.. your contributions welcome).
- */
-public class ColorSelector implements Tool, DocumentListener {
-
- Editor editor;
- JFrame frame;
-
- int hue, saturation, brightness; // range 360, 100, 100
- int red, green, blue; // range 256, 256, 256
-
- ColorRange range;
- ColorSlider slider;
-
- JTextField hueField, saturationField, brightnessField;
- JTextField redField, greenField, blueField;
-
- JTextField hexField;
-
- JPanel colorPanel;
-
-
- public String getMenuTitle() {
- return "Color Selector";
- }
-
-
- public void init(Editor editor) {
- this.editor = editor;
-
- frame = new JFrame("Color Selector");
- frame.getContentPane().setLayout(new BorderLayout());
-
- Box box = Box.createHorizontalBox();
- box.setBorder(new EmptyBorder(12, 12, 12, 12));
-
- range = new ColorRange();
- range.init();
- Box rangeBox = new Box(BoxLayout.Y_AXIS);
- rangeBox.setAlignmentY(0);
- rangeBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
- rangeBox.add(range);
- box.add(rangeBox);
- box.add(Box.createHorizontalStrut(10));
-
- slider = new ColorSlider();
- slider.init();
- Box sliderBox = new Box(BoxLayout.Y_AXIS);
- sliderBox.setAlignmentY(0);
- sliderBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
- sliderBox.add(slider);
- box.add(sliderBox);
- box.add(Box.createHorizontalStrut(10));
-
- box.add(createColorFields());
- box.add(Box.createHorizontalStrut(10));
-
- frame.getContentPane().add(box, BorderLayout.CENTER);
- frame.pack();
- frame.setResizable(false);
-
- // these don't help either.. they fix the component size but
- // leave a gap where the component is located
- //range.setSize(256, 256);
- //slider.setSize(256, 20);
-
- Dimension size = frame.getSize();
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- frame.setLocation((screen.width - size.width) / 2,
- (screen.height - size.height) / 2);
-
- frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- frame.setVisible(false);
- }
- });
- Base.registerWindowCloseKeys(frame.getRootPane(), new ActionListener() {
- public void actionPerformed(ActionEvent actionEvent) {
- frame.setVisible(false);
- }
- });
-
- Base.setIcon(frame);
-
- hueField.getDocument().addDocumentListener(this);
- saturationField.getDocument().addDocumentListener(this);
- brightnessField.getDocument().addDocumentListener(this);
- redField.getDocument().addDocumentListener(this);
- greenField.getDocument().addDocumentListener(this);
- blueField.getDocument().addDocumentListener(this);
- hexField.getDocument().addDocumentListener(this);
-
- hexField.setText("FFFFFF");
- }
-
-
- public void run() {
- frame.setVisible(true);
- // You've got to be f--ing kidding me.. why did the following line
- // get deprecated for the pile of s-- that follows it?
- //frame.setCursor(Cursor.CROSSHAIR_CURSOR);
- frame.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
- }
-
-
- public void changedUpdate(DocumentEvent e) {
- //System.out.println("changed");
- }
-
- public void removeUpdate(DocumentEvent e) {
- //System.out.println("remove");
- }
-
-
- boolean updating;
-
- public void insertUpdate(DocumentEvent e) {
- if (updating) return; // don't update forever recursively
- updating = true;
-
- Document doc = e.getDocument();
- if (doc == hueField.getDocument()) {
- hue = bounded(hue, hueField, 359);
- updateRGB();
- updateHex();
-
- } else if (doc == saturationField.getDocument()) {
- saturation = bounded(saturation, saturationField, 99);
- updateRGB();
- updateHex();
-
- } else if (doc == brightnessField.getDocument()) {
- brightness = bounded(brightness, brightnessField, 99);
- updateRGB();
- updateHex();
-
- } else if (doc == redField.getDocument()) {
- red = bounded(red, redField, 255);
- updateHSB();
- updateHex();
-
- } else if (doc == greenField.getDocument()) {
- green = bounded(green, greenField, 255);
- updateHSB();
- updateHex();
-
- } else if (doc == blueField.getDocument()) {
- blue = bounded(blue, blueField, 255);
- updateHSB();
- updateHex();
-
- } else if (doc == hexField.getDocument()) {
- String str = hexField.getText();
- while (str.length() < 6) {
- str += "0";
- }
- if (str.length() > 6) {
- str = str.substring(0, 6);
- }
- updateRGB2(Integer.parseInt(str, 16));
- updateHSB();
- }
- range.redraw();
- slider.redraw();
- colorPanel.repaint();
- updating = false;
- }
-
-
- /**
- * Set the RGB values based on the current HSB values.
- */
- protected void updateRGB() {
- int rgb = Color.HSBtoRGB((float)hue / 359f,
- (float)saturation / 99f,
- (float)brightness / 99f);
- updateRGB2(rgb);
- }
-
-
- /**
- * Set the RGB values based on a calculated ARGB int.
- * Used by both updateRGB() to set the color from the HSB values,
- * and by updateHex(), to unpack the hex colors and assign them.
- */
- protected void updateRGB2(int rgb) {
- red = (rgb >> 16) & 0xff;
- green = (rgb >> 8) & 0xff;
- blue = rgb & 0xff;
-
- redField.setText(String.valueOf(red));
- greenField.setText(String.valueOf(green));
- blueField.setText(String.valueOf(blue));
- }
-
-
- /**
- * Set the HSB values based on the current RGB values.
- */
- protected void updateHSB() {
- float hsb[] = new float[3];
- Color.RGBtoHSB(red, green, blue, hsb);
-
- hue = (int) (hsb[0] * 359.0f);
- saturation = (int) (hsb[1] * 99.0f);
- brightness = (int) (hsb[2] * 99.0f);
-
- hueField.setText(String.valueOf(hue));
- saturationField.setText(String.valueOf(saturation));
- brightnessField.setText(String.valueOf(brightness));
- }
-
-
- protected void updateHex() {
- hexField.setText(PApplet.hex(red, 2) +
- PApplet.hex(green, 2) +
- PApplet.hex(blue, 2));
- }
-
-
- /**
- * Get the bounded value for a specific range. If the value is outside
- * the max, you can't edit right away, so just act as if it's already
- * been bounded and return the bounded value, then fire an event to set
- * it to the value that was just returned.
- */
- protected int bounded(int current, final JTextField field, final int max) {
- String text = field.getText();
- if (text.length() == 0) {
- return 0;
- }
- try {
- int value = Integer.parseInt(text);
- if (value > max) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- field.setText(String.valueOf(max));
- }
- });
- return max;
- }
- return value;
-
- } catch (NumberFormatException e) {
- return current; // should not be reachable
- }
- }
-
-
- protected Container createColorFields() {
- Box box = Box.createVerticalBox();
- box.setAlignmentY(0);
-
- colorPanel = new JPanel() {
- public void paintComponent(Graphics g) {
- g.setColor(new Color(red, green, blue));
- Dimension size = getSize();
- g.fillRect(0, 0, size.width, size.height);
- }
- };
- colorPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
- Dimension dim = new Dimension(60, 40);
- colorPanel.setMinimumSize(dim);
- //colorPanel.setMaximumSize(dim);
- //colorPanel.setPreferredSize(dim);
- box.add(colorPanel);
- box.add(Box.createVerticalStrut(10));
-
- Box row;
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("H:"));
- row.add(hueField = new NumberField(4, false));
- row.add(new JLabel(" \u00B0")); // degree symbol
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(5));
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("S:"));
- row.add(saturationField = new NumberField(4, false));
- row.add(new JLabel(" %"));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(5));
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("B:"));
- row.add(brightnessField = new NumberField(4, false));
- row.add(new JLabel(" %"));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(10));
-
- //
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("R:"));
- row.add(redField = new NumberField(4, false));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(5));
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("G:"));
- row.add(greenField = new NumberField(4, false));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(5));
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("B:"));
- row.add(blueField = new NumberField(4, false));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(10));
-
- //
-
- row = Box.createHorizontalBox();
- row.add(createFixedLabel("#"));
- row.add(hexField = new NumberField(5, true));
- row.add(Box.createHorizontalGlue());
- box.add(row);
- box.add(Box.createVerticalStrut(10));
-
- box.add(Box.createVerticalGlue());
- return box;
- }
-
-
- int labelH;
-
- /**
- * return a label of a fixed width
- */
- protected JLabel createFixedLabel(String title) {
- JLabel label = new JLabel(title);
- if (labelH == 0) {
- labelH = label.getPreferredSize().height;
- }
- Dimension dim = new Dimension(20, labelH);
- label.setPreferredSize(dim);
- label.setMinimumSize(dim);
- label.setMaximumSize(dim);
- return label;
- }
-
-
- public class ColorRange extends PApplet {
-
- static final int WIDE = 256;
- static final int HIGH = 256;
-
- int lastX, lastY;
-
-
- public void setup() {
- size(WIDE, HIGH, P3D);
- noLoop();
-
- colorMode(HSB, 360, 256, 256);
- noFill();
- rectMode(CENTER);
- }
-
- public void draw() {
- if ((g == null) || (g.pixels == null)) return;
- if ((width != WIDE) || (height < HIGH)) {
- //System.out.println("bad size " + width + " " + height);
- return;
- }
-
- int index = 0;
- for (int j = 0; j < 256; j++) {
- for (int i = 0; i < 256; i++) {
- g.pixels[index++] = color(hue, i, 255 - j);
- }
- }
-
- stroke((brightness > 50) ? 0 : 255);
- rect(lastX, lastY, 9, 9);
- }
-
- public void mousePressed() {
- updateMouse();
- }
-
- public void mouseDragged() {
- updateMouse();
- }
-
- public void updateMouse() {
- if ((mouseX >= 0) && (mouseX < 256) &&
- (mouseY >= 0) && (mouseY < 256)) {
- int nsaturation = (int) (100 * (mouseX / 255.0f));
- int nbrightness = 100 - ((int) (100 * (mouseY / 255.0f)));
- saturationField.setText(String.valueOf(nsaturation));
- brightnessField.setText(String.valueOf(nbrightness));
-
- lastX = mouseX;
- lastY = mouseY;
- }
- }
-
- public Dimension getPreferredSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public Dimension getMinimumSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public Dimension getMaximumSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public void keyPressed() {
- if (key == ESC) {
- ColorSelector.this.frame.setVisible(false);
- // don't quit out of processing
- // http://dev.processing.org/bugs/show_bug.cgi?id=1006
- key = 0;
- }
- }
- }
-
-
- public class ColorSlider extends PApplet {
-
- static final int WIDE = 20;
- static final int HIGH = 256;
-
- public void setup() {
- size(WIDE, HIGH, P3D);
- colorMode(HSB, 255, 100, 100);
- noLoop();
- }
-
- public void draw() {
- if ((g == null) || (g.pixels == null)) return;
- if ((width != WIDE) || (height < HIGH)) {
- //System.out.println("bad size " + width + " " + height);
- return;
- }
-
- int index = 0;
- int sel = 255 - (int) (255 * (hue / 359f));
- for (int j = 0; j < 256; j++) {
- int c = color(255 - j, 100, 100);
- if (j == sel) c = 0xFF000000;
- for (int i = 0; i < WIDE; i++) {
- g.pixels[index++] = c;
- }
- }
- }
-
- public void mousePressed() {
- updateMouse();
- }
-
- public void mouseDragged() {
- updateMouse();
- }
-
- public void updateMouse() {
- if ((mouseX >= 0) && (mouseX < 256) &&
- (mouseY >= 0) && (mouseY < 256)) {
- int nhue = 359 - (int) (359 * (mouseY / 255.0f));
- hueField.setText(String.valueOf(nhue));
- }
- }
-
- public Dimension getPreferredSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public Dimension getMinimumSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public Dimension getMaximumSize() {
- return new Dimension(WIDE, HIGH);
- }
-
- public void keyPressed() {
- if (key == ESC) {
- ColorSelector.this.frame.setVisible(false);
- // don't quit out of processing
- // http://dev.processing.org/bugs/show_bug.cgi?id=1006
- key = 0;
- }
- }
- }
-
-
- /**
- * Extension of JTextField that only allows numbers
- */
- class NumberField extends JTextField {
-
- public boolean allowHex;
-
- public NumberField(int cols, boolean allowHex) {
- super(cols);
- this.allowHex = allowHex;
- }
-
- protected Document createDefaultModel() {
- return new NumberDocument(this);
- }
-
- public Dimension getPreferredSize() {
- if (!allowHex) {
- return new Dimension(45, super.getPreferredSize().height);
- }
- return super.getPreferredSize();
- }
-
- public Dimension getMinimumSize() {
- return getPreferredSize();
- }
-
- public Dimension getMaximumSize() {
- return getPreferredSize();
- }
- }
-
-
- /**
- * Document model to go with JTextField that only allows numbers.
- */
- class NumberDocument extends PlainDocument {
-
- NumberField parentField;
-
- public NumberDocument(NumberField parentField) {
- this.parentField = parentField;
- //System.out.println("setting parent to " + parentSelector);
- }
-
- public void insertString(int offs, String str, AttributeSet a)
- throws BadLocationException {
-
- if (str == null) return;
-
- char chars[] = str.toCharArray();
- int charCount = 0;
- // remove any non-digit chars
- for (int i = 0; i < chars.length; i++) {
- boolean ok = Character.isDigit(chars[i]);
- if (parentField.allowHex) {
- if ((chars[i] >= 'A') && (chars[i] <= 'F')) ok = true;
- if ((chars[i] >= 'a') && (chars[i] <= 'f')) ok = true;
- }
- if (ok) {
- if (charCount != i) { // shift if necessary
- chars[charCount] = chars[i];
- }
- charCount++;
- }
- }
- super.insertString(offs, new String(chars, 0, charCount), a);
- // can't call any sort of methods on the enclosing class here
- // seems to have something to do with how Document objects are set up
- }
- }
-}
diff --git a/app/src/processing/app/tools/CreateFont.java b/app/src/processing/app/tools/CreateFont.java
deleted file mode 100644
index 62d2ce4c0..000000000
--- a/app/src/processing/app/tools/CreateFont.java
+++ /dev/null
@@ -1,813 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2004-10 Ben Fry and Casey Reas
- Copyright (c) 2001-04 Massachusetts Institute of Technology
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.app.tools;
-
-import processing.app.*;
-import processing.core.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.util.*;
-
-import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.event.*;
-
-
-/**
- * GUI tool for font creation heaven/hell.
- */
-public class CreateFont extends JFrame implements Tool {
- Editor editor;
- //Sketch sketch;
-
- Dimension windowSize;
-
- JList fontSelector;
- JTextField sizeSelector;
- JButton charsetButton;
- JCheckBox smoothBox;
- JComponent sample;
- JButton okButton;
- JTextField filenameField;
-
- HashMap table;
- boolean smooth = true;
-
- Font font;
-
- String[] list;
- int selection = -1;
-
- CharacterSelector charSelector;
-
-
- public CreateFont() {
- super("Create Font");
- }
-
-
- public String getMenuTitle() {
- return "Create Font...";
- }
-
-
- public void init(Editor editor) {
- this.editor = editor;
-
- Container paine = getContentPane();
- paine.setLayout(new BorderLayout()); //10, 10));
-
- JPanel pain = new JPanel();
- pain.setBorder(new EmptyBorder(13, 13, 13, 13));
- paine.add(pain, BorderLayout.CENTER);
-
- pain.setLayout(new BoxLayout(pain, BoxLayout.Y_AXIS));
-
- String labelText =
- "Use this tool to create bitmap fonts for your program.\n" +
- "Select a font and size, and click 'OK' to generate the font.\n" +
- "It will be added to the data folder of the current sketch.";
-
- JTextArea textarea = new JTextArea(labelText);
- textarea.setBorder(new EmptyBorder(10, 10, 20, 10));
- textarea.setBackground(null);
- textarea.setEditable(false);
- textarea.setHighlighter(null);
- textarea.setFont(new Font("Dialog", Font.PLAIN, 12));
- pain.add(textarea);
-
- // don't care about families starting with . or #
- // also ignore dialog, dialoginput, monospaced, serif, sansserif
-
- // getFontList is deprecated in 1.4, so this has to be used
- GraphicsEnvironment ge =
- GraphicsEnvironment.getLocalGraphicsEnvironment();
-
- Font fonts[] = ge.getAllFonts();
-
- String flist[] = new String[fonts.length];
- table = new HashMap();
-
- int index = 0;
- for (int i = 0; i < fonts.length; i++) {
- //String psname = fonts[i].getPSName();
- //if (psname == null) System.err.println("ps name is null");
-
- flist[index++] = fonts[i].getPSName();
- table.put(fonts[i].getPSName(), fonts[i]);
- }
-
- list = new String[index];
- System.arraycopy(flist, 0, list, 0, index);
-
- fontSelector = new JList(list);
- fontSelector.addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
- if (e.getValueIsAdjusting() == false) {
- selection = fontSelector.getSelectedIndex();
- okButton.setEnabled(true);
- update();
- }
- }
- });
-
- fontSelector.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- fontSelector.setVisibleRowCount(12);
- JScrollPane fontScroller = new JScrollPane(fontSelector);
- pain.add(fontScroller);
-
- Dimension d1 = new Dimension(13, 13);
- pain.add(new Box.Filler(d1, d1, d1));
-
- sample = new SampleComponent(this);
-
- // Seems that in some instances, no default font is set
- // http://dev.processing.org/bugs/show_bug.cgi?id=777
- sample.setFont(new Font("Dialog", Font.PLAIN, 12));
-
- pain.add(sample);
-
- Dimension d2 = new Dimension(6, 6);
- pain.add(new Box.Filler(d2, d2, d2));
-
- JPanel panel = new JPanel();
- panel.add(new JLabel("Size:"));
- sizeSelector = new JTextField(" 48 ");
- sizeSelector.getDocument().addDocumentListener(new DocumentListener() {
- public void insertUpdate(DocumentEvent e) { update(); }
- public void removeUpdate(DocumentEvent e) { update(); }
- public void changedUpdate(DocumentEvent e) { }
- });
- panel.add(sizeSelector);
-
- smoothBox = new JCheckBox("Smooth");
- smoothBox.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- smooth = smoothBox.isSelected();
- update();
- }
- });
- smoothBox.setSelected(smooth);
- panel.add(smoothBox);
-
-// allBox = new JCheckBox("All Characters");
-// allBox.addActionListener(new ActionListener() {
-// public void actionPerformed(ActionEvent e) {
-// all = allBox.isSelected();
-// }
-// });
-// allBox.setSelected(all);
-// panel.add(allBox);
- charsetButton = new JButton("Characters...");
- charsetButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- //showCharacterList();
- charSelector.setVisible(true);
- }
- });
- panel.add(charsetButton);
-
- pain.add(panel);
-
- JPanel filestuff = new JPanel();
- filestuff.add(new JLabel("Filename:"));
- filestuff.add(filenameField = new JTextField(20));
- filestuff.add(new JLabel(".vlw"));
- pain.add(filestuff);
-
- JPanel buttons = new JPanel();
- JButton cancelButton = new JButton("Cancel");
- cancelButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- setVisible(false);
- }
- });
- okButton = new JButton("OK");
- okButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- build();
- }
- });
- okButton.setEnabled(false);
-
- buttons.add(cancelButton);
- buttons.add(okButton);
- pain.add(buttons);
-
- JRootPane root = getRootPane();
- root.setDefaultButton(okButton);
- ActionListener disposer = new ActionListener() {
- public void actionPerformed(ActionEvent actionEvent) {
- setVisible(false);
- }
- };
- Base.registerWindowCloseKeys(root, disposer);
- Base.setIcon(this);
-
- setResizable(false);
- pack();
-
- // do this after pack so it doesn't affect layout
- sample.setFont(new Font(list[0], Font.PLAIN, 48));
-
- fontSelector.setSelectedIndex(0);
-
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- windowSize = getSize();
-
- setLocation((screen.width - windowSize.width) / 2,
- (screen.height - windowSize.height) / 2);
-
- // create this behind the scenes
- charSelector = new CharacterSelector();
- }
-
-
- public void run() {
- setVisible(true);
- }
-
-
- public void update() {
- int fontsize = 0;
- try {
- fontsize = Integer.parseInt(sizeSelector.getText().trim());
- //System.out.println("'" + sizeSelector.getText() + "'");
- } catch (NumberFormatException e2) { }
-
- // if a deselect occurred, selection will be -1
- if ((fontsize > 0) && (fontsize < 256) && (selection != -1)) {
- //font = new Font(list[selection], Font.PLAIN, fontsize);
- Font instance = (Font) table.get(list[selection]);
- font = instance.deriveFont(Font.PLAIN, fontsize);
- //System.out.println("setting font to " + font);
- sample.setFont(font);
-
- String filenameSuggestion = list[selection].replace(' ', '_');
- filenameSuggestion += "-" + fontsize;
- filenameField.setText(filenameSuggestion);
- }
- }
-
-
- public void build() {
- int fontsize = 0;
- try {
- fontsize = Integer.parseInt(sizeSelector.getText().trim());
- } catch (NumberFormatException e) { }
-
- if (fontsize <= 0) {
- JOptionPane.showMessageDialog(this, "Bad font size, try again.",
- "Badness", JOptionPane.WARNING_MESSAGE);
- return;
- }
-
- String filename = filenameField.getText().trim();
- if (filename.length() == 0) {
- JOptionPane.showMessageDialog(this, "Enter a file name for the font.",
- "Lameness", JOptionPane.WARNING_MESSAGE);
- return;
- }
- if (!filename.endsWith(".vlw")) {
- filename += ".vlw";
- }
-
- // Please implement me properly. The schematic is below, but not debugged.
- // http://dev.processing.org/bugs/show_bug.cgi?id=1464
-
-// final String filename2 = filename;
-// final int fontsize2 = fontsize;
-// SwingUtilities.invokeLater(new Runnable() {
-// public void run() {
- try {
- Font instance = (Font) table.get(list[selection]);
- font = instance.deriveFont(Font.PLAIN, fontsize);
- //PFont f = new PFont(font, smooth, all ? null : PFont.CHARSET);
- PFont f = new PFont(font, smooth, charSelector.getCharacters());
-
-// PFont f = new PFont(font, smooth, null);
-// char[] charset = charSelector.getCharacters();
-// ProgressMonitor progressMonitor = new ProgressMonitor(CreateFont.this,
-// "Creating font", "", 0, charset.length);
-// progressMonitor.setProgress(0);
-// for (int i = 0; i < charset.length; i++) {
-// System.out.println(charset[i]);
-// f.index(charset[i]); // load this char
-// progressMonitor.setProgress(i+1);
-// }
-
- // make sure the 'data' folder exists
- File folder = editor.getSketch().prepareDataFolder();
- f.save(new FileOutputStream(new File(folder, filename)));
-
- } catch (IOException e) {
- JOptionPane.showMessageDialog(CreateFont.this,
- "An error occurred while creating font.",
- "No font for you",
- JOptionPane.WARNING_MESSAGE);
- e.printStackTrace();
- }
-// }
-// });
-
- setVisible(false);
- }
-
-
- /**
- * make the window vertically resizable
- */
- public Dimension getMaximumSize() {
- return new Dimension(windowSize.width, 2000);
-}
-
-
- public Dimension getMinimumSize() {
- return windowSize;
- }
-
-
- /*
- public void show(File targetFolder) {
- this.targetFolder = targetFolder;
- show();
- }
- */
-}
-
-
-/**
- * Component that draws the sample text. This is its own subclassed component
- * because Mac OS X controls seem to reset the RenderingHints for smoothing
- * so that they cannot be overridden properly for JLabel or JTextArea.
- * @author fry
- */
-class SampleComponent extends JComponent {
- // see http://rinkworks.com/words/pangrams.shtml
- String text =
- "Forsaking monastic tradition, twelve jovial friars gave up their " +
- "vocation for a questionable existence on the flying trapeze.";
- int high = 80;
-
- CreateFont parent;
-
- public SampleComponent(CreateFont p) {
- this.parent = p;
-
- // and yet, we still need an inner class to handle the basics.
- // or no, maybe i'll refactor this as a separate class!
- // maybe a few getters and setters? mmm?
- addMouseListener(new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- String input =
- (String) JOptionPane.showInputDialog(parent,
- "Enter new sample text:",
- "Sample Text",
- JOptionPane.PLAIN_MESSAGE,
- null, // icon
- null, // choices
- text);
- if (input != null) {
- text = input;
- parent.repaint();
- }
- }
- });
- }
-
- public void paintComponent(Graphics g) {
-// System.out.println("smoothing set to " + smooth);
- Graphics2D g2 = (Graphics2D) g;
- g2.setColor(Color.WHITE);
- Dimension dim = getSize();
- g2.fillRect(0, 0, dim.width, dim.height);
- g2.setColor(Color.BLACK);
-
- g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- parent.smooth ?
- RenderingHints.VALUE_TEXT_ANTIALIAS_ON :
- RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
- // add this one as well (after 1.0.9)
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- parent.smooth ?
- RenderingHints.VALUE_ANTIALIAS_ON :
- RenderingHints.VALUE_ANTIALIAS_OFF);
- //super.paintComponent(g2);
- Font font = getFont();
- int ascent = g2.getFontMetrics().getAscent();
-// System.out.println(f.getName());
- g2.setFont(font);
- g2.drawString(text, 5, dim.height - (dim.height - ascent) / 2);
- }
-
- public Dimension getPreferredSize() {
- return new Dimension(400, high);
- }
-
- public Dimension getMaximumSize() {
- return new Dimension(10000, high);
- }
-
- public Dimension getMinimumSize() {
- return new Dimension(100, high);
- }
-}
-
-
-/**
- * Frame for selecting which characters will be included with the font.
- */
-class CharacterSelector extends JFrame {
- JRadioButton defaultCharsButton;
- JRadioButton allCharsButton;
- JRadioButton unicodeCharsButton;
- JScrollPane unicodeBlockScroller;
- JList charsetList;
-
-
- public CharacterSelector() {
- super("Character Selector");
-
- charsetList = new CheckBoxList();
- DefaultListModel model = new DefaultListModel();
- charsetList.setModel(model);
- for (String item : blockNames) {
- model.addElement(new JCheckBox(item));
- }
-
- unicodeBlockScroller =
- new JScrollPane(charsetList,
- ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
-
- Container outer = getContentPane();
- outer.setLayout(new BorderLayout());
-
- JPanel pain = new JPanel();
- pain.setBorder(new EmptyBorder(13, 13, 13, 13));
- outer.add(pain, BorderLayout.CENTER);
-
- pain.setLayout(new BoxLayout(pain, BoxLayout.Y_AXIS));
-
- String labelText =
- "Default characters will include most bitmaps for Mac OS\n" +
- "and Windows Latin scripts. Including all characters may\n" +
- "require large amounts of memory for all of the bitmaps.\n" +
- "For greater control, you can select specific Unicode blocks.";
- JTextArea textarea = new JTextArea(labelText);
- textarea.setBorder(new EmptyBorder(13, 8, 13, 8));
- textarea.setBackground(null);
- textarea.setEditable(false);
- textarea.setHighlighter(null);
- textarea.setFont(new Font("Dialog", Font.PLAIN, 12));
- pain.add(textarea);
-
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- //System.out.println("action " + unicodeCharsButton.isSelected());
- //unicodeBlockScroller.setEnabled(unicodeCharsButton.isSelected());
- charsetList.setEnabled(unicodeCharsButton.isSelected());
- }
- };
- defaultCharsButton = new JRadioButton("Default Characters");
- allCharsButton = new JRadioButton("All Characters");
- unicodeCharsButton = new JRadioButton("Specific Unicode Blocks");
-
- defaultCharsButton.addActionListener(listener);
- allCharsButton.addActionListener(listener);
- unicodeCharsButton.addActionListener(listener);
-
- ButtonGroup group = new ButtonGroup();
- group.add(defaultCharsButton);
- group.add(allCharsButton);
- group.add(unicodeCharsButton);
-
- JPanel radioPanel = new JPanel();
- //radioPanel.setBackground(Color.red);
- radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS));
- radioPanel.add(defaultCharsButton);
- radioPanel.add(allCharsButton);
- radioPanel.add(unicodeCharsButton);
-
- JPanel rightStuff = new JPanel();
- rightStuff.setLayout(new BoxLayout(rightStuff, BoxLayout.X_AXIS));
- rightStuff.add(radioPanel);
- rightStuff.add(Box.createHorizontalGlue());
- pain.add(rightStuff);
- pain.add(Box.createVerticalStrut(13));
-
-// pain.add(radioPanel);
-
-// pain.add(defaultCharsButton);
-// pain.add(allCharsButton);
-// pain.add(unicodeCharsButton);
-
- defaultCharsButton.setSelected(true);
- charsetList.setEnabled(false);
-
- //frame.getContentPane().add(scroller);
- pain.add(unicodeBlockScroller);
- pain.add(Box.createVerticalStrut(8));
-
- JPanel buttons = new JPanel();
- JButton okButton = new JButton("OK");
- okButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- setVisible(false);
- }
- });
- okButton.setEnabled(true);
- buttons.add(okButton);
- pain.add(buttons);
-
- JRootPane root = getRootPane();
- root.setDefaultButton(okButton);
- ActionListener disposer = new ActionListener() {
- public void actionPerformed(ActionEvent actionEvent) {
- setVisible(false);
- }
- };
- Base.registerWindowCloseKeys(root, disposer);
- Base.setIcon(this);
-
- pack();
-
- Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
- Dimension windowSize = getSize();
-
- setLocation((screen.width - windowSize.width) / 2,
- (screen.height - windowSize.height) / 2);
- }
-
-
- protected char[] getCharacters() {
- if (defaultCharsButton.isSelected()) {
- return PFont.CHARSET;
- }
-
- char[] charset = new char[65536];
- if (allCharsButton.isSelected()) {
- for (int i = 0; i < 0xFFFF; i++) {
- charset[i] = (char) i;
- }
- } else {
- DefaultListModel model = (DefaultListModel) charsetList.getModel();
- int index = 0;
- for (int i = 0; i < BLOCKS.length; i++) {
- if (((JCheckBox) model.get(i)).isSelected()) {
- for (int j = blockStart[i]; j <= blockStop[i]; j++) {
- charset[index++] = (char) j;
- }
- }
- }
- charset = PApplet.subset(charset, 0, index);
- }
- //System.out.println("Creating font with " + charset.length + " characters.");
- return charset;
- }
-
-
- // http://www.unicode.org/Public/UNIDATA/Blocks.txt
- static final String[] BLOCKS = {
- "0000..007F; Basic Latin",
- "0080..00FF; Latin-1 Supplement",
- "0100..017F; Latin Extended-A",
- "0180..024F; Latin Extended-B",
- "0250..02AF; IPA Extensions",
- "02B0..02FF; Spacing Modifier Letters",
- "0300..036F; Combining Diacritical Marks",
- "0370..03FF; Greek and Coptic",
- "0400..04FF; Cyrillic",
- "0500..052F; Cyrillic Supplement",
- "0530..058F; Armenian",
- "0590..05FF; Hebrew",
- "0600..06FF; Arabic",
- "0700..074F; Syriac",
- "0750..077F; Arabic Supplement",
- "0780..07BF; Thaana",
- "07C0..07FF; NKo",
- "0800..083F; Samaritan",
- "0900..097F; Devanagari",
- "0980..09FF; Bengali",
- "0A00..0A7F; Gurmukhi",
- "0A80..0AFF; Gujarati",
- "0B00..0B7F; Oriya",
- "0B80..0BFF; Tamil",
- "0C00..0C7F; Telugu",
- "0C80..0CFF; Kannada",
- "0D00..0D7F; Malayalam",
- "0D80..0DFF; Sinhala",
- "0E00..0E7F; Thai",
- "0E80..0EFF; Lao",
- "0F00..0FFF; Tibetan",
- "1000..109F; Myanmar",
- "10A0..10FF; Georgian",
- "1100..11FF; Hangul Jamo",
- "1200..137F; Ethiopic",
- "1380..139F; Ethiopic Supplement",
- "13A0..13FF; Cherokee",
- "1400..167F; Unified Canadian Aboriginal Syllabics",
- "1680..169F; Ogham",
- "16A0..16FF; Runic",
- "1700..171F; Tagalog",
- "1720..173F; Hanunoo",
- "1740..175F; Buhid",
- "1760..177F; Tagbanwa",
- "1780..17FF; Khmer",
- "1800..18AF; Mongolian",
- "18B0..18FF; Unified Canadian Aboriginal Syllabics Extended",
- "1900..194F; Limbu",
- "1950..197F; Tai Le",
- "1980..19DF; New Tai Lue",
- "19E0..19FF; Khmer Symbols",
- "1A00..1A1F; Buginese",
- "1A20..1AAF; Tai Tham",
- "1B00..1B7F; Balinese",
- "1B80..1BBF; Sundanese",
- "1C00..1C4F; Lepcha",
- "1C50..1C7F; Ol Chiki",
- "1CD0..1CFF; Vedic Extensions",
- "1D00..1D7F; Phonetic Extensions",
- "1D80..1DBF; Phonetic Extensions Supplement",
- "1DC0..1DFF; Combining Diacritical Marks Supplement",
- "1E00..1EFF; Latin Extended Additional",
- "1F00..1FFF; Greek Extended",
- "2000..206F; General Punctuation",
- "2070..209F; Superscripts and Subscripts",
- "20A0..20CF; Currency Symbols",
- "20D0..20FF; Combining Diacritical Marks for Symbols",
- "2100..214F; Letterlike Symbols",
- "2150..218F; Number Forms",
- "2190..21FF; Arrows",
- "2200..22FF; Mathematical Operators",
- "2300..23FF; Miscellaneous Technical",
- "2400..243F; Control Pictures",
- "2440..245F; Optical Character Recognition",
- "2460..24FF; Enclosed Alphanumerics",
- "2500..257F; Box Drawing",
- "2580..259F; Block Elements",
- "25A0..25FF; Geometric Shapes",
- "2600..26FF; Miscellaneous Symbols",
- "2700..27BF; Dingbats",
- "27C0..27EF; Miscellaneous Mathematical Symbols-A",
- "27F0..27FF; Supplemental Arrows-A",
- "2800..28FF; Braille Patterns",
- "2900..297F; Supplemental Arrows-B",
- "2980..29FF; Miscellaneous Mathematical Symbols-B",
- "2A00..2AFF; Supplemental Mathematical Operators",
- "2B00..2BFF; Miscellaneous Symbols and Arrows",
- "2C00..2C5F; Glagolitic",
- "2C60..2C7F; Latin Extended-C",
- "2C80..2CFF; Coptic",
- "2D00..2D2F; Georgian Supplement",
- "2D30..2D7F; Tifinagh",
- "2D80..2DDF; Ethiopic Extended",
- "2DE0..2DFF; Cyrillic Extended-A",
- "2E00..2E7F; Supplemental Punctuation",
- "2E80..2EFF; CJK Radicals Supplement",
- "2F00..2FDF; Kangxi Radicals",
- "2FF0..2FFF; Ideographic Description Characters",
- "3000..303F; CJK Symbols and Punctuation",
- "3040..309F; Hiragana",
- "30A0..30FF; Katakana",
- "3100..312F; Bopomofo",
- "3130..318F; Hangul Compatibility Jamo",
- "3190..319F; Kanbun",
- "31A0..31BF; Bopomofo Extended",
- "31C0..31EF; CJK Strokes",
- "31F0..31FF; Katakana Phonetic Extensions",
- "3200..32FF; Enclosed CJK Letters and Months",
- "3300..33FF; CJK Compatibility",
- "3400..4DBF; CJK Unified Ideographs Extension A",
- "4DC0..4DFF; Yijing Hexagram Symbols",
- "4E00..9FFF; CJK Unified Ideographs",
- "A000..A48F; Yi Syllables",
- "A490..A4CF; Yi Radicals",
- "A4D0..A4FF; Lisu",
- "A500..A63F; Vai",
- "A640..A69F; Cyrillic Extended-B",
- "A6A0..A6FF; Bamum",
- "A700..A71F; Modifier Tone Letters",
- "A720..A7FF; Latin Extended-D",
- "A800..A82F; Syloti Nagri",
- "A830..A83F; Common Indic Number Forms",
- "A840..A87F; Phags-pa",
- "A880..A8DF; Saurashtra",
- "A8E0..A8FF; Devanagari Extended",
- "A900..A92F; Kayah Li",
- "A930..A95F; Rejang",
- "A960..A97F; Hangul Jamo Extended-A",
- "A980..A9DF; Javanese",
- "AA00..AA5F; Cham",
- "AA60..AA7F; Myanmar Extended-A",
- "AA80..AADF; Tai Viet",
- "ABC0..ABFF; Meetei Mayek",
- "AC00..D7AF; Hangul Syllables",
- "D7B0..D7FF; Hangul Jamo Extended-B",
- "D800..DB7F; High Surrogates",
- "DB80..DBFF; High Private Use Surrogates",
- "DC00..DFFF; Low Surrogates",
- "E000..F8FF; Private Use Area",
- "F900..FAFF; CJK Compatibility Ideographs",
- "FB00..FB4F; Alphabetic Presentation Forms",
- "FB50..FDFF; Arabic Presentation Forms-A",
- "FE00..FE0F; Variation Selectors",
- "FE10..FE1F; Vertical Forms",
- "FE20..FE2F; Combining Half Marks",
- "FE30..FE4F; CJK Compatibility Forms",
- "FE50..FE6F; Small Form Variants",
- "FE70..FEFF; Arabic Presentation Forms-B",
- "FF00..FFEF; Halfwidth and Fullwidth Forms",
- "FFF0..FFFF; Specials"
- };
-
- static String[] blockNames;
- static int[] blockStart;
- static int[] blockStop;
- static {
- int count = BLOCKS.length;
- blockNames = new String[count];
- blockStart = new int[count];
- blockStop = new int[count];
- for (int i = 0; i < count; i++) {
- String line = BLOCKS[i];
- blockStart[i] = PApplet.unhex(line.substring(0, 4));
- blockStop[i] = PApplet.unhex(line.substring(6, 10));
- blockNames[i] = line.substring(12);
- }
-// PApplet.println(codePointStop);
-// PApplet.println(codePoints);
- }
-}
-
-
-// Code for this CheckBoxList class found on the net, though I've lost the
-// link. If you run across the original version, please let me know so that
-// the original author can be credited properly. It was from a snippet
-// collection, but it seems to have been picked up so many places with others
-// placing their copyright on it, that I haven't been able to determine the
-// original author. [fry 20100216]
-class CheckBoxList extends JList {
- protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
-
- public CheckBoxList() {
- setCellRenderer(new CellRenderer());
-
- addMouseListener(new MouseAdapter() {
- public void mousePressed(MouseEvent e) {
- if (isEnabled()) {
- int index = locationToIndex(e.getPoint());
-
- if (index != -1) {
- JCheckBox checkbox = (JCheckBox)
- getModel().getElementAt(index);
- checkbox.setSelected(!checkbox.isSelected());
- repaint();
- }
- }
- }
- });
- setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- }
-
-
- protected class CellRenderer implements ListCellRenderer {
- public Component getListCellRendererComponent(JList list, Object value,
- int index, boolean isSelected,
- boolean cellHasFocus) {
- JCheckBox checkbox = (JCheckBox) value;
- checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground());
- checkbox.setForeground(isSelected ? getSelectionForeground() : getForeground());
- //checkbox.setEnabled(isEnabled());
- checkbox.setEnabled(list.isEnabled());
- checkbox.setFont(getFont());
- checkbox.setFocusPainted(false);
- checkbox.setBorderPainted(true);
- checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
- return checkbox;
- }
- }
-}
\ No newline at end of file