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