mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
Initial sync with Processing 6406. Compiles and runs (on Mac OS X) but probably very buggy.
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-09 Ben Fry and Casey Reas
|
||||
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
|
||||
@ -42,7 +42,10 @@ import processing.core.*;
|
||||
*/
|
||||
public class Base {
|
||||
public static final int REVISION = 18;
|
||||
/** This might be replaced by main() if there's a lib/version.txt file. */
|
||||
static String VERSION_NAME = "0018";
|
||||
/** Set true if this a proper release rather than a numbered revision. */
|
||||
static public boolean RELEASE = false;
|
||||
|
||||
static HashMap<Integer, String> platformNames = new HashMap<Integer, String>();
|
||||
static {
|
||||
@ -101,31 +104,16 @@ public class Base {
|
||||
// ArrayList editors = Collections.synchronizedList(new ArrayList<Editor>());
|
||||
Editor activeEditor;
|
||||
|
||||
// int nextEditorX;
|
||||
// int nextEditorY;
|
||||
|
||||
// import com.sun.jna.Library;
|
||||
// import com.sun.jna.Native;
|
||||
|
||||
// public interface CLibrary extends Library {
|
||||
// CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
|
||||
// int setenv(String name, String value, int overwrite);
|
||||
// String getenv(String name);
|
||||
// int unsetenv(String name);
|
||||
// int putenv(String string);
|
||||
// }
|
||||
|
||||
|
||||
static public void main(String args[]) {
|
||||
// /Users/fry/coconut/sketchbook/libraries/gsvideo/library
|
||||
// CLibrary clib = CLibrary.INSTANCE;
|
||||
// clib.setenv("DYLD_LIBRARY_PATH", "/Users/fry/coconut/sketchbook/libraries/gsvideo/library", 1);
|
||||
// System.out.println("env is now " + clib.getenv("DYLD_LIBRARY_PATH"));
|
||||
|
||||
try {
|
||||
File versionFile = getContentFile("lib/version.txt");
|
||||
if (versionFile.exists()) {
|
||||
VERSION_NAME = PApplet.loadStrings(versionFile)[0];
|
||||
String version = PApplet.loadStrings(versionFile)[0];
|
||||
if (!version.equals(VERSION_NAME)) {
|
||||
VERSION_NAME = version;
|
||||
RELEASE = true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -187,10 +175,12 @@ public class Base {
|
||||
try {
|
||||
platform.setLookAndFeel();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Non-fatal error while setting the Look & Feel.");
|
||||
System.err.println("The error message follows, however Arduino should run fine.");
|
||||
System.err.println(e.getMessage());
|
||||
//e.printStackTrace();
|
||||
String mess = e.getMessage();
|
||||
if (mess.indexOf("ch.randelshofer.quaqua.QuaquaLookAndFeel") == -1) {
|
||||
System.err.println("Non-fatal error while setting the Look & Feel.");
|
||||
System.err.println("The error message follows, however Arduino should run fine.");
|
||||
System.err.println(mess);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a location for untitled sketches
|
||||
@ -213,7 +203,7 @@ public class Base {
|
||||
|
||||
static protected void initPlatform() {
|
||||
try {
|
||||
Class platformClass = Class.forName("processing.app.Platform");
|
||||
Class<?> platformClass = Class.forName("processing.app.Platform");
|
||||
if (Base.isMacOS()) {
|
||||
platformClass = Class.forName("processing.app.macosx.Platform");
|
||||
} else if (Base.isWindows()) {
|
||||
@ -270,7 +260,7 @@ public class Base {
|
||||
}
|
||||
}
|
||||
|
||||
// If not path is set, get the default sketchbook folder for this platform
|
||||
// If no path is set, get the default sketchbook folder for this platform
|
||||
if (sketchbookPath == null) {
|
||||
File defaultFolder = getDefaultSketchbookFolder();
|
||||
Preferences.set("sketchbook.path", defaultFolder.getAbsolutePath());
|
||||
@ -456,8 +446,8 @@ public class Base {
|
||||
|
||||
protected int[] nextEditorLocation() {
|
||||
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
int defaultWidth = Preferences.getInteger("default.window.width");
|
||||
int defaultHeight = Preferences.getInteger("default.window.height");
|
||||
int defaultWidth = Preferences.getInteger("editor.window.width.default");
|
||||
int defaultHeight = Preferences.getInteger("editor.window.height.default");
|
||||
|
||||
if (activeEditor == null) {
|
||||
// If no current active editor, use default placement
|
||||
@ -584,7 +574,7 @@ public class Base {
|
||||
* Replace the sketch in the current window with a new untitled document.
|
||||
*/
|
||||
public void handleNewReplace() {
|
||||
if (!activeEditor.checkModified(true)) {
|
||||
if (!activeEditor.checkModified()) {
|
||||
return; // sketch was modified, and user canceled
|
||||
}
|
||||
// Close the running window, avoid window boogers with multiple sketches
|
||||
@ -616,7 +606,7 @@ public class Base {
|
||||
* @param path Location of the primary pde file for the sketch.
|
||||
*/
|
||||
public void handleOpenReplace(String path) {
|
||||
if (!activeEditor.checkModified(true)) {
|
||||
if (!activeEditor.checkModified()) {
|
||||
return; // sketch was modified, and user canceled
|
||||
}
|
||||
// Close the running window, avoid window boogers with multiple sketches
|
||||
@ -758,8 +748,8 @@ public class Base {
|
||||
*/
|
||||
public boolean handleClose(Editor editor) {
|
||||
// Check if modified
|
||||
boolean immediate = editors.size() == 1;
|
||||
if (!editor.checkModified(immediate)) {
|
||||
// boolean immediate = editors.size() == 1;
|
||||
if (!editor.checkModified()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -862,7 +852,7 @@ public class Base {
|
||||
protected boolean handleQuitEach() {
|
||||
int index = 0;
|
||||
for (Editor editor : editors) {
|
||||
if (editor.checkModified(true)) {
|
||||
if (editor.checkModified()) {
|
||||
// Update to the new/final sketch path for this fella
|
||||
storeSketchPath(editor, index);
|
||||
index++;
|
||||
@ -914,7 +904,8 @@ public class Base {
|
||||
|
||||
// Add a list of all sketches and subfolders
|
||||
try {
|
||||
boolean sketches = addSketches(menu, getSketchbookFolder(), true);
|
||||
//boolean sketches = addSketches(menu, getSketchbookFolder(), true);
|
||||
boolean sketches = addSketches(menu, getSketchbookFolder());
|
||||
if (sketches) menu.addSeparator();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -923,11 +914,11 @@ public class Base {
|
||||
//System.out.println("rebuilding examples menu");
|
||||
// Add each of the subfolders of examples directly to the menu
|
||||
try {
|
||||
boolean found = addSketches(menu, examplesFolder, true);
|
||||
boolean found = addSketches(menu, examplesFolder);
|
||||
if (found) menu.addSeparator();
|
||||
found = addSketches(menu, getSketchbookLibrariesFolder(), true);
|
||||
found = addSketches(menu, getSketchbookLibrariesFolder());
|
||||
if (found) menu.addSeparator();
|
||||
addSketches(menu, librariesFolder, true);
|
||||
addSketches(menu, librariesFolder);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -939,7 +930,8 @@ public class Base {
|
||||
//new Exception().printStackTrace();
|
||||
try {
|
||||
menu.removeAll();
|
||||
addSketches(menu, getSketchbookFolder(), false);
|
||||
//addSketches(menu, getSketchbookFolder(), false);
|
||||
addSketches(menu, getSketchbookFolder());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -983,11 +975,11 @@ public class Base {
|
||||
//System.out.println("rebuilding examples menu");
|
||||
try {
|
||||
menu.removeAll();
|
||||
boolean found = addSketches(menu, examplesFolder, false);
|
||||
boolean found = addSketches(menu, examplesFolder);
|
||||
if (found) menu.addSeparator();
|
||||
found = addSketches(menu, getSketchbookLibrariesFolder(), false);
|
||||
found = addSketches(menu, getSketchbookLibrariesFolder());
|
||||
if (found) menu.addSeparator();
|
||||
addSketches(menu, librariesFolder, false);
|
||||
addSketches(menu, librariesFolder);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -1050,8 +1042,7 @@ public class Base {
|
||||
* should replace the sketch in the current window, or false when the
|
||||
* sketch should open in a new window.
|
||||
*/
|
||||
protected boolean addSketches(JMenu menu, File folder,
|
||||
final boolean openReplaces) throws IOException {
|
||||
protected boolean addSketches(JMenu menu, File folder) throws IOException {
|
||||
// skip .DS_Store files, etc (this shouldn't actually be necessary)
|
||||
if (!folder.isDirectory()) return false;
|
||||
|
||||
@ -1068,7 +1059,8 @@ public class Base {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String path = e.getActionCommand();
|
||||
if (new File(path).exists()) {
|
||||
if (openReplaces) {
|
||||
// if (openReplaces) {
|
||||
if ((e.getModifiers() & ActionEvent.SHIFT_MASK) == 0) {
|
||||
handleOpenReplace(path);
|
||||
} else {
|
||||
handleOpen(path);
|
||||
@ -1121,14 +1113,15 @@ public class Base {
|
||||
} else {
|
||||
// don't create an extra menu level for a folder named "examples"
|
||||
if (subfolder.getName().equals("examples")) {
|
||||
boolean found = addSketches(menu, subfolder, openReplaces); //, false);
|
||||
boolean found = addSketches(menu, subfolder);
|
||||
if (found) ifound = true;
|
||||
} else {
|
||||
// not a sketch folder, but maybe a subfolder containing sketches
|
||||
JMenu submenu = new JMenu(list[i]);
|
||||
// needs to be separate var
|
||||
// otherwise would set ifound to false
|
||||
boolean found = addSketches(submenu, subfolder, openReplaces); //, false);
|
||||
//boolean found = addSketches(submenu, subfolder, openReplaces); //, false);
|
||||
boolean found = addSketches(submenu, subfolder); //, false);
|
||||
if (found) {
|
||||
menu.add(submenu);
|
||||
ifound = true;
|
||||
@ -1319,6 +1312,11 @@ public class Base {
|
||||
// }
|
||||
|
||||
|
||||
static public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
|
||||
static public String getPlatformName() {
|
||||
String osname = System.getProperty("os.name");
|
||||
|
||||
@ -1714,12 +1712,11 @@ public class Base {
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Registers key events for a Ctrl-W and ESC with an ActionListener
|
||||
* that will take care of disposing the window.
|
||||
*/
|
||||
static public void registerWindowCloseKeys(JRootPane root, //Window window,
|
||||
static public void registerWindowCloseKeys(JRootPane root,
|
||||
ActionListener disposer) {
|
||||
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
root.registerKeyboardAction(disposer, stroke,
|
||||
@ -1836,6 +1833,129 @@ public class Base {
|
||||
// ...................................................................
|
||||
|
||||
|
||||
|
||||
// incomplete
|
||||
static public int showYesNoCancelQuestion(Editor editor, String title,
|
||||
String primary, String secondary) {
|
||||
if (!Base.isMacOS()) {
|
||||
int result =
|
||||
JOptionPane.showConfirmDialog(null, primary + "\n" + secondary, title,
|
||||
JOptionPane.YES_NO_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
return result;
|
||||
// if (result == JOptionPane.YES_OPTION) {
|
||||
//
|
||||
// } else if (result == JOptionPane.NO_OPTION) {
|
||||
// return true; // ok to continue
|
||||
//
|
||||
// } else if (result == JOptionPane.CANCEL_OPTION) {
|
||||
// return false;
|
||||
//
|
||||
// } else {
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
|
||||
} else {
|
||||
// Pane formatting adapted from the Quaqua guide
|
||||
// http://www.randelshofer.ch/quaqua/guide/joptionpane.html
|
||||
JOptionPane pane =
|
||||
new JOptionPane("<html> " +
|
||||
"<head> <style type=\"text/css\">"+
|
||||
"b { font: 13pt \"Lucida Grande\" }"+
|
||||
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
|
||||
"</style> </head>" +
|
||||
"<b>Do you want to save changes to this sketch<BR>" +
|
||||
" before closing?</b>" +
|
||||
"<p>If you don't save, your changes will be lost.",
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
String[] options = new String[] {
|
||||
"Save", "Cancel", "Don't Save"
|
||||
};
|
||||
pane.setOptions(options);
|
||||
|
||||
// highlight the safest option ala apple hig
|
||||
pane.setInitialValue(options[0]);
|
||||
|
||||
// on macosx, setting the destructive property places this option
|
||||
// away from the others at the lefthand side
|
||||
pane.putClientProperty("Quaqua.OptionPane.destructiveOption",
|
||||
new Integer(2));
|
||||
|
||||
JDialog dialog = pane.createDialog(editor, null);
|
||||
dialog.setVisible(true);
|
||||
|
||||
Object result = pane.getValue();
|
||||
if (result == options[0]) {
|
||||
return JOptionPane.YES_OPTION;
|
||||
} else if (result == options[1]) {
|
||||
return JOptionPane.CANCEL_OPTION;
|
||||
} else if (result == options[2]) {
|
||||
return JOptionPane.NO_OPTION;
|
||||
} else {
|
||||
return JOptionPane.CLOSED_OPTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//if (result == JOptionPane.YES_OPTION) {
|
||||
//
|
||||
// } else if (result == JOptionPane.NO_OPTION) {
|
||||
// return true; // ok to continue
|
||||
//
|
||||
// } else if (result == JOptionPane.CANCEL_OPTION) {
|
||||
// return false;
|
||||
//
|
||||
// } else {
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
|
||||
static public int showYesNoQuestion(Frame editor, String title,
|
||||
String primary, String secondary) {
|
||||
if (!Base.isMacOS()) {
|
||||
return JOptionPane.showConfirmDialog(editor,
|
||||
"<html><body>" +
|
||||
"<b>" + primary + "</b>" +
|
||||
"<br>" + secondary, title,
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
} else {
|
||||
// Pane formatting adapted from the Quaqua guide
|
||||
// http://www.randelshofer.ch/quaqua/guide/joptionpane.html
|
||||
JOptionPane pane =
|
||||
new JOptionPane("<html> " +
|
||||
"<head> <style type=\"text/css\">"+
|
||||
"b { font: 13pt \"Lucida Grande\" }"+
|
||||
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
|
||||
"</style> </head>" +
|
||||
"<b>" + primary + "</b>" +
|
||||
"<p>" + secondary + "</p>",
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
String[] options = new String[] {
|
||||
"Yes", "No"
|
||||
};
|
||||
pane.setOptions(options);
|
||||
|
||||
// highlight the safest option ala apple hig
|
||||
pane.setInitialValue(options[0]);
|
||||
|
||||
JDialog dialog = pane.createDialog(editor, null);
|
||||
dialog.setVisible(true);
|
||||
|
||||
Object result = pane.getValue();
|
||||
if (result == options[0]) {
|
||||
return JOptionPane.YES_OPTION;
|
||||
} else if (result == options[1]) {
|
||||
return JOptionPane.NO_OPTION;
|
||||
} else {
|
||||
return JOptionPane.CLOSED_OPTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a path to something in the Processing folder. Eventually this
|
||||
* may refer to the Contents subfolder of Processing.app, if we bundle things
|
||||
@ -1959,6 +2079,36 @@ public class Base {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read from a file with a bunch of attribute/value pairs
|
||||
* that are separated by = and ignore comments with #.
|
||||
*/
|
||||
static public HashMap<String,String> readSettings(File inputFile) {
|
||||
HashMap<String,String> outgoing = new HashMap<String,String>();
|
||||
if (!inputFile.exists()) return outgoing; // return empty hash
|
||||
|
||||
String lines[] = PApplet.loadStrings(inputFile);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
int hash = lines[i].indexOf('#');
|
||||
String line = (hash == -1) ?
|
||||
lines[i].trim() : lines[i].substring(0, hash).trim();
|
||||
if (line.length() == 0) continue;
|
||||
|
||||
int equals = line.indexOf('=');
|
||||
if (equals == -1) {
|
||||
System.err.println("ignoring illegal line in " + inputFile);
|
||||
System.err.println(" " + line);
|
||||
continue;
|
||||
}
|
||||
String attr = line.substring(0, equals).trim();
|
||||
String valu = line.substring(equals + 1).trim();
|
||||
outgoing.put(attr, valu);
|
||||
}
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
static public void copyFile(File sourceFile,
|
||||
File targetFile) throws IOException {
|
||||
InputStream from =
|
||||
@ -2116,7 +2266,7 @@ public class Base {
|
||||
|
||||
static public String[] listFiles(File folder, boolean relative) {
|
||||
String path = folder.getAbsolutePath();
|
||||
Vector vector = new Vector();
|
||||
Vector<String> vector = new Vector<String>();
|
||||
listFiles(relative ? (path + File.separator) : "", path, vector);
|
||||
String outgoing[] = new String[vector.size()];
|
||||
vector.copyInto(outgoing);
|
||||
@ -2125,7 +2275,7 @@ public class Base {
|
||||
|
||||
|
||||
static protected void listFiles(String basePath,
|
||||
String path, Vector vector) {
|
||||
String path, Vector<String> vector) {
|
||||
File folder = new File(path);
|
||||
String list[] = folder.list();
|
||||
if (list == null) return;
|
||||
|
@ -43,7 +43,6 @@ import javax.swing.undo.*;
|
||||
|
||||
import gnu.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Main editor panel for the Processing Development Environment.
|
||||
*/
|
||||
@ -114,7 +113,6 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
EditorLineStatus lineStatus;
|
||||
|
||||
boolean newEditor = true;
|
||||
JEditorPane editorPane;
|
||||
|
||||
JEditTextArea textarea;
|
||||
@ -122,14 +120,14 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
// runtime information and window placement
|
||||
Point sketchWindowLocation;
|
||||
Runner runtime;
|
||||
//Runner runtime;
|
||||
|
||||
JMenuItem exportAppItem;
|
||||
JMenuItem saveMenuItem;
|
||||
JMenuItem saveAsMenuItem;
|
||||
|
||||
boolean running;
|
||||
boolean presenting;
|
||||
//boolean presenting;
|
||||
boolean uploading;
|
||||
|
||||
// undo fellers
|
||||
@ -142,6 +140,12 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
FindReplace find;
|
||||
|
||||
Runnable runHandler;
|
||||
Runnable presentHandler;
|
||||
Runnable stopHandler;
|
||||
Runnable exportHandler;
|
||||
Runnable exportAppHandler;
|
||||
|
||||
|
||||
public Editor(Base ibase, String path, int[] location) {
|
||||
super("Arduino");
|
||||
@ -149,6 +153,9 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
//Base.setIcon(this);
|
||||
|
||||
// Install default actions for Run, Present, etc.
|
||||
resetHandlers();
|
||||
|
||||
// add listener to handle window close box hit event
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
@ -232,22 +239,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
lineStatus = new EditorLineStatus(textarea);
|
||||
consolePanel.add(lineStatus, BorderLayout.SOUTH);
|
||||
|
||||
// if (newEditor) {
|
||||
// try {
|
||||
// setupEditorPane();
|
||||
// upper.add(editorPane);
|
||||
// } catch (Exception e1) {
|
||||
// PrintWriter w = PApplet.createWriter(new File("/Users/fry/Desktop/blah.txt"));
|
||||
// w.println(e1.getMessage());
|
||||
// e1.printStackTrace(w);
|
||||
// w.flush();
|
||||
// w.close();
|
||||
//// e1.printStackTrace());
|
||||
//// e1.printStackTrace(System.out);
|
||||
// }
|
||||
// } else {
|
||||
upper.add(textarea);
|
||||
// }
|
||||
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
|
||||
upper, consolePanel);
|
||||
|
||||
@ -276,64 +268,10 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
listener = new EditorListener(this, textarea);
|
||||
pain.add(box);
|
||||
|
||||
pain.setTransferHandler(new TransferHandler() {
|
||||
// get shift down/up events so we can show the alt version of toolbar buttons
|
||||
textarea.addKeyListener(toolbar);
|
||||
|
||||
public boolean canImport(JComponent dest, DataFlavor[] flavors) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean importData(JComponent src, Transferable transferable) {
|
||||
int successful = 0;
|
||||
|
||||
try {
|
||||
DataFlavor uriListFlavor =
|
||||
new DataFlavor("text/uri-list;class=java.lang.String");
|
||||
|
||||
if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
|
||||
java.util.List list = (java.util.List)
|
||||
transferable.getTransferData(DataFlavor.javaFileListFlavor);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
File file = (File) list.get(i);
|
||||
if (sketch.addFile(file)) {
|
||||
successful++;
|
||||
}
|
||||
}
|
||||
} else if (transferable.isDataFlavorSupported(uriListFlavor)) {
|
||||
//System.out.println("uri list");
|
||||
String data = (String)transferable.getTransferData(uriListFlavor);
|
||||
String[] pieces = PApplet.splitTokens(data, "\r\n");
|
||||
//PApplet.println(pieces);
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
if (pieces[i].startsWith("#")) continue;
|
||||
|
||||
String path = null;
|
||||
if (pieces[i].startsWith("file:///")) {
|
||||
path = pieces[i].substring(7);
|
||||
} else if (pieces[i].startsWith("file:/")) {
|
||||
path = pieces[i].substring(5);
|
||||
}
|
||||
if (sketch.addFile(new File(path))) {
|
||||
successful++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (successful == 0) {
|
||||
statusError("No files were added to the sketch.");
|
||||
|
||||
} else if (successful == 1) {
|
||||
statusNotice("One file added to the sketch.");
|
||||
|
||||
} else {
|
||||
statusNotice(successful + " files added to the sketch.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
pain.setTransferHandler(new FileDropHandler());
|
||||
|
||||
// System.out.println("t1");
|
||||
|
||||
@ -345,6 +283,20 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// Set the window bounds and the divider location before setting it visible
|
||||
setPlacement(location);
|
||||
|
||||
|
||||
// If the window is resized too small this will resize it again to the
|
||||
// minimums. Adapted by Chris Lonnen from comments here:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4320050
|
||||
// as a fix for http://dev.processing.org/bugs/show_bug.cgi?id=25
|
||||
final int minW = Preferences.getInteger("editor.window.width.min");
|
||||
final int minH = Preferences.getInteger("editor.window.height.min");
|
||||
addComponentListener(new java.awt.event.ComponentAdapter() {
|
||||
public void componentResized(ComponentEvent event) {
|
||||
setSize((getWidth() < minW) ? minW : getWidth(),
|
||||
(getHeight() < minH) ? minH : getHeight());
|
||||
}
|
||||
});
|
||||
|
||||
// System.out.println("t3");
|
||||
|
||||
// Bring back the general options for the editor
|
||||
@ -363,46 +315,71 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// http://wiki.netbeans.org/DevFaqEditorCodeCompletionAnyJEditorPane
|
||||
void setupEditorPane() throws IOException {
|
||||
editorPane = new JEditorPane();
|
||||
/**
|
||||
* Handles files dragged & dropped from the desktop and into the editor
|
||||
* window. Dragging files into the editor window is the same as using
|
||||
* "Sketch → Add File" for each file.
|
||||
*/
|
||||
class FileDropHandler extends TransferHandler {
|
||||
public boolean canImport(JComponent dest, DataFlavor[] flavors) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// This will find the Java editor kit and associate it with
|
||||
// our editor pane. But that does not give us code completion
|
||||
// just yet because we have no Java context (i.e. no class path, etc.).
|
||||
// However, this does give us syntax coloring.
|
||||
EditorKit kit = CloneableEditorSupport.getEditorKit("text/x-java");
|
||||
editorPane.setEditorKit(kit);
|
||||
|
||||
// You can specify any ".java" file.
|
||||
// If the file does not exist, it will be created.
|
||||
// The contents of the file does not matter.
|
||||
// The extension must be ".java", however.
|
||||
// String newSourcePath = "/Users/fry/Desktop/tmp.java";
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean importData(JComponent src, Transferable transferable) {
|
||||
int successful = 0;
|
||||
|
||||
// File tmpFile = new File(newSourcePath);
|
||||
// System.out.println(tmpFile.getParent() + " " + tmpFile.getName());
|
||||
// FileObject fob = FileUtil.createData(tmpFile);
|
||||
File tmpFile = File.createTempFile("temp", ".java");
|
||||
FileObject fob = FileUtil.toFileObject(FileUtil.normalizeFile(tmpFile));
|
||||
try {
|
||||
DataFlavor uriListFlavor =
|
||||
new DataFlavor("text/uri-list;class=java.lang.String");
|
||||
|
||||
DataObject dob = DataObject.find(fob);
|
||||
editorPane.getDocument().putProperty(Document.StreamDescriptionProperty, dob);
|
||||
if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
|
||||
java.util.List list = (java.util.List)
|
||||
transferable.getTransferData(DataFlavor.javaFileListFlavor);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
File file = (File) list.get(i);
|
||||
if (sketch.addFile(file)) {
|
||||
successful++;
|
||||
}
|
||||
}
|
||||
} else if (transferable.isDataFlavorSupported(uriListFlavor)) {
|
||||
// Some platforms (Mac OS X and Linux, when this began) preferred
|
||||
// this method of moving files.
|
||||
String data = (String)transferable.getTransferData(uriListFlavor);
|
||||
String[] pieces = PApplet.splitTokens(data, "\r\n");
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
if (pieces[i].startsWith("#")) continue;
|
||||
|
||||
// This sets up a default class path for us so that
|
||||
// we can find all the JDK classes via code completion.
|
||||
DialogBinding.bindComponentToFile(fob, 0, 0, editorPane);
|
||||
String path = null;
|
||||
if (pieces[i].startsWith("file:///")) {
|
||||
path = pieces[i].substring(7);
|
||||
} else if (pieces[i].startsWith("file:/")) {
|
||||
path = pieces[i].substring(5);
|
||||
}
|
||||
if (sketch.addFile(new File(path))) {
|
||||
successful++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Last but not least, we need to fill the editor pane with
|
||||
// some initial dummy code - as it seems somehow required to
|
||||
// kick-start code completion.
|
||||
// A simple dummy package declaration will do.
|
||||
editorPane.setText("package dummy;");
|
||||
if (successful == 0) {
|
||||
statusError("No files were added to the sketch.");
|
||||
|
||||
} else if (successful == 1) {
|
||||
statusNotice("One file added to the sketch.");
|
||||
|
||||
} else {
|
||||
statusNotice(successful + " files added to the sketch.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
protected void setPlacement(int[] location) {
|
||||
setBounds(location[0], location[1], location[2], location[3]);
|
||||
if (location[4] != 0) {
|
||||
@ -434,10 +411,10 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
* This appears to only be required on OS X 10.2, and is not
|
||||
* even being called on later versions of OS X or Windows.
|
||||
*/
|
||||
public Dimension getMinimumSize() {
|
||||
//System.out.println("getting minimum size");
|
||||
return new Dimension(500, 550);
|
||||
}
|
||||
// public Dimension getMinimumSize() {
|
||||
// //System.out.println("getting minimum size");
|
||||
// return new Dimension(500, 550);
|
||||
// }
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
@ -737,7 +714,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
|
||||
protected void addTools(JMenu menu, File sourceFolder) {
|
||||
HashMap toolItems = new HashMap();
|
||||
HashMap<String, JMenuItem> toolItems = new HashMap<String, JMenuItem>();
|
||||
|
||||
File[] folders = sourceFolder.listFiles(new FileFilter() {
|
||||
public boolean accept(File folder) {
|
||||
@ -807,7 +784,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// If no class name found, just move on.
|
||||
if (className == null) continue;
|
||||
|
||||
Class toolClass = Class.forName(className, true, loader);
|
||||
Class<?> toolClass = Class.forName(className, true, loader);
|
||||
final Tool tool = (Tool) toolClass.newInstance();
|
||||
|
||||
tool.init(Editor.this);
|
||||
@ -817,6 +794,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SwingUtilities.invokeLater(tool);
|
||||
//new Thread(tool).start();
|
||||
}
|
||||
});
|
||||
//menu.add(item);
|
||||
@ -826,7 +804,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
ArrayList<String> toolList = new ArrayList(toolItems.keySet());
|
||||
ArrayList<String> toolList = new ArrayList<String>(toolItems.keySet());
|
||||
if (toolList.size() == 0) return;
|
||||
|
||||
menu.addSeparator();
|
||||
@ -843,7 +821,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(file);
|
||||
Enumeration entries = zipFile.entries();
|
||||
Enumeration<?> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
@ -869,7 +847,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
protected JMenuItem createToolMenuItem(String className) {
|
||||
try {
|
||||
Class toolClass = Class.forName(className);
|
||||
Class<?> toolClass = Class.forName(className);
|
||||
final Tool tool = (Tool) toolClass.newInstance();
|
||||
|
||||
JMenuItem item = new JMenuItem(tool.getMenuTitle());
|
||||
@ -903,12 +881,14 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
menu.add(createToolMenuItem("processing.app.tools.Archiver"));
|
||||
menu.add(createToolMenuItem("processing.app.tools.FixEncoding"));
|
||||
|
||||
/*
|
||||
//menu.add(createToolMenuItem("processing.app.tools.android.Build"));
|
||||
item = createToolMenuItem("processing.app.tools.android.Build");
|
||||
item.setAccelerator(KeyStroke.getKeyStroke('D', modifiers));
|
||||
menu.add(item);
|
||||
*/
|
||||
// // These are temporary entries while Android mode is being worked out.
|
||||
// // The mode will not be in the tools menu, and won't involve a cmd-key
|
||||
// if (!Base.RELEASE) {
|
||||
// item = createToolMenuItem("processing.app.tools.android.AndroidTool");
|
||||
// item.setAccelerator(KeyStroke.getKeyStroke('D', modifiers));
|
||||
// menu.add(item);
|
||||
// menu.add(createToolMenuItem("processing.app.tools.android.Reset"));
|
||||
// }
|
||||
|
||||
return menu;
|
||||
}
|
||||
@ -1363,6 +1343,35 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// these will be done in a more generic way soon, more like:
|
||||
// setHandler("action name", Runnable);
|
||||
// but for the time being, working out the kinks of how many things to
|
||||
// abstract from the editor in this fashion.
|
||||
|
||||
|
||||
public void setHandlers(Runnable runHandler, Runnable presentHandler,
|
||||
Runnable stopHandler,
|
||||
Runnable exportHandler, Runnable exportAppHandler) {
|
||||
this.runHandler = runHandler;
|
||||
this.presentHandler = presentHandler;
|
||||
this.stopHandler = stopHandler;
|
||||
this.exportHandler = exportHandler;
|
||||
this.exportAppHandler = exportAppHandler;
|
||||
}
|
||||
|
||||
|
||||
public void resetHandlers() {
|
||||
runHandler = new DefaultRunHandler();
|
||||
presentHandler = new DefaultPresentHandler();
|
||||
stopHandler = new DefaultStopHandler();
|
||||
exportHandler = new DefaultExportHandler();
|
||||
exportAppHandler = new DefaultExportAppHandler();
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current sketch object.
|
||||
*/
|
||||
@ -1799,26 +1808,50 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
console.clear();
|
||||
}
|
||||
|
||||
//presenting = present;
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
sketch.compile(verbose);
|
||||
statusNotice("Done compiling.");
|
||||
} catch (RunnerException e) {
|
||||
//statusError("Error compiling...");
|
||||
statusError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
toolbar.deactivate(EditorToolbar.RUN);
|
||||
}
|
||||
});
|
||||
// Cannot use invokeLater() here, otherwise it gets
|
||||
// placed on the event thread and causes a hang--bad idea all around.
|
||||
new Thread(verbose ? presentHandler : runHandler).start();
|
||||
}
|
||||
|
||||
// DAM: in Arduino, this is compile
|
||||
class DefaultRunHandler implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
sketch.prepare();
|
||||
String appletClassName = sketch.build(false);
|
||||
statusNotice("Done compiling.");
|
||||
} catch (Exception e) {
|
||||
statusError(e);
|
||||
}
|
||||
|
||||
toolbar.deactivate(EditorToolbar.RUN);
|
||||
}
|
||||
}
|
||||
|
||||
// DAM: in Arduino, this is compile (with verbose output)
|
||||
class DefaultPresentHandler implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
sketch.prepare();
|
||||
String appletClassName = sketch.build(true);
|
||||
statusNotice("Done compiling.");
|
||||
} catch (Exception e) {
|
||||
statusError(e);
|
||||
}
|
||||
|
||||
toolbar.deactivate(EditorToolbar.RUN);
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultStopHandler implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
// DAM: we should try to kill the compilation or upload process here.
|
||||
} catch (Exception e) {
|
||||
statusError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location of the sketch run window. Used by Runner to update the
|
||||
@ -1855,8 +1888,10 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
|
||||
/**
|
||||
* Called by Runner to notify that the sketch has stopped running.
|
||||
* Tools should not call this function, use handleStop() instead.
|
||||
* Deactivate the Run button. This is called by Runner to notify that the
|
||||
* sketch has stopped running, usually in response to an error (or maybe
|
||||
* the sketch completing and exiting?) Tools should not call this function.
|
||||
* To initiate a "stop" action, call handleStop() instead.
|
||||
*/
|
||||
public void internalRunnerClosed() {
|
||||
running = false;
|
||||
@ -1870,11 +1905,9 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
public void internalCloseRunner() {
|
||||
running = false;
|
||||
|
||||
if (stopHandler != null)
|
||||
try {
|
||||
if (runtime != null) {
|
||||
runtime.close(); // kills the window
|
||||
runtime = null; // will this help?
|
||||
}
|
||||
stopHandler.run();
|
||||
} catch (Exception e) { }
|
||||
|
||||
sketch.cleanup();
|
||||
@ -1883,13 +1916,14 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
/**
|
||||
* Check if the sketch is modified and ask user to save changes.
|
||||
* Immediately should be set true when quitting, or when the save should
|
||||
* not happen asynchronously. Come to think of it, that's always now?
|
||||
* @return false if canceling the close/quit operation
|
||||
*/
|
||||
protected boolean checkModified(boolean immediately) {
|
||||
protected boolean checkModified() {
|
||||
if (!sketch.isModified()) return true;
|
||||
|
||||
// As of Processing 1.0.10, this always happens immediately.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=1456
|
||||
|
||||
String prompt = "Save changes to " + sketch.getName() + "? ";
|
||||
|
||||
if (!Base.isMacOS()) {
|
||||
@ -1899,13 +1933,14 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
return handleSave(immediately);
|
||||
return handleSave(true);
|
||||
|
||||
} else if (result == JOptionPane.NO_OPTION) {
|
||||
return true; // ok to continue
|
||||
|
||||
} else if (result == JOptionPane.CANCEL_OPTION) {
|
||||
return false;
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@ -1950,7 +1985,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
|
||||
Object result = pane.getValue();
|
||||
if (result == options[0]) { // save (and close/quit)
|
||||
return handleSave(immediately);
|
||||
return handleSave(true);
|
||||
|
||||
} else if (result == options[2]) { // don't save (still close/quit)
|
||||
return true;
|
||||
@ -2203,39 +2238,69 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
synchronized public void handleExport(final boolean verbose) {
|
||||
//if (!handleExportCheckModified()) return;
|
||||
toolbar.activate(EditorToolbar.EXPORT);
|
||||
|
||||
console.clear();
|
||||
statusNotice("Uploading to I/O Board...");
|
||||
|
||||
//SwingUtilities.invokeLater(new Runnable() {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serialMonitor.closeSerialPort();
|
||||
serialMonitor.setVisible(false);
|
||||
|
||||
uploading = true;
|
||||
|
||||
boolean success = sketch.exportApplet(verbose);
|
||||
if (success) {
|
||||
statusNotice("Done uploading.");
|
||||
} else {
|
||||
// error message will already be visible
|
||||
}
|
||||
} catch (RunnerException e) {
|
||||
//statusError("Error during upload.");
|
||||
//e.printStackTrace();
|
||||
statusError(e);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploading = false;
|
||||
//toolbar.clear();
|
||||
toolbar.deactivate(EditorToolbar.EXPORT);
|
||||
}});
|
||||
t.start();
|
||||
new Thread(verbose ? exportAppHandler : exportHandler).start();
|
||||
}
|
||||
|
||||
// DAM: in Arduino, this is upload
|
||||
class DefaultExportHandler implements Runnable {
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
serialMonitor.closeSerialPort();
|
||||
serialMonitor.setVisible(false);
|
||||
|
||||
uploading = true;
|
||||
|
||||
boolean success = sketch.exportApplet(false);
|
||||
if (success) {
|
||||
statusNotice("Done uploading.");
|
||||
} else {
|
||||
// error message will already be visible
|
||||
}
|
||||
} catch (RunnerException e) {
|
||||
//statusError("Error during upload.");
|
||||
//e.printStackTrace();
|
||||
statusError(e);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploading = false;
|
||||
//toolbar.clear();
|
||||
toolbar.deactivate(EditorToolbar.EXPORT);
|
||||
}
|
||||
}
|
||||
|
||||
// DAM: in Arduino, this is upload (with verbose output)
|
||||
class DefaultExportAppHandler implements Runnable {
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
serialMonitor.closeSerialPort();
|
||||
serialMonitor.setVisible(false);
|
||||
|
||||
uploading = true;
|
||||
|
||||
boolean success = sketch.exportApplet(true);
|
||||
if (success) {
|
||||
statusNotice("Done uploading.");
|
||||
} else {
|
||||
// error message will already be visible
|
||||
}
|
||||
} catch (RunnerException e) {
|
||||
//statusError("Error during upload.");
|
||||
//e.printStackTrace();
|
||||
statusError(e);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploading = false;
|
||||
//toolbar.clear();
|
||||
toolbar.deactivate(EditorToolbar.EXPORT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the sketch has been modified, and if so,
|
||||
@ -2418,7 +2483,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
}
|
||||
statusError(mess);
|
||||
}
|
||||
e.printStackTrace();
|
||||
// e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
@ -2563,4 +2628,3 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@ -47,8 +48,6 @@ public class EditorConsole extends JScrollPane {
|
||||
MutableAttributeSet stdStyle;
|
||||
MutableAttributeSet errStyle;
|
||||
|
||||
boolean cerror;
|
||||
|
||||
int maxLineCount;
|
||||
|
||||
static File errFile;
|
||||
@ -221,18 +220,9 @@ public class EditorConsole extends JScrollPane {
|
||||
|
||||
|
||||
public void write(byte b[], int offset, int length, boolean err) {
|
||||
if (err != cerror) {
|
||||
// advance the line because switching between err/out streams
|
||||
// potentially, could check whether we're already on a new line
|
||||
message("", cerror, true);
|
||||
}
|
||||
|
||||
// we could do some cross platform CR/LF mangling here before outputting
|
||||
|
||||
// add text to output document
|
||||
message(new String(b, offset, length), err, false);
|
||||
// set last error state
|
||||
cerror = err;
|
||||
}
|
||||
|
||||
|
||||
@ -291,10 +281,10 @@ public class EditorConsole extends JScrollPane {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
class EditorConsoleStream extends OutputStream {
|
||||
private static class EditorConsoleStream extends OutputStream {
|
||||
//static EditorConsole current;
|
||||
boolean err; // whether stderr or stdout
|
||||
byte single[] = new byte[1];
|
||||
final boolean err; // whether stderr or stdout
|
||||
final byte single[] = new byte[1];
|
||||
|
||||
public EditorConsoleStream(boolean err) {
|
||||
this.err = err;
|
||||
@ -389,7 +379,7 @@ public class EditorConsole extends JScrollPane {
|
||||
* swing event thread, so they need to be synchronized
|
||||
*/
|
||||
class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
ArrayList elements = new ArrayList();
|
||||
ArrayList<ElementSpec> elements = new ArrayList<ElementSpec>();
|
||||
int maxLineLength, maxLineCount;
|
||||
int currentLineLength = 0;
|
||||
boolean needLineBreak = false;
|
||||
|
@ -103,6 +103,10 @@ public class EditorListener {
|
||||
char c = event.getKeyChar();
|
||||
int code = event.getKeyCode();
|
||||
|
||||
// if (code == KeyEvent.VK_SHIFT) {
|
||||
// editor.toolbar.setShiftPressed(true);
|
||||
// }
|
||||
|
||||
//System.out.println((int)c + " " + code + " " + event);
|
||||
//System.out.println();
|
||||
|
||||
@ -457,6 +461,13 @@ public class EditorListener {
|
||||
}
|
||||
|
||||
|
||||
// public boolean keyReleased(KeyEvent event) {
|
||||
// if (code == KeyEvent.VK_SHIFT) {
|
||||
// editor.toolbar.setShiftPressed(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
public boolean keyTyped(KeyEvent event) {
|
||||
char c = event.getKeyChar();
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
||||
Copyright (c) 2004-09 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
|
||||
@ -25,6 +25,7 @@ package processing.app;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
@ -32,12 +33,18 @@ import javax.swing.event.*;
|
||||
/**
|
||||
* run/stop/etc buttons for the ide
|
||||
*/
|
||||
public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
public class EditorToolbar extends JComponent implements MouseInputListener, KeyListener {
|
||||
|
||||
/** Rollover titles for each button. */
|
||||
static final String title[] = {
|
||||
"Verify", "Stop", "New", "Open", "Save", "Upload", "Serial Monitor"
|
||||
};
|
||||
|
||||
/** Titles for each button when the shift key is pressed. */
|
||||
static final String titleShift[] = {
|
||||
"Verify (w/ Verbose Output)", "Stop", "New Editor Window", "Open in Another Window", "Save", "Upload (w/ Verbose Output)", "Serial Monitor"
|
||||
};
|
||||
|
||||
static final int BUTTON_COUNT = title.length;
|
||||
/** Width of each toolbar button. */
|
||||
static final int BUTTON_WIDTH = 27;
|
||||
@ -45,6 +52,9 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
static final int BUTTON_HEIGHT = 32;
|
||||
/** The amount of space between groups of buttons on the toolbar. */
|
||||
static final int BUTTON_GAP = 5;
|
||||
/** Size of the button image being chopped up. */
|
||||
static final int BUTTON_IMAGE_SIZE = 33;
|
||||
|
||||
|
||||
static final int RUN = 0;
|
||||
static final int STOP = 1;
|
||||
@ -61,45 +71,35 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
static final int ACTIVE = 2;
|
||||
|
||||
Editor editor;
|
||||
//boolean disableRun; // this was for library
|
||||
//Label status;
|
||||
|
||||
Image offscreen;
|
||||
int width, height;
|
||||
|
||||
Color bgcolor;
|
||||
|
||||
static Image buttons;
|
||||
static Image inactive[];
|
||||
static Image rollover[];
|
||||
static Image active[];
|
||||
static Image[][] buttonImages;
|
||||
int currentRollover;
|
||||
//int currentSelection;
|
||||
|
||||
JPopupMenu popup;
|
||||
JMenu menu;
|
||||
|
||||
int buttonCount;
|
||||
int state[] = new int[BUTTON_COUNT];
|
||||
Image stateImage[];
|
||||
int[] state = new int[BUTTON_COUNT];
|
||||
Image[] stateImage;
|
||||
int which[]; // mapping indices to implementation
|
||||
|
||||
int x1[], x2[];
|
||||
int y1, y2;
|
||||
|
||||
String status;
|
||||
Font statusFont;
|
||||
Color statusColor;
|
||||
|
||||
boolean shiftPressed;
|
||||
|
||||
public EditorToolbar(Editor editor, JMenu menu) {
|
||||
this.editor = editor;
|
||||
this.menu = menu;
|
||||
|
||||
if (buttons == null) {
|
||||
buttons = Base.getThemeImage("buttons.gif", this);
|
||||
}
|
||||
|
||||
buttonCount = 0;
|
||||
which = new int[BUTTON_COUNT];
|
||||
|
||||
@ -115,9 +115,6 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
currentRollover = -1;
|
||||
|
||||
bgcolor = Theme.getColor("buttons.bgcolor");
|
||||
|
||||
status = "";
|
||||
|
||||
statusFont = Theme.getFont("buttons.status.font");
|
||||
statusColor = Theme.getColor("buttons.status.color");
|
||||
|
||||
@ -125,30 +122,28 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
addMouseMotionListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void paintComponent(Graphics screen) {
|
||||
// this data is shared by all EditorToolbar instances
|
||||
if (inactive == null) {
|
||||
inactive = new Image[BUTTON_COUNT];
|
||||
rollover = new Image[BUTTON_COUNT];
|
||||
active = new Image[BUTTON_COUNT];
|
||||
|
||||
int IMAGE_SIZE = 33;
|
||||
protected void loadButtons() {
|
||||
Image allButtons = Base.getThemeImage("buttons.gif", this);
|
||||
buttonImages = new Image[BUTTON_COUNT][3];
|
||||
|
||||
for (int i = 0; i < BUTTON_COUNT; i++) {
|
||||
inactive[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
Graphics g = inactive[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -2*IMAGE_SIZE, null);
|
||||
|
||||
rollover[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
g = rollover[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -1*IMAGE_SIZE, null);
|
||||
|
||||
active[i] = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
g = active[i].getGraphics();
|
||||
g.drawImage(buttons, -(i*IMAGE_SIZE) - 3, -0*IMAGE_SIZE, null);
|
||||
for (int state = 0; state < 3; state++) {
|
||||
Image image = createImage(BUTTON_WIDTH, BUTTON_HEIGHT);
|
||||
Graphics g = image.getGraphics();
|
||||
g.drawImage(allButtons,
|
||||
-(i*BUTTON_IMAGE_SIZE) - 3,
|
||||
(-2 + state)*BUTTON_IMAGE_SIZE, null);
|
||||
buttonImages[i][state] = image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics screen) {
|
||||
// this data is shared by all EditorToolbar instances
|
||||
if (buttonImages == null) {
|
||||
loadButtons();
|
||||
}
|
||||
|
||||
// this happens once per instance of EditorToolbar
|
||||
if (stateImage == null) {
|
||||
@ -191,21 +186,34 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
|
||||
/*
|
||||
// if i ever find the guy who wrote the java2d api, i will hurt him.
|
||||
*
|
||||
* whereas I love the Java2D API. --jdf. lol.
|
||||
*
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
FontRenderContext frc = g2.getFontRenderContext();
|
||||
float statusW = (float) statusFont.getStringBounds(status, frc).getWidth();
|
||||
float statusX = (getSize().width - statusW) / 2;
|
||||
g2.drawString(status, statusX, statusY);
|
||||
*/
|
||||
//int statusY = (BUTTON_HEIGHT + statusFont.getAscent()) / 2;
|
||||
if (currentRollover != -1) {
|
||||
int statusY = (BUTTON_HEIGHT + g.getFontMetrics().getAscent()) / 2;
|
||||
String status = shiftPressed ? titleShift[currentRollover] : title[currentRollover];
|
||||
g.drawString(status, buttonCount * BUTTON_WIDTH + 3 * BUTTON_GAP, statusY);
|
||||
}
|
||||
|
||||
screen.drawImage(offscreen, 0, 0, null);
|
||||
|
||||
if (!isEnabled()) {
|
||||
screen.setColor(new Color(0,0,0,100));
|
||||
screen.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
// mouse events before paint();
|
||||
if (state == null) return;
|
||||
|
||||
@ -213,16 +221,17 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
// avoid flicker, since there will probably be an update event
|
||||
setState(OPEN, INACTIVE, false);
|
||||
}
|
||||
//System.out.println(e);
|
||||
//mouseMove(e);
|
||||
handleMouse(e.getX(), e.getY());
|
||||
handleMouse(e);
|
||||
}
|
||||
|
||||
|
||||
public void mouseDragged(MouseEvent e) { }
|
||||
|
||||
|
||||
public void handleMouse(int x, int y) {
|
||||
public void handleMouse(MouseEvent e) {
|
||||
int x = e.getX();
|
||||
int y = e.getY();
|
||||
|
||||
if (currentRollover != -1) {
|
||||
if ((x > x1[currentRollover]) && (y > y1) &&
|
||||
(x < x2[currentRollover]) && (y < y2)) {
|
||||
@ -230,7 +239,6 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
|
||||
} else {
|
||||
setState(currentRollover, INACTIVE, true);
|
||||
messageClear(title[currentRollover]);
|
||||
currentRollover = -1;
|
||||
}
|
||||
}
|
||||
@ -238,10 +246,8 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
if (sel == -1) return;
|
||||
|
||||
if (state[sel] != ACTIVE) {
|
||||
//if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
|
||||
setState(sel, ROLLOVER, true);
|
||||
currentRollover = sel;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,32 +269,16 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
|
||||
|
||||
private void setState(int slot, int newState, boolean updateAfter) {
|
||||
//if (inactive == null) return;
|
||||
state[slot] = newState;
|
||||
switch (newState) {
|
||||
case INACTIVE:
|
||||
stateImage[slot] = inactive[which[slot]];
|
||||
break;
|
||||
case ACTIVE:
|
||||
stateImage[slot] = active[which[slot]];
|
||||
break;
|
||||
case ROLLOVER:
|
||||
stateImage[slot] = rollover[which[slot]];
|
||||
message(title[which[slot]]);
|
||||
break;
|
||||
}
|
||||
stateImage[slot] = buttonImages[which[slot]][newState];
|
||||
if (updateAfter) {
|
||||
//System.out.println("trying to update " + slot + " " + state[slot]);
|
||||
//new Exception("setting slot " + slot + " to " + state[slot]).printStackTrace();
|
||||
repaint(); // changed for swing from update();
|
||||
//Toolkit.getDefaultToolkit().sync();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
//mouseMove(e);
|
||||
handleMouse(e.getX(), e.getY());
|
||||
handleMouse(e);
|
||||
}
|
||||
|
||||
|
||||
@ -300,14 +290,18 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
if (state[OPEN] != INACTIVE) {
|
||||
setState(OPEN, INACTIVE, true);
|
||||
}
|
||||
status = "";
|
||||
handleMouse(e.getX(), e.getY());
|
||||
handleMouse(e);
|
||||
}
|
||||
|
||||
int wasDown = -1;
|
||||
|
||||
|
||||
public void mousePressed(MouseEvent e) {
|
||||
|
||||
// jdf
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
final int x = e.getX();
|
||||
final int y = e.getY();
|
||||
|
||||
@ -331,8 +325,11 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
break;
|
||||
|
||||
case NEW:
|
||||
//editor.base.handleNew(e.isShiftDown());
|
||||
if (shiftPressed) {
|
||||
editor.base.handleNew();
|
||||
} else {
|
||||
editor.base.handleNewReplace();
|
||||
}
|
||||
break;
|
||||
|
||||
case SAVE:
|
||||
@ -353,84 +350,26 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
public void mouseClicked(MouseEvent e) { }
|
||||
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
/*
|
||||
switch (currentSelection) {
|
||||
|
||||
case OPEN:
|
||||
setState(OPEN, INACTIVE, true);
|
||||
break;
|
||||
}
|
||||
currentSelection = -1;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//public void disableRun(boolean what) {
|
||||
//disableRun = what;
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
public void run() {
|
||||
if (inactive == null) return;
|
||||
clear();
|
||||
setState(RUN, ACTIVE, true);
|
||||
}
|
||||
*/
|
||||
|
||||
// public void running(boolean yesno) {
|
||||
// setState(RUN, yesno ? ACTIVE : INACTIVE, true);
|
||||
// }
|
||||
public void mouseReleased(MouseEvent e) { }
|
||||
|
||||
|
||||
/**
|
||||
* Set a particular button to be active.
|
||||
*/
|
||||
public void activate(int what) {
|
||||
//System.out.println("activating " + what);
|
||||
if (inactive == null) return;
|
||||
if (buttonImages != null) {
|
||||
setState(what, ACTIVE, true);
|
||||
}
|
||||
|
||||
//public void clearRun() {
|
||||
//if (inactive == null) return;
|
||||
//setState(RUN, INACTIVE, true);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a particular button to be active.
|
||||
*/
|
||||
public void deactivate(int what) {
|
||||
if (inactive == null) return; // don't draw if not ready
|
||||
if (buttonImages != null) {
|
||||
setState(what, INACTIVE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all the state of all buttons.
|
||||
*/
|
||||
// public void clear() { // (int button) {
|
||||
// if (inactive == null) return;
|
||||
//
|
||||
// System.out.println("clearing state of buttons");
|
||||
// // skip the run button, do the others
|
||||
// for (int i = 1; i < buttonCount; i++) {
|
||||
// setState(i, INACTIVE, false);
|
||||
// }
|
||||
// repaint(); // changed for swing from update();
|
||||
// }
|
||||
|
||||
|
||||
public void message(String msg) {
|
||||
//status.setText(msg + " "); // don't mind the hack
|
||||
status = msg;
|
||||
}
|
||||
|
||||
|
||||
public void messageClear(String msg) {
|
||||
//if (status.getText().equals(msg + " ")) status.setText(Editor.EMPTY);
|
||||
if (status.equals(msg)) status = "";
|
||||
}
|
||||
|
||||
|
||||
@ -447,4 +386,23 @@ public class EditorToolbar extends JComponent implements MouseInputListener {
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(3000, BUTTON_HEIGHT);
|
||||
}
|
||||
|
||||
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shiftPressed = true;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
shiftPressed = false;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void keyTyped(KeyEvent e) { }
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ import java.io.File;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
|
||||
/**
|
||||
* Used by Base for platform-specific tweaking, for instance finding the
|
||||
@ -129,6 +132,36 @@ public class Platform {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
public interface CLibrary extends Library {
|
||||
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
|
||||
int setenv(String name, String value, int overwrite);
|
||||
String getenv(String name);
|
||||
int unsetenv(String name);
|
||||
int putenv(String string);
|
||||
}
|
||||
|
||||
|
||||
public void setenv(String variable, String value) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
clib.setenv(variable, value, 1);
|
||||
}
|
||||
|
||||
|
||||
public String getenv(String variable) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
return clib.getenv(variable);
|
||||
}
|
||||
|
||||
|
||||
public int unsetenv(String variable) {
|
||||
CLibrary clib = CLibrary.INSTANCE;
|
||||
return clib.unsetenv(variable);
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
protected void showLauncherWarning() {
|
||||
Base.showWarning("No launcher available",
|
||||
"Unspecified platform, no launcher available.\n" +
|
||||
|
@ -626,6 +626,11 @@ public class Preferences {
|
||||
}
|
||||
|
||||
|
||||
static public void unset(String attribute) {
|
||||
table.remove(attribute);
|
||||
}
|
||||
|
||||
|
||||
static public boolean getBoolean(String attribute) {
|
||||
String value = get(attribute); //, null);
|
||||
return (new Boolean(value)).booleanValue();
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-09 Ben Fry and Casey Reas
|
||||
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
|
||||
@ -95,6 +95,9 @@ public class Sketch {
|
||||
* DLLs or JNILIBs.
|
||||
*/
|
||||
private String libraryPath;
|
||||
/**
|
||||
* List of library folders.
|
||||
*/
|
||||
private ArrayList<File> importedLibraries;
|
||||
|
||||
/**
|
||||
@ -1165,11 +1168,14 @@ public class Sketch {
|
||||
* X. afterwards, some of these steps need a cleanup function
|
||||
* </PRE>
|
||||
*/
|
||||
protected String compile(boolean verbose)
|
||||
throws RunnerException {
|
||||
|
||||
String name;
|
||||
|
||||
//protected String compile() throws RunnerException {
|
||||
|
||||
|
||||
/**
|
||||
* When running from the editor, take care of preparations before running
|
||||
* the build.
|
||||
*/
|
||||
public void prepare() {
|
||||
// make sure the user didn't hide the sketch folder
|
||||
ensureExistence();
|
||||
|
||||
@ -1199,11 +1205,8 @@ public class Sketch {
|
||||
// better connected to the dataFolder stuff below.
|
||||
cleanup();
|
||||
|
||||
// handle preprocessing the main file's code
|
||||
name = build(tempBuildFolder.getAbsolutePath(), verbose);
|
||||
size(tempBuildFolder.getAbsolutePath(), name);
|
||||
|
||||
return name;
|
||||
// // handle preprocessing the main file's code
|
||||
// return build(tempBuildFolder.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
@ -1255,14 +1258,6 @@ public class Sketch {
|
||||
// 1. concatenate all .pde files to the 'main' pde
|
||||
// store line number for starting point of each code bit
|
||||
|
||||
// Unfortunately, the header has to be written on a single line, because
|
||||
// there's no way to determine how long it will be until the code has
|
||||
// already been preprocessed. The header will vary in length based on
|
||||
// the programming mode (STATIC, ACTIVE, or JAVA), which is determined
|
||||
// by the preprocessor. So the preprocOffset for the primary class remains
|
||||
// zero, even though it'd be nice to have a legitimate offset, and be able
|
||||
// to remove the 'pretty' boolean for preproc.write().
|
||||
|
||||
StringBuffer bigCode = new StringBuffer();
|
||||
int bigCount = 0;
|
||||
for (SketchCode sc : code) {
|
||||
@ -1271,29 +1266,9 @@ public class Sketch {
|
||||
bigCode.append(sc.getProgram());
|
||||
bigCode.append('\n');
|
||||
bigCount += sc.getLineCount();
|
||||
// if (sc != code[0]) {
|
||||
// sc.setPreprocName(null); // don't compile me
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
String program = code[0].getProgram();
|
||||
StringBuffer bigCode = new StringBuffer(program);
|
||||
int bigCount = code[0].getLineCount();
|
||||
bigCode.append('\n');
|
||||
|
||||
for (int i = 1; i < codeCount; i++) {
|
||||
if (code[i].isExtension("pde")) {
|
||||
code[i].setPreprocOffset(bigCount);
|
||||
bigCode.append(code[i].getProgram());
|
||||
bigCode.append('\n');
|
||||
bigCount += code[i].getLineCount();
|
||||
code[i].setPreprocName(null); // don't compile me
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Note that the headerOffset isn't applied until compile and run, because
|
||||
// it only applies to the code after it's been written to the .java file.
|
||||
int headerOffset = 0;
|
||||
@ -1391,6 +1366,134 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<File> getImportedLibraries() {
|
||||
return importedLibraries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
* in the actual sketch.
|
||||
* @param message The error message.
|
||||
* @param filename The .java file where the exception was found.
|
||||
* @param line Line number of the .java file for the exception (1-indexed)
|
||||
* @return A RunnerException to be sent to the editor, or null if it wasn't
|
||||
* possible to place the exception to the sketch code.
|
||||
*/
|
||||
// public RunnerException placeExceptionAlt(String message,
|
||||
// String filename, int line) {
|
||||
// String appletJavaFile = appletClassName + ".java";
|
||||
// SketchCode errorCode = null;
|
||||
// if (filename.equals(appletJavaFile)) {
|
||||
// for (SketchCode code : getCode()) {
|
||||
// if (code.isExtension("pde")) {
|
||||
// if (line >= code.getPreprocOffset()) {
|
||||
// errorCode = code;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// for (SketchCode code : getCode()) {
|
||||
// if (code.isExtension("java")) {
|
||||
// if (filename.equals(code.getFileName())) {
|
||||
// errorCode = code;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// int codeIndex = getCodeIndex(errorCode);
|
||||
//
|
||||
// if (codeIndex != -1) {
|
||||
// //System.out.println("got line num " + lineNumber);
|
||||
// // in case this was a tab that got embedded into the main .java
|
||||
// line -= getCode(codeIndex).getPreprocOffset();
|
||||
//
|
||||
// // lineNumber is 1-indexed, but editor wants zero-indexed
|
||||
// line--;
|
||||
//
|
||||
// // getMessage() will be what's shown in the editor
|
||||
// RunnerException exception =
|
||||
// new RunnerException(message, codeIndex, line, -1);
|
||||
// exception.hideStackTrace();
|
||||
// return exception;
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Map an error from a set of processed .java files back to its location
|
||||
* in the actual sketch.
|
||||
* @param message The error message.
|
||||
* @param filename The .java file where the exception was found.
|
||||
* @param line Line number of the .java file for the exception (0-indexed!)
|
||||
* @return A RunnerException to be sent to the editor, or null if it wasn't
|
||||
* possible to place the exception to the sketch code.
|
||||
*/
|
||||
public RunnerException placeException(String message,
|
||||
String dotJavaFilename,
|
||||
int dotJavaLine) {
|
||||
int codeIndex = 0; //-1;
|
||||
int codeLine = -1;
|
||||
|
||||
// System.out.println("placing " + dotJavaFilename + " " + dotJavaLine);
|
||||
// System.out.println("code count is " + getCodeCount());
|
||||
|
||||
// first check to see if it's a .java file
|
||||
for (int i = 0; i < getCodeCount(); i++) {
|
||||
SketchCode code = getCode(i);
|
||||
if (code.isExtension("java")) {
|
||||
if (dotJavaFilename.equals(code.getFileName())) {
|
||||
codeIndex = i;
|
||||
codeLine = dotJavaLine;
|
||||
return new RunnerException(message, codeIndex, codeLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not the preprocessed file at this point, then need to get out
|
||||
if (!dotJavaFilename.equals(name + ".java")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if it's not a .java file, codeIndex will still be 0
|
||||
// this section searches through the list of .pde files
|
||||
codeIndex = 0;
|
||||
for (int i = 0; i < getCodeCount(); i++) {
|
||||
SketchCode code = getCode(i);
|
||||
|
||||
if (code.isExtension("pde")) {
|
||||
// System.out.println("preproc offset is " + code.getPreprocOffset());
|
||||
// System.out.println("looking for line " + dotJavaLine);
|
||||
if (code.getPreprocOffset() <= dotJavaLine) {
|
||||
codeIndex = i;
|
||||
// System.out.println("i'm thinkin file " + i);
|
||||
codeLine = dotJavaLine - code.getPreprocOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
// could not find a proper line number, so deal with this differently.
|
||||
// but if it was in fact the .java file we're looking for, though,
|
||||
// send the error message through.
|
||||
// this is necessary because 'import' statements will be at a line
|
||||
// that has a lower number than the preproc offset, for instance.
|
||||
// if (codeLine == -1 && !dotJavaFilename.equals(name + ".java")) {
|
||||
// return null;
|
||||
// }
|
||||
return new RunnerException(message, codeIndex, codeLine);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the build inside the temporary build folder.
|
||||
* @return null if compilation failed, main class name if not
|
||||
* @throws RunnerException
|
||||
*/
|
||||
public String build(boolean verbose) throws RunnerException {
|
||||
return build(tempBuildFolder.getAbsolutePath(), verbose);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Preprocess and compile all the code for this sketch.
|
||||
*
|
||||
@ -1410,6 +1513,7 @@ public class Sketch {
|
||||
// that will bubble up to whomever called build().
|
||||
Compiler compiler = new Compiler();
|
||||
if (compiler.compile(this, buildPath, primaryClassName, verbose)) {
|
||||
size(buildPath, primaryClassName);
|
||||
return primaryClassName;
|
||||
}
|
||||
return null;
|
||||
@ -1500,7 +1604,7 @@ public class Sketch {
|
||||
verbose);
|
||||
|
||||
return success ? suggestedClassName : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all commented portions of a given String as spaces.
|
||||
@ -1538,7 +1642,8 @@ public class Sketch {
|
||||
break;
|
||||
|
||||
} else {
|
||||
index++;
|
||||
// continue blanking this area
|
||||
p[index++] = ' ';
|
||||
}
|
||||
}
|
||||
if (!endOfRainbow) {
|
||||
@ -1562,8 +1667,8 @@ public class Sketch {
|
||||
* Export to application via GUI.
|
||||
*/
|
||||
protected boolean exportApplication() throws IOException, RunnerException {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -1571,8 +1676,8 @@ public class Sketch {
|
||||
*/
|
||||
public boolean exportApplication(String destPath,
|
||||
int exportPlatform) throws IOException, RunnerException {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected void addManifest(ZipOutputStream zos) throws IOException {
|
||||
@ -1588,35 +1693,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read from a file with a bunch of attribute/value pairs
|
||||
* that are separated by = and ignore comments with #.
|
||||
*/
|
||||
protected HashMap<String,String> readSettings(File inputFile) {
|
||||
HashMap<String,String> outgoing = new HashMap<String,String>();
|
||||
if (!inputFile.exists()) return outgoing; // return empty hash
|
||||
|
||||
String lines[] = PApplet.loadStrings(inputFile);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
int hash = lines[i].indexOf('#');
|
||||
String line = (hash == -1) ?
|
||||
lines[i].trim() : lines[i].substring(0, hash).trim();
|
||||
if (line.length() == 0) continue;
|
||||
|
||||
int equals = line.indexOf('=');
|
||||
if (equals == -1) {
|
||||
System.err.println("ignoring illegal line in " + inputFile);
|
||||
System.err.println(" " + line);
|
||||
continue;
|
||||
}
|
||||
String attr = line.substring(0, equals).trim();
|
||||
String valu = line.substring(equals + 1).trim();
|
||||
outgoing.put(attr, valu);
|
||||
}
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Slurps up .class files from a colon (or semicolon on windows)
|
||||
* separated list of paths and adds them to a ZipOutputStream.
|
||||
@ -1923,11 +1999,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<File> getImportedLibraries() {
|
||||
return importedLibraries;
|
||||
}
|
||||
|
||||
|
||||
public String getClassPath() {
|
||||
return classPath;
|
||||
}
|
||||
|
95
app/src/processing/app/StreamRedirectThread.java
Normal file
95
app/src/processing/app/StreamRedirectThread.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
|
||||
* @(#)StreamRedirectThread.java 1.4 03/01/23
|
||||
*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||
* modify and redistribute this software in source and binary code form,
|
||||
* provided that i) this copyright notice and license appear on all copies of
|
||||
* the software; and ii) Licensee does not utilize the software in a manner
|
||||
* which is disparaging to Sun.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* This software is not designed or intended for use in on-line control of
|
||||
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||
* the design, construction, operation or maintenance of any nuclear
|
||||
* facility. Licensee represents and warrants that it will not use or
|
||||
* redistribute the Software for such purposes.
|
||||
*/
|
||||
package processing.app;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* StreamRedirectThread is a thread which copies it's input to
|
||||
* it's output and terminates when it completes.
|
||||
*
|
||||
* @version @(#) StreamRedirectThread.java 1.4 03/01/23 23:33:38
|
||||
* @author Robert Field
|
||||
*/
|
||||
public class StreamRedirectThread extends Thread {
|
||||
|
||||
private final Reader in;
|
||||
private final Writer out;
|
||||
|
||||
private static final int BUFFER_SIZE = 2048;
|
||||
|
||||
|
||||
/**
|
||||
* Set up for copy.
|
||||
* @param name Name of the thread
|
||||
* @param in Stream to copy from
|
||||
* @param out Stream to copy to
|
||||
*/
|
||||
public StreamRedirectThread(String name, InputStream in, OutputStream out) {
|
||||
super(name);
|
||||
this.in = new InputStreamReader(in);
|
||||
this.out = new OutputStreamWriter(out);
|
||||
setPriority(Thread.MAX_PRIORITY-1);
|
||||
}
|
||||
|
||||
|
||||
public StreamRedirectThread(String name, Reader in, Writer out) {
|
||||
super(name);
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
setPriority(Thread.MAX_PRIORITY-1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
char[] cbuf = new char[BUFFER_SIZE];
|
||||
int count;
|
||||
//System.out.println("opening streamredirectthread");
|
||||
while ((count = in.read(cbuf, 0, BUFFER_SIZE)) >= 0) {
|
||||
out.write(cbuf, 0, count);
|
||||
// had to add the flush() here.. maybe shouldn't be using writer? [fry]
|
||||
out.flush();
|
||||
}
|
||||
//System.out.println("exiting streamredirectthread");
|
||||
out.flush();
|
||||
} catch(IOException exc) {
|
||||
System.err.println("Child I/O Transfer - " + exc);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,12 @@ import java.util.zip.*;
|
||||
//import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* An example of a very simple, multi-threaded HTTP server.
|
||||
* Taken from <a href="http://java.sun.com/developer/technicalArticles/Networking/Webserver/">this</a> article on java.sun.com.
|
||||
* This code is placed here in anticipation of running the reference from an
|
||||
* internal web server that reads the docs from a zip file, instead of using
|
||||
* thousands of .html files on the disk, which is really inefficient.
|
||||
* <p/>
|
||||
* This is a very simple, multi-threaded HTTP server, originally based on
|
||||
* <a href="http://j.mp/6BQwpI">this</a> article on java.sun.com.
|
||||
*/
|
||||
public class WebServer implements HttpConstants {
|
||||
|
||||
|
@ -65,7 +65,8 @@ public class EventThread extends Thread {
|
||||
// Maps ThreadReference to ThreadTrace instances
|
||||
private Map traceMap = new HashMap();
|
||||
|
||||
EventThread(Runner parent, VirtualMachine vm, String[] excludes, PrintWriter writer) {
|
||||
|
||||
public EventThread(Runner parent, VirtualMachine vm, String[] excludes, PrintWriter writer) {
|
||||
super("event-handler");
|
||||
this.parent = parent;
|
||||
this.vm = vm;
|
||||
@ -103,7 +104,7 @@ public class EventThread extends Thread {
|
||||
* @param excludes Class patterns for which we don't want events
|
||||
* @param watchFields Do we want to watch assignments to fields
|
||||
*/
|
||||
void setEventRequests(boolean watchFields) {
|
||||
public void setEventRequests(boolean watchFields) {
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
|
||||
// VMDeathRequest deathReq = mgr.createVMDeathRequest();
|
@ -29,7 +29,7 @@ import java.io.*;
|
||||
/**
|
||||
* Slurps up messages from compiler.
|
||||
*/
|
||||
class MessageSiphon implements Runnable {
|
||||
public class MessageSiphon implements Runnable {
|
||||
BufferedReader streamReader;
|
||||
Thread thread;
|
||||
MessageConsumer consumer;
|
||||
@ -84,4 +84,9 @@ class MessageSiphon implements Runnable {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Thread getThread() {
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
package processing.app.debug;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.preproc.PdePreprocessor;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.Point;
|
||||
@ -49,60 +50,54 @@ public class Runner implements MessageConsumer {
|
||||
private boolean presenting;
|
||||
|
||||
// Object that listens for error messages or exceptions.
|
||||
private RunnerListener listener;
|
||||
protected RunnerListener listener;
|
||||
|
||||
// Running remote VM
|
||||
private VirtualMachine vm;
|
||||
protected VirtualMachine vm;
|
||||
|
||||
// Thread transferring remote error stream to our error stream
|
||||
private Thread errThread = null;
|
||||
protected Thread errThread = null;
|
||||
|
||||
// Thread transferring remote output stream to our output stream
|
||||
private Thread outThread = null;
|
||||
protected Thread outThread = null;
|
||||
|
||||
// Mode for tracing the Trace program (default= 0 off)
|
||||
private int debugTraceMode = 0;
|
||||
protected int debugTraceMode = 0;
|
||||
|
||||
// Do we want to watch assignments to fields
|
||||
private boolean watchFields = false;
|
||||
protected boolean watchFields = false;
|
||||
|
||||
// Class patterns for which we don't want events
|
||||
private String[] excludes = {
|
||||
protected String[] excludes = {
|
||||
"java.*", "javax.*", "sun.*", "com.sun.*",
|
||||
"apple.*",
|
||||
"processing.*"
|
||||
};
|
||||
|
||||
private RunnerException exception;
|
||||
protected RunnerException exception;
|
||||
//private PrintStream leechErr;
|
||||
|
||||
private Editor editor;
|
||||
private Sketch sketch;
|
||||
protected Editor editor;
|
||||
protected Sketch sketch;
|
||||
private String appletClassName;
|
||||
|
||||
// private boolean newMessage;
|
||||
// private int messageLineCount;
|
||||
// private boolean foundMessageSource;
|
||||
//
|
||||
// private SystemOutSiphon processInput;
|
||||
// private OutputStream processOutput;
|
||||
// private MessageSiphon processError;
|
||||
|
||||
|
||||
public Runner(Sketch sketch, String appletClassName,
|
||||
boolean presenting, RunnerListener listener) {
|
||||
this.sketch = sketch;
|
||||
this.appletClassName = appletClassName;
|
||||
this.presenting = presenting;
|
||||
public Runner(RunnerListener listener, Sketch sketch) {
|
||||
this.listener = listener;
|
||||
this.sketch = sketch;
|
||||
|
||||
if (listener instanceof Editor) {
|
||||
this.editor = (Editor) listener;
|
||||
// } else {
|
||||
// System.out.println("actually it's a " + listener.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void launch() {
|
||||
public void launch(String appletClassName, boolean presenting) {
|
||||
this.appletClassName = appletClassName;
|
||||
this.presenting = presenting;
|
||||
|
||||
// TODO entire class is a total mess as of release 0136.
|
||||
// This will be cleaned up significantly over the next couple months.
|
||||
|
||||
@ -132,7 +127,7 @@ public class Runner implements MessageConsumer {
|
||||
|
||||
|
||||
protected String[] getMachineParams() {
|
||||
ArrayList params = new ArrayList();
|
||||
ArrayList<String> params = new ArrayList<String>();
|
||||
|
||||
//params.add("-Xint"); // interpreted mode
|
||||
//params.add("-Xprof"); // profiler
|
||||
@ -203,6 +198,13 @@ public class Runner implements MessageConsumer {
|
||||
protected String[] getSketchParams() {
|
||||
ArrayList<String> params = new ArrayList<String>();
|
||||
|
||||
// It's dangerous to add your own main() to your code,
|
||||
// but if you've done it, we'll respect your right to hang yourself.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=1446
|
||||
if (PdePreprocessor.foundMain) {
|
||||
params.add(appletClassName);
|
||||
|
||||
} else {
|
||||
params.add("processing.core.PApplet");
|
||||
|
||||
// If there was a saved location (this guy has been run more than once)
|
||||
@ -242,6 +244,7 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
|
||||
params.add(appletClassName);
|
||||
}
|
||||
|
||||
// String outgoing[] = new String[params.size()];
|
||||
// params.toArray(outgoing);
|
||||
@ -250,121 +253,11 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected VirtualMachine launchVirtualMachine_sun(String[] vmParams, String[] classParams) {
|
||||
//vm = launchTarget(sb.toString());
|
||||
LaunchingConnector connector =
|
||||
findLaunchingConnector("com.sun.jdi.CommandLineLaunch");
|
||||
//Map arguments = connectorArguments(connector, mainArgs);
|
||||
|
||||
PApplet.println(connector); // gets the defaults
|
||||
|
||||
Map arguments = connector.defaultArguments();
|
||||
//System.out.println(arguments);
|
||||
|
||||
// for (Iterator itr = arguments.keySet().iterator(); itr.hasNext(); ) {
|
||||
// Connector.Argument argument =
|
||||
// (Connector.Argument) arguments.get(itr.next());
|
||||
// System.out.println(argument);
|
||||
// }
|
||||
|
||||
//connector.transport().
|
||||
|
||||
Connector.Argument mainArg =
|
||||
(Connector.Argument)arguments.get("main");
|
||||
if (mainArg == null) {
|
||||
throw new Error("Bad launching connector");
|
||||
}
|
||||
String mainArgs = "";
|
||||
//mainArgs = addArgument(mainArgs, className);
|
||||
if (classParams != null) {
|
||||
for (int i = 0; i < classParams.length; i++) {
|
||||
mainArgs = addArgument(mainArgs, classParams[i], ' ');
|
||||
}
|
||||
}
|
||||
mainArg.setValue(mainArgs);
|
||||
|
||||
//System.out.println("main args are: ");
|
||||
//System.out.println(mainArgs);
|
||||
|
||||
// if (watchFields) {
|
||||
// // We need a VM that supports watchpoints
|
||||
// Connector.Argument optionArg =
|
||||
// (Connector.Argument)arguments.get("options");
|
||||
// if (optionArg == null) {
|
||||
// throw new Error("Bad launching connector");
|
||||
// }
|
||||
// optionArg.setValue("-classic");
|
||||
// }
|
||||
String optionArgs = "";
|
||||
for (int i = 0; i < vmParams.length; i++) {
|
||||
optionArgs = addArgument(optionArgs, vmParams[i], ' ');
|
||||
}
|
||||
// prevent any incorrect transport address b.s. from being added
|
||||
// -Xrunjdwp:transport=dt_socket,address=cincinnati118.ipcorporate.com:55422,suspend=y
|
||||
//optionArgs = addArgument(optionArgs, "-agentlib:jdwp=transport=dt_socket,address=localhost:12345,suspend=y", ' ');
|
||||
//optionArgs += " -Xrunjdwp:transport=dt_socket,address=localhost:55422,suspend=y";
|
||||
//optionArgs = optionArgs + " -agentlib:jdwp=transport=dt_socket";
|
||||
//optionArgs = addArgument(optionArgs, "-Xrunjdwp:transport=dt_socket,address=localhost:55422,suspend=y", ' ');
|
||||
|
||||
//optionArgs = addArgument(optionArgs, "address=127.0.0.1:54321", ' ');
|
||||
//optionArgs = addArgument(optionArgs, "localAddress", ' ');
|
||||
|
||||
Connector.Argument optionArg =
|
||||
(Connector.Argument)arguments.get("options");
|
||||
optionArg.setValue(optionArgs);
|
||||
|
||||
// Connector.Argument addressArg =
|
||||
// (Connector.Argument)arguments.get("address");
|
||||
//arguments.put("raw.address", new Connector.Argument("blah"));
|
||||
//PApplet.println("it's gonna be " + addressArg);
|
||||
|
||||
//arguments.put("address", "localhost");
|
||||
|
||||
// Connector.Argument addressArg =
|
||||
// (Connector.Argument)arguments.get("address");
|
||||
// addressArg.setValue("localhost");
|
||||
|
||||
// System.out.println("option args are: ");
|
||||
// System.out.println(arguments.get("options"));
|
||||
|
||||
System.out.println("args are " + arguments);
|
||||
|
||||
// com.sun.tools.jdi.SunCommandLineLauncher
|
||||
|
||||
// http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#sunlaunch
|
||||
try {
|
||||
return connector.launch(arguments);
|
||||
} catch (IOException exc) {
|
||||
throw new Error("Unable to launch target VM: " + exc);
|
||||
} catch (IllegalConnectorArgumentsException exc) {
|
||||
throw new Error("Internal error: " + exc);
|
||||
} catch (VMStartException exc) {
|
||||
exc.printStackTrace();
|
||||
System.err.println();
|
||||
System.err.println("Could not run the sketch.");
|
||||
System.err.println("Make sure that you haven't set the maximum available memory too high.");
|
||||
System.err.println("For more information, read revisions.txt and Help -> Troubleshooting.");
|
||||
//System.err.println("Target VM failed to initialize:");
|
||||
//System.err.println("msg is " + exc.getMessage());
|
||||
//exc.printStackTrace();
|
||||
//throw new Error("Target VM failed to initialize: " +
|
||||
//exc.getMessage());
|
||||
//throw new Error(exc.getMessage());
|
||||
//throw new RunnerException(exc.getMessage());
|
||||
//editor.error(exc);
|
||||
editor.error("Could not run the sketch.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
protected VirtualMachine launchVirtualMachine(String[] vmParams,
|
||||
String[] classParams) {
|
||||
//vm = launchTarget(sb.toString());
|
||||
LaunchingConnector connector =
|
||||
findLaunchingConnector("com.sun.jdi.RawCommandLineLaunch");
|
||||
LaunchingConnector connector = (LaunchingConnector)
|
||||
findConnector("com.sun.jdi.RawCommandLineLaunch");
|
||||
//PApplet.println(connector); // gets the defaults
|
||||
|
||||
//Map arguments = connectorArguments(connector, mainArgs);
|
||||
@ -447,9 +340,10 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
System.err.println("For more information, read revisions.txt and Help \u2192 Troubleshooting.");
|
||||
}
|
||||
if (editor != null) {
|
||||
// changing this to separate editor and listener [091124]
|
||||
//if (editor != null) {
|
||||
listener.statusError("Could not run the sketch.");
|
||||
}
|
||||
//}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -493,7 +387,7 @@ public class Runner implements MessageConsumer {
|
||||
* start threads to forward remote error and output streams,
|
||||
* resume the remote VM, wait for the final event, and shutdown.
|
||||
*/
|
||||
void generateTrace(PrintWriter writer) {
|
||||
protected void generateTrace(PrintWriter writer) {
|
||||
vm.setDebugTraceMode(debugTraceMode);
|
||||
|
||||
EventThread eventThread = null;
|
||||
@ -515,7 +409,7 @@ public class Runner implements MessageConsumer {
|
||||
// process.getErrorStream(),
|
||||
// System.err);
|
||||
MessageSiphon ms = new MessageSiphon(process.getErrorStream(), this);
|
||||
errThread = ms.thread;
|
||||
errThread = ms.getThread();
|
||||
|
||||
outThread = new StreamRedirectThread("output reader",
|
||||
process.getInputStream(),
|
||||
@ -545,7 +439,6 @@ public class Runner implements MessageConsumer {
|
||||
if (editor != null) {
|
||||
editor.internalRunnerClosed();
|
||||
}
|
||||
|
||||
} catch (InterruptedException exc) {
|
||||
// we don't interrupt
|
||||
}
|
||||
@ -554,20 +447,10 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a com.sun.jdi.CommandLineLaunch connector
|
||||
*/
|
||||
LaunchingConnector findLaunchingConnector(String connectorName) {
|
||||
//VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
|
||||
|
||||
// Get the default connector.
|
||||
// Not useful here since they all need different args.
|
||||
// System.out.println(Bootstrap.virtualMachineManager().defaultConnector());
|
||||
// return Bootstrap.virtualMachineManager().defaultConnector();
|
||||
|
||||
protected Connector findConnector(String connectorName) {
|
||||
List connectors = Bootstrap.virtualMachineManager().allConnectors();
|
||||
|
||||
// code to list available connectors
|
||||
// debug: code to list available connectors
|
||||
// Iterator iter2 = connectors.iterator();
|
||||
// while (iter2.hasNext()) {
|
||||
// Connector connector = (Connector)iter2.next();
|
||||
@ -578,10 +461,10 @@ public class Runner implements MessageConsumer {
|
||||
while (iter.hasNext()) {
|
||||
Connector connector = (Connector)iter.next();
|
||||
if (connector.name().equals(connectorName)) {
|
||||
return (LaunchingConnector)connector;
|
||||
return connector;
|
||||
}
|
||||
}
|
||||
throw new Error("No launching connector");
|
||||
throw new Error("No connector");
|
||||
}
|
||||
|
||||
|
||||
@ -611,7 +494,17 @@ public class Runner implements MessageConsumer {
|
||||
// System.out.println(or.referenceType().fields());
|
||||
// if (name.startsWith("java.lang.")) {
|
||||
// name = name.substring(10);
|
||||
if (exceptionName.equals("java.lang.OutOfMemoryError")) {
|
||||
if (!handleCommonErrors(exceptionName, message, listener)) {
|
||||
reportException(message, event.thread());
|
||||
}
|
||||
if (editor != null) {
|
||||
editor.internalRunnerClosed();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean handleCommonErrors(final String exceptionClass, final String message, final RunnerListener listener)
|
||||
{
|
||||
if (exceptionClass.equals("java.lang.OutOfMemoryError")) {
|
||||
listener.statusError("OutOfMemoryError: You may need to increase the memory setting in Preferences.");
|
||||
System.err.println("An OutOfMemoryError means that your code is either using up too much memory");
|
||||
System.err.println("because of a bug (e.g. creating an array that's too large, or unintentionally");
|
||||
@ -619,96 +512,83 @@ public class Runner implements MessageConsumer {
|
||||
System.err.println("If your sketch uses a lot of memory (for instance if it loads a lot of data files)");
|
||||
System.err.println("you can increase the memory available to your sketch using the Preferences window.");
|
||||
|
||||
} else if (exceptionName.equals("java.lang.StackOverflowError")) {
|
||||
} else if (exceptionClass.equals("java.lang.StackOverflowError")) {
|
||||
listener.statusError("StackOverflowError: This sketch is attempting too much recursion.");
|
||||
System.err.println("A StackOverflowError means that you have a bug that's causing a function");
|
||||
System.err.println("to be called recursively (it's calling itself and going in circles),");
|
||||
System.err.println("or you're intentionally calling a recursive function too much,");
|
||||
System.err.println("and your code should be rewritten in a more efficient manner.");
|
||||
|
||||
} else if (exceptionName.equals("java.lang.UnsupportedClassVersionError")) {
|
||||
} else if (exceptionClass.equals("java.lang.UnsupportedClassVersionError")) {
|
||||
listener.statusError("UnsupportedClassVersionError: A library is using code compiled with an unsupported version of Java.");
|
||||
System.err.println("This version of Processing only supports libraries and JAR files compiled for Java 1.5.");
|
||||
System.err.println("A library used by this sketch was compiled for Java 1.6 or later, ");
|
||||
System.err.println("and needs to be recompiled to be compatible with Java 1.5.");
|
||||
|
||||
} else if (exceptionName.equals("java.lang.NoSuchMethodError") || exceptionName.equals("java.lang.NoSuchFieldError")) {
|
||||
listener.statusError(exceptionName.substring(10) + ": You're probably using a library that's incompatible with this version of Processing.");
|
||||
|
||||
} else if (message.equals("ClassNotFoundException: quicktime.std.StdQTException")) {
|
||||
listener.statusError("Could not find QuickTime, please reinstall QuickTime 7 or later.");
|
||||
|
||||
} else if (exceptionClass.equals("java.lang.NoSuchMethodError") || exceptionClass.equals("java.lang.NoSuchFieldError")) {
|
||||
listener.statusError(exceptionClass.substring(10) + ": You're probably using a library that's incompatible with this version of Processing.");
|
||||
} else if (message!=null &&
|
||||
message.equals("ClassNotFoundException: quicktime.std.StdQTException")) {
|
||||
listener
|
||||
.statusError("Could not find QuickTime, please reinstall QuickTime 7 or later.");
|
||||
} else {
|
||||
reportException(message, event.thread());
|
||||
return false;
|
||||
}
|
||||
editor.internalRunnerClosed();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// This may be called more than one time per error in the VM,
|
||||
// TODO: This may be called more than one time per error in the VM,
|
||||
// presumably because exceptions might be wrapped inside others,
|
||||
// and this will fire for both.
|
||||
protected void reportException(String message, ThreadReference thread) {
|
||||
try {
|
||||
int codeIndex = -1;
|
||||
int lineNumber = -1;
|
||||
listener.statusError(findException(message, thread));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move through a list of stack frames, searching for references to code
|
||||
* found in the current sketch. Return with a RunnerException that contains
|
||||
* the location of the error, or if nothing is found, just return with a
|
||||
* RunnerException that wraps the error message itself.
|
||||
*/
|
||||
RunnerException findException(String message, ThreadReference thread) {
|
||||
try {
|
||||
// use to dump the stack for debugging
|
||||
// for (StackFrame frame : thread.frames()) {
|
||||
// System.out.println("frame: " + frame);
|
||||
// }
|
||||
|
||||
// Any of the thread.blah() methods can throw an AbsentInformationEx
|
||||
// if that bit of data is missing. If so, just write out the error
|
||||
// message to the console.
|
||||
List<StackFrame> frames = thread.frames();
|
||||
for (StackFrame frame : frames) {
|
||||
// System.out.println("frame: " + frame);
|
||||
try {
|
||||
Location location = frame.location();
|
||||
String filename = null;
|
||||
filename = location.sourceName();
|
||||
lineNumber = location.lineNumber();
|
||||
|
||||
String appletJavaFile = appletClassName + ".java";
|
||||
SketchCode errorCode = null;
|
||||
if (filename.equals(appletJavaFile)) {
|
||||
for (SketchCode code : sketch.getCode()) {
|
||||
if (code.isExtension("pde")) {
|
||||
if (lineNumber >= code.getPreprocOffset()) {
|
||||
errorCode = code;
|
||||
int lineNumber = location.lineNumber() - 1;
|
||||
RunnerException rex =
|
||||
sketch.placeException(message, filename, lineNumber);
|
||||
if (rex != null) {
|
||||
return rex;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (SketchCode code : sketch.getCode()) {
|
||||
if (code.isExtension("java")) {
|
||||
if (filename.equals(code.getFileName())) {
|
||||
errorCode = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
codeIndex = sketch.getCodeIndex(errorCode);
|
||||
|
||||
if (codeIndex != -1) {
|
||||
//System.out.println("got line num " + lineNumber);
|
||||
// in case this was a tab that got embedded into the main .java
|
||||
lineNumber -= sketch.getCode(codeIndex).getPreprocOffset();
|
||||
|
||||
// lineNumber is 1-indexed, but editor wants zero-indexed
|
||||
lineNumber--;
|
||||
|
||||
// getMessage() will be what's shown in the editor
|
||||
exception = new RunnerException(message, codeIndex, lineNumber, -1);
|
||||
exception.hideStackTrace();
|
||||
listener.statusError(exception);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (AbsentInformationException e) {
|
||||
// Any of the thread.blah() methods can throw an AbsentInformationEx
|
||||
// if that bit of data is missing. If so, just write out the error
|
||||
// message to the console.
|
||||
//e.printStackTrace(); // not useful
|
||||
exception = new RunnerException(message);
|
||||
exception.hideStackTrace();
|
||||
listener.statusError(exception);
|
||||
|
||||
}
|
||||
}
|
||||
} catch (IncompatibleThreadStateException e) {
|
||||
// This shouldn't happen, but if it does, print the exception in case
|
||||
// it's something that needs to be debugged separately.
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Give up, nothing found inside the pile of stack frames
|
||||
RunnerException rex = new RunnerException(message);
|
||||
// exception is being created /here/, so stack trace is not useful
|
||||
rex.hideStackTrace();
|
||||
return rex;
|
||||
}
|
||||
|
||||
|
||||
@ -727,26 +607,7 @@ public class Runner implements MessageConsumer {
|
||||
}
|
||||
vm = null;
|
||||
}
|
||||
|
||||
//if (window != null) window.hide();
|
||||
// if (window != null) {
|
||||
// //System.err.println("disposing window");
|
||||
// window.dispose();
|
||||
// window = null;
|
||||
// }
|
||||
|
||||
/*
|
||||
if (process != null) {
|
||||
try {
|
||||
process.destroy();
|
||||
} catch (Exception e) {
|
||||
//System.err.println("(ignored) error while destroying");
|
||||
//e.printStackTrace();
|
||||
}
|
||||
process = null;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// made synchronized for rev 87
|
||||
@ -762,7 +623,10 @@ public class Runner implements MessageConsumer {
|
||||
// that signals that the applet has been quit.
|
||||
if (s.indexOf(PApplet.EXTERNAL_STOP) == 0) {
|
||||
//System.out.println("external: quit");
|
||||
editor.internalCloseRunner();
|
||||
if (editor != null) {
|
||||
//editor.internalCloseRunner(); // [091124]
|
||||
editor.handleStop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -773,281 +637,23 @@ public class Runner implements MessageConsumer {
|
||||
int space = nums.indexOf(' ');
|
||||
int left = Integer.parseInt(nums.substring(0, space));
|
||||
int top = Integer.parseInt(nums.substring(space + 1));
|
||||
// this is only fired when connected to an editor
|
||||
editor.setSketchLocation(new Point(left, top));
|
||||
//System.out.println("external: move to " + left + " " + top);
|
||||
return;
|
||||
}
|
||||
|
||||
// Removed while doing cleaning for 0145,
|
||||
// it seems that this is never actually printed out.
|
||||
/*
|
||||
// this is PApplet sending a message saying "i'm about to spew
|
||||
// a stack trace because an error occurred during PApplet.run()"
|
||||
if (s.indexOf(PApplet.LEECH_WAKEUP) == 0) {
|
||||
// newMessage being set to 'true' means that the next time
|
||||
// message() is called, expect the first line of the actual
|
||||
// error message & stack trace to be sent from the applet.
|
||||
newMessage = true;
|
||||
return; // this line ignored
|
||||
}
|
||||
*/
|
||||
|
||||
// these are used for debugging, in case there are concerns
|
||||
// that some errors aren't coming through properly
|
||||
/*
|
||||
if (s.length() > 2) {
|
||||
System.err.println(newMessage);
|
||||
System.err.println("message " + s.length() + ":" + s);
|
||||
}
|
||||
*/
|
||||
// if (s.length() > 2) {
|
||||
// System.err.println(newMessage);
|
||||
// System.err.println("message " + s.length() + ":" + s);
|
||||
// }
|
||||
|
||||
// always shove out the mesage, since it might not fall under
|
||||
// the same setup as we're expecting
|
||||
System.err.print(s);
|
||||
//System.err.println("[" + s.length() + "] " + s);
|
||||
System.err.flush();
|
||||
|
||||
// // exit here because otherwise the exception name
|
||||
// // may be titled with a blank string
|
||||
// if (s.trim().length() == 0) return;
|
||||
//
|
||||
// // annoying, because it seems as though the terminators
|
||||
// // aren't being sent properly
|
||||
// //System.err.println(s);
|
||||
//
|
||||
// //if (newMessage && s.length() > 2) {
|
||||
// if (newMessage) {
|
||||
// exception = new RunnerException(s); // type of java ex
|
||||
// exception.hideStackTrace();
|
||||
// //System.out.println("setting ex type to " + s);
|
||||
// newMessage = false;
|
||||
// foundMessageSource = false;
|
||||
// messageLineCount = 0;
|
||||
//
|
||||
// } else {
|
||||
// messageLineCount++;
|
||||
//
|
||||
// /*
|
||||
//java.lang.NullPointerException
|
||||
// at javatest.<init>(javatest.java:5)
|
||||
// at Temporary_2425_1153.draw(Temporary_2425_1153.java:11)
|
||||
// at PApplet.nextFrame(PApplet.java:481)
|
||||
// at PApplet.run(PApplet.java:428)
|
||||
// at java.lang.Thread.run(Unknown Source)
|
||||
// */
|
||||
//
|
||||
// if (!foundMessageSource) {
|
||||
// // " at javatest.<init>(javatest.java:5)"
|
||||
// // -> "javatest.<init>(javatest.java:5)"
|
||||
// int atIndex = s.indexOf("at ");
|
||||
// if (atIndex == -1) {
|
||||
// //System.err.println(s); // stop double-printing exceptions
|
||||
// return;
|
||||
// }
|
||||
// s = s.substring(atIndex + 3);
|
||||
//
|
||||
// // added for 0124 to improve error handling
|
||||
// // not highlighting lines if it's in the p5 code
|
||||
// if (s.startsWith("processing.")) return;
|
||||
// // no highlight if it's java.lang.whatever
|
||||
// if (s.startsWith("java.")) return;
|
||||
//
|
||||
// // "javatest.<init>(javatest.java:5)"
|
||||
// // -> "javatest.<init>" and "(javatest.java:5)"
|
||||
// int startParen = s.indexOf('(');
|
||||
// // at javatest.<init>(javatest.java:5)
|
||||
// //String pkgClassFxn = null;
|
||||
// //String fileLine = null;
|
||||
// int codeIndex = -1;
|
||||
// int lineNumber = -1;
|
||||
//
|
||||
// if (startParen == -1) {
|
||||
// //pkgClassFxn = s;
|
||||
//
|
||||
// } else {
|
||||
// //pkgClassFxn = s.substring(0, startParen);
|
||||
//
|
||||
// // "(javatest.java:5)"
|
||||
// String fileAndLine = s.substring(startParen + 1);
|
||||
// int stopParen = fileAndLine.indexOf(')');
|
||||
// //fileAndLine = fileAndLine.substring(0, fileAndLine.length() - 1);
|
||||
// fileAndLine = fileAndLine.substring(0, stopParen);
|
||||
// //System.out.println("file 'n line " + fileAndLine);
|
||||
//
|
||||
// //if (!fileAndLine.equals("Unknown Source")) {
|
||||
// // "javatest.java:5"
|
||||
// int colonIndex = fileAndLine.indexOf(':');
|
||||
// if (colonIndex != -1) {
|
||||
// String filename = fileAndLine.substring(0, colonIndex);
|
||||
// // "javatest.java" and "5"
|
||||
// //System.out.println("filename = " + filename);
|
||||
// //System.out.println("pre0 = " + sketch.code[0].preprocName);
|
||||
// //for (int i = 0; i < sketch.codeCount; i++) {
|
||||
// //System.out.println(i + " " + sketch.code[i].lineOffset + " " +
|
||||
// // sketch.code[i].preprocName);
|
||||
// //}
|
||||
// lineNumber =
|
||||
// Integer.parseInt(fileAndLine.substring(colonIndex + 1)) - 1;
|
||||
//
|
||||
// for (int i = 0; i < sketch.getCodeCount(); i++) {
|
||||
// SketchCode code = sketch.getCode(i);
|
||||
// //System.out.println(code.preprocName + " " + lineNumber + " " +
|
||||
// // code.preprocOffset);
|
||||
// if (((code.preprocName == null) &&
|
||||
// (lineNumber >= code.preprocOffset)) ||
|
||||
// ((code.preprocName != null) &&
|
||||
// code.preprocName.equals(filename))) {
|
||||
// codeIndex = i;
|
||||
// //System.out.println("got codeindex " + codeIndex);
|
||||
// //break;
|
||||
// //} else if (
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (codeIndex != -1) {
|
||||
// //System.out.println("got line num " + lineNumber);
|
||||
// // in case this was a tab that got embedded into the main .java
|
||||
// lineNumber -= sketch.getCode(codeIndex).preprocOffset;
|
||||
//
|
||||
// // this may have a paren on the end, if so need to strip
|
||||
// // down to just the digits
|
||||
// /*
|
||||
// int lastNumberIndex = colonIndex + 1;
|
||||
// while ((lastNumberIndex < fileAndLine.length()) &&
|
||||
// Character.isDigit(fileAndLine.charAt(lastNumberIndex))) {
|
||||
// lastNumberIndex++;
|
||||
// }
|
||||
// */
|
||||
//
|
||||
// // lineNumber is 1-indexed, but editor wants zero-indexed
|
||||
// // getMessage() will be what's shown in the editor
|
||||
// exception =
|
||||
// new RunnerException(exception.getMessage(),
|
||||
// codeIndex, lineNumber, -1);
|
||||
// exception.hideStackTrace();
|
||||
// foundMessageSource = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// editor.error(exception);
|
||||
//
|
||||
// /*
|
||||
// int index = s.indexOf(className + ".java");
|
||||
// if (index != -1) {
|
||||
// int len = (className + ".java").length();
|
||||
// String lineNumberStr = s.substring(index + len + 1);
|
||||
// index = lineNumberStr.indexOf(')');
|
||||
// lineNumberStr = lineNumberStr.substring(0, index);
|
||||
// try {
|
||||
// exception.line = Integer.parseInt(lineNumberStr) - 1; //2;
|
||||
// } catch (NumberFormatException e) { }
|
||||
// //e.printStackTrace(); // a recursive error waiting to happen?
|
||||
// // if nfe occurs, who cares, still send the error on up
|
||||
// editor.error(exception);
|
||||
// */
|
||||
//
|
||||
// /*
|
||||
// // WARNING THESE ARE DISABLED!!
|
||||
// } else if ((index = s.indexOf(className + ".class")) != -1) {
|
||||
// // code to check for:
|
||||
// // at Temporary_484_3845.loop(Compiled Code)
|
||||
// // would also probably get:
|
||||
// // at Temporary_484_3845.loop
|
||||
// // which (i believe) is used by the mac and/or jview
|
||||
// String functionStr = s.substring(index +
|
||||
// (className + ".class").length() + 1);
|
||||
// index = functionStr.indexOf('(');
|
||||
// if (index != -1) {
|
||||
// functionStr = functionStr.substring(0, index);
|
||||
// }
|
||||
// exception = new RunnerException(//"inside \"" + functionStr + "()\": " +
|
||||
// exception.getMessage() +
|
||||
// " inside " + functionStr + "() " +
|
||||
// "[add Compiler.disable() to setup()]");
|
||||
// editor.error(exception);
|
||||
// // this will fall through in tihs example:
|
||||
// // at Temporary_4636_9696.pootie(Compiled Code)
|
||||
// // at Temporary_4636_9696.loop(Temporary_4636_9696.java:24)
|
||||
// // because pootie() (re)sets the exception title
|
||||
// // and throws it, but then the line number gets set
|
||||
// // because of the line that comes after
|
||||
// */
|
||||
//
|
||||
// } else if (messageLineCount > 10) { // 5 -> 10 for 0088
|
||||
// // this means the class name may not be mentioned
|
||||
// // in the stack trace.. this is just a general purpose
|
||||
// // error, but needs to make it through anyway.
|
||||
// // so if five lines have gone past, might as well signal
|
||||
// messageLineCount = -100;
|
||||
// exception = new RunnerException(exception.getMessage());
|
||||
// exception.hideStackTrace();
|
||||
// editor.error(exception);
|
||||
//
|
||||
// } else {
|
||||
// //System.err.print(s);
|
||||
// }
|
||||
// //System.out.println("got it " + s);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Siphons from an InputStream of System.out (from a Process)
|
||||
* and sends it to the real System.out.
|
||||
*/
|
||||
class SystemOutSiphon implements Runnable {
|
||||
InputStream input;
|
||||
Thread thread;
|
||||
|
||||
public SystemOutSiphon(InputStream input) {
|
||||
this.input = input;
|
||||
|
||||
thread = new Thread(this);
|
||||
// unless this is set to min, it seems to hork the app
|
||||
// since it's in charge of stuffing the editor console with strings
|
||||
// maybe it's time to get rid of/fix that friggin console
|
||||
// ...disabled for 0075, with 0074's fix for code folder hanging
|
||||
// this only seems to make the console unresponsive
|
||||
//thread.setPriority(Thread.MIN_PRIORITY);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
byte boofer[] = new byte[256];
|
||||
|
||||
while (Thread.currentThread() == thread) {
|
||||
try {
|
||||
// can't use a buffered reader here because incremental
|
||||
// print statements are interesting too.. causes some
|
||||
// disparity with how System.err gets spewed, oh well.
|
||||
int count = input.read(boofer, 0, boofer.length);
|
||||
if (count == -1) {
|
||||
thread = null;
|
||||
|
||||
} else {
|
||||
System.out.print(new String(boofer, 0, count));
|
||||
//System.out.flush();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// this is prolly because the app was quit & the stream broken
|
||||
//e.printStackTrace(System.out);
|
||||
//e.printStackTrace();
|
||||
thread = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
//System.out.println("SystemOutSiphon: i just died in your arms tonight");
|
||||
// on mac os x, this will spew a "Bad File Descriptor" ex
|
||||
// each time an external app is shut down.
|
||||
//e.printStackTrace();
|
||||
thread = null;
|
||||
//System.out.println("");
|
||||
}
|
||||
//System.out.println("SystemOutSiphon: out");
|
||||
//thread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,10 +37,18 @@ public class RunnerException extends Exception /*RuntimeException*/ {
|
||||
|
||||
|
||||
public RunnerException(String message) {
|
||||
this(message, -1, -1, -1, true);
|
||||
this(message, true);
|
||||
}
|
||||
|
||||
public RunnerException(String message, boolean showStackTrace) {
|
||||
this(message, -1, -1, -1, showStackTrace);
|
||||
}
|
||||
|
||||
public RunnerException(String message, int file, int line) {
|
||||
this(message, file, line, -1, true);
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(String message, int file, int line, int column) {
|
||||
this(message, file, line, column, true);
|
||||
}
|
||||
|
@ -28,4 +28,6 @@ public interface RunnerListener {
|
||||
public void statusError(String message);
|
||||
|
||||
public void statusError(Exception exception);
|
||||
|
||||
public void statusNotice(String message);
|
||||
}
|
@ -67,10 +67,18 @@ public class Platform extends processing.app.Platform {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Attempt to use xdg-open
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String[] { "xdg-open" });
|
||||
p.waitFor();
|
||||
Preferences.set("launcher", "xdg-open");
|
||||
return true;
|
||||
} catch (Exception e) { }
|
||||
|
||||
// Attempt to use gnome-open
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
|
||||
/*int result =*/ p.waitFor();
|
||||
p.waitFor();
|
||||
// Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
|
||||
Preferences.set("launcher", "gnome-open");
|
||||
return true;
|
||||
@ -79,7 +87,7 @@ public class Platform extends processing.app.Platform {
|
||||
// Attempt with kde-open
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
|
||||
/*int result =*/ p.waitFor();
|
||||
p.waitFor();
|
||||
Preferences.set("launcher", "kde-open");
|
||||
return true;
|
||||
} catch (Exception e) { }
|
||||
@ -100,7 +108,8 @@ public class Platform extends processing.app.Platform {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
System.out.println("not available");
|
||||
System.out.println("No launcher set, cannot open " +
|
||||
file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,15 @@ package processing.app.macosx;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.apple.eio.FileManager;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
/**
|
||||
@ -103,36 +106,45 @@ public class Platform extends processing.app.Platform {
|
||||
|
||||
|
||||
public void openURL(String url) throws Exception {
|
||||
if (!url.startsWith("http://")) {
|
||||
if (PApplet.javaVersion < 1.6f) {
|
||||
if (url.startsWith("http://")) {
|
||||
// formerly com.apple.eio.FileManager.openURL(url);
|
||||
// but due to deprecation, instead loading dynamically
|
||||
try {
|
||||
Class<?> eieio = Class.forName("com.apple.eio.FileManager");
|
||||
Method openMethod =
|
||||
eieio.getMethod("openURL", new Class[] { String.class });
|
||||
openMethod.invoke(null, new Object[] { url });
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
// Assume this is a file instead, and just open it.
|
||||
// Extension of http://dev.processing.org/bugs/show_bug.cgi?id=1010
|
||||
processing.core.PApplet.open(url);
|
||||
|
||||
/*
|
||||
// prepend file:// on this guy since it's a file
|
||||
url = "file://" + url;
|
||||
|
||||
// replace spaces with %20 for the file url
|
||||
// otherwise the mac doesn't like to open it
|
||||
// can't just use URLEncoder, since that makes slashes into
|
||||
// %2F characters, which is no good. some might say "useless"
|
||||
if (url.indexOf(' ') != -1) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
char c[] = url.toCharArray();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if (c[i] == ' ') {
|
||||
sb.append("%20");
|
||||
} else {
|
||||
sb.append(c[i]);
|
||||
}
|
||||
}
|
||||
url = sb.toString();
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
try {
|
||||
Class<?> desktopClass = Class.forName("java.awt.Desktop");
|
||||
Method getMethod = desktopClass.getMethod("getDesktop");
|
||||
Object desktop = getMethod.invoke(null, new Object[] { });
|
||||
|
||||
// for Java 1.6, replacing with java.awt.Desktop.browse()
|
||||
// and java.awt.Desktop.open()
|
||||
if (url.startsWith("http://")) { // browse to a location
|
||||
Method browseMethod =
|
||||
desktopClass.getMethod("browse", new Class[] { URI.class });
|
||||
browseMethod.invoke(desktop, new Object[] { new URI(url) });
|
||||
} else { // open a file
|
||||
Method openMethod =
|
||||
desktopClass.getMethod("open", new Class[] { File.class });
|
||||
openMethod.invoke(desktop, new Object[] { new File(url) });
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// for Java 1.6, replace with java.awt.Desktop.browse() and java.awt.Desktop.open()
|
||||
com.apple.eio.FileManager.openURL(url);
|
||||
}
|
||||
|
||||
|
||||
public boolean openFolderAvailable() {
|
||||
|
@ -50,7 +50,8 @@ public class ThinkDifferent implements ApplicationListener {
|
||||
|
||||
static protected void init(Base base) {
|
||||
if (application == null) {
|
||||
application = new com.apple.eawt.Application();
|
||||
//application = new com.apple.eawt.Application();
|
||||
application = com.apple.eawt.Application.getApplication();
|
||||
}
|
||||
if (adapter == null) {
|
||||
adapter = new ThinkDifferent(base);
|
||||
|
@ -51,15 +51,9 @@ public class PdePreprocessor {
|
||||
|
||||
List prototypes;
|
||||
|
||||
|
||||
|
||||
|
||||
String[] defaultImports;
|
||||
|
||||
// these ones have the .* at the end, since a class name might be at the end
|
||||
// instead of .* which would make trouble other classes using this can lop
|
||||
// off the . and anything after it to produce a package name consistently.
|
||||
//public String extraImports[];
|
||||
ArrayList<String> programImports;
|
||||
|
||||
// imports just from the code folder, treated differently
|
||||
@ -71,24 +65,24 @@ public class PdePreprocessor {
|
||||
PrintStream stream;
|
||||
String program;
|
||||
String buildPath;
|
||||
// starts as sketch name, ends as main class name
|
||||
String name;
|
||||
|
||||
|
||||
/**
|
||||
* Setup a new preprocessor.
|
||||
*/
|
||||
public PdePreprocessor() { }
|
||||
|
||||
public int writePrefix(String program, String buildPath,
|
||||
String name, String codeFolderPackages[])
|
||||
throws FileNotFoundException {
|
||||
this.buildPath = buildPath;
|
||||
this.name = name;
|
||||
|
||||
public PdePreprocessor() {
|
||||
int tabSize = Preferences.getInteger("editor.tabs.size");
|
||||
char[] indentChars = new char[tabSize];
|
||||
Arrays.fill(indentChars, ' ');
|
||||
indent = new String(indentChars);
|
||||
}
|
||||
|
||||
public int writePrefix(String program, String buildPath,
|
||||
String sketchName, String codeFolderPackages[]) throws FileNotFoundException {
|
||||
this.buildPath = buildPath;
|
||||
this.name = sketchName;
|
||||
|
||||
// if the program ends with no CR or LF an OutOfMemoryError will happen.
|
||||
// not gonna track down the bug now, so here's a hack for it:
|
||||
@ -99,52 +93,13 @@ public class PdePreprocessor {
|
||||
// an OutOfMemoryError or NullPointerException will happen.
|
||||
// again, not gonna bother tracking this down, but here's a hack.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=16
|
||||
Sketch.scrubComments(program);
|
||||
// this returns the scrubbed version, but more important for this
|
||||
// function, it'll check to see if there are errors with the comments.
|
||||
String scrubbed = Sketch.scrubComments(program);
|
||||
// If there are errors, an exception is thrown and this fxn exits.
|
||||
|
||||
if (Preferences.getBoolean("preproc.substitute_unicode")) {
|
||||
// check for non-ascii chars (these will be/must be in unicode format)
|
||||
char p[] = program.toCharArray();
|
||||
int unicodeCount = 0;
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] > 127) unicodeCount++;
|
||||
}
|
||||
// if non-ascii chars are in there, convert to unicode escapes
|
||||
if (unicodeCount != 0) {
|
||||
// add unicodeCount * 5.. replacing each unicode char
|
||||
// with six digit uXXXX sequence (xxxx is in hex)
|
||||
// (except for nbsp chars which will be a replaced with a space)
|
||||
int index = 0;
|
||||
char p2[] = new char[p.length + unicodeCount*5];
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] < 128) {
|
||||
p2[index++] = p[i];
|
||||
|
||||
} else if (p[i] == 160) { // unicode for non-breaking space
|
||||
p2[index++] = ' ';
|
||||
|
||||
} else {
|
||||
int c = p[i];
|
||||
p2[index++] = '\\';
|
||||
p2[index++] = 'u';
|
||||
char str[] = Integer.toHexString(c).toCharArray();
|
||||
// add leading zeros, so that the length is 4
|
||||
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
|
||||
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
|
||||
System.arraycopy(str, 0, p2, index, str.length);
|
||||
index += str.length;
|
||||
}
|
||||
}
|
||||
program = new String(p2, 0, index);
|
||||
}
|
||||
program = substituteUnicode(program);
|
||||
}
|
||||
|
||||
// These may change in-between (if the prefs panel adds this option)
|
||||
// so grab them here on construction.
|
||||
String prefsLine = Preferences.get("preproc.imports");
|
||||
defaultImports = PApplet.splitTokens(prefsLine, ", ");
|
||||
|
||||
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
|
||||
String importRegexp = "^\\s*#include\\s+[<\"](\\S+)[\">]";
|
||||
programImports = new ArrayList<String>();
|
||||
@ -184,8 +139,47 @@ public class PdePreprocessor {
|
||||
return headerCount + prototypeCount;
|
||||
}
|
||||
|
||||
|
||||
static String substituteUnicode(String program) {
|
||||
// check for non-ascii chars (these will be/must be in unicode format)
|
||||
char p[] = program.toCharArray();
|
||||
int unicodeCount = 0;
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] > 127) unicodeCount++;
|
||||
}
|
||||
// if non-ascii chars are in there, convert to unicode escapes
|
||||
if (unicodeCount != 0) {
|
||||
// add unicodeCount * 5.. replacing each unicode char
|
||||
// with six digit uXXXX sequence (xxxx is in hex)
|
||||
// (except for nbsp chars which will be a replaced with a space)
|
||||
int index = 0;
|
||||
char p2[] = new char[p.length + unicodeCount*5];
|
||||
for (int i = 0; i < p.length; i++) {
|
||||
if (p[i] < 128) {
|
||||
p2[index++] = p[i];
|
||||
|
||||
} else if (p[i] == 160) { // unicode for non-breaking space
|
||||
p2[index++] = ' ';
|
||||
|
||||
} else {
|
||||
int c = p[i];
|
||||
p2[index++] = '\\';
|
||||
p2[index++] = 'u';
|
||||
char str[] = Integer.toHexString(c).toCharArray();
|
||||
// add leading zeros, so that the length is 4
|
||||
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
|
||||
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
|
||||
System.arraycopy(str, 0, p2, index, str.length);
|
||||
index += str.length;
|
||||
}
|
||||
}
|
||||
program = new String(p2, 0, index);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
/**
|
||||
* preprocesses a pde file and write out a java file
|
||||
* preprocesses a pde file and writes out a java file
|
||||
* @return the classname of the exported Java
|
||||
*/
|
||||
//public String write(String program, String buildPath, String name,
|
||||
|
@ -24,7 +24,7 @@ import java.util.*;
|
||||
* to the implementations of this class to do so.
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: InputHandler.java 4168 2008-08-09 17:24:37Z fry $
|
||||
* @version $Id: InputHandler.java 6126 2010-02-16 23:43:53Z fry $
|
||||
*/
|
||||
public abstract class InputHandler extends KeyAdapter
|
||||
{
|
||||
@ -70,6 +70,9 @@ public abstract class InputHandler extends KeyAdapter
|
||||
public static final ActionListener SELECT_PREV_WORD = new prev_word(true);
|
||||
public static final ActionListener REPEAT = new repeat();
|
||||
public static final ActionListener TOGGLE_RECT = new toggle_rect();
|
||||
public static final ActionListener CLIPBOARD_CUT = new clipboard_cut(); // [fry]
|
||||
public static final ActionListener CLIPBOARD_COPY = new clipboard_copy();
|
||||
public static final ActionListener CLIPBOARD_PASTE = new clipboard_paste();
|
||||
|
||||
// Default action
|
||||
public static final ActionListener INSERT_CHAR = new insert_char();
|
||||
@ -113,6 +116,9 @@ public abstract class InputHandler extends KeyAdapter
|
||||
actions.put("repeat",REPEAT);
|
||||
actions.put("toggle-rect",TOGGLE_RECT);
|
||||
actions.put("insert-char",INSERT_CHAR);
|
||||
actions.put("clipboard-cut",CLIPBOARD_CUT);
|
||||
actions.put("clipboard-copy",CLIPBOARD_COPY);
|
||||
actions.put("clipboard-paste",CLIPBOARD_PASTE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1077,6 +1083,34 @@ public abstract class InputHandler extends KeyAdapter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class clipboard_cut implements ActionListener
|
||||
{
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
getTextArea(evt).cut();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class clipboard_copy implements ActionListener
|
||||
{
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
getTextArea(evt).copy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class clipboard_paste implements ActionListener
|
||||
{
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
getTextArea(evt).paste();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class insert_char implements ActionListener,
|
||||
InputHandler.NonRepeatable
|
||||
{
|
||||
|
@ -22,6 +22,9 @@ import java.awt.event.*;
|
||||
import java.awt.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
|
||||
import processing.app.syntax.im.InputMethodSupport;
|
||||
|
||||
/**
|
||||
* jEdit's text area component. It is more suited for editing program
|
||||
@ -51,7 +54,7 @@ import java.util.Vector;
|
||||
* + "}");</pre>
|
||||
*
|
||||
* @author Slava Pestov
|
||||
* @version $Id: JEditTextArea.java 5625 2009-06-07 21:08:59Z fry $
|
||||
* @version $Id: JEditTextArea.java 6123 2010-02-16 21:43:44Z fry $
|
||||
*/
|
||||
public class JEditTextArea extends JComponent
|
||||
{
|
||||
@ -127,6 +130,16 @@ public class JEditTextArea extends JComponent
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline Input Method Support for Japanese.
|
||||
*/
|
||||
private InputMethodSupport inputMethodSupport = null;
|
||||
public InputMethodRequests getInputMethodRequests() {
|
||||
if (inputMethodSupport == null) {
|
||||
inputMethodSupport = new InputMethodSupport(this);
|
||||
}
|
||||
return inputMethodSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current position of the vertical scroll bar. [fry]
|
||||
|
@ -34,18 +34,22 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
||||
inputHandler = new DefaultInputHandler();
|
||||
//inputHandler.addDefaultKeyBindings(); // 0122
|
||||
|
||||
// use option on mac for things that are ctrl on windows/linux
|
||||
// use option on mac for text edit controls that are ctrl on windows/linux
|
||||
String mod = Base.isMacOS() ? "A" : "C";
|
||||
|
||||
// right now, ctrl-up/down is select up/down, but mod should be
|
||||
// used instead, because the mac expects it to be option(alt)
|
||||
|
||||
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
|
||||
// for 0122, shift-backspace is delete, for 0176, it's now a preference,
|
||||
// to prevent holy warriors from attacking me for it.
|
||||
if (Preferences.getBoolean("editor.keys.shift_backspace_is_delete")) {
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.DELETE);
|
||||
} else {
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||
}
|
||||
|
||||
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
|
||||
|
||||
//inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||
// for 0122, shift-backspace is delete
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.DELETE);
|
||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
|
||||
|
||||
// the following two were changing for 0122 for better mac/pc compatability
|
||||
@ -57,12 +61,23 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
||||
//inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
|
||||
|
||||
inputHandler.addKeyBinding("INSERT", InputHandler.OVERWRITE);
|
||||
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=162
|
||||
// added for 0176, though the bindings do not appear relevant for osx
|
||||
if (Preferences.getBoolean("editor.keys.alternative_cut_copy_paste")) {
|
||||
inputHandler.addKeyBinding("C+INSERT", InputHandler.CLIPBOARD_COPY);
|
||||
inputHandler.addKeyBinding("S+INSERT", InputHandler.CLIPBOARD_PASTE);
|
||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.CLIPBOARD_CUT);
|
||||
}
|
||||
|
||||
// disabling for 0122, not sure what this does
|
||||
//inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
|
||||
|
||||
// for 0122, these have been changed for better compatability
|
||||
// for 0122, these have been changed for better compatibility
|
||||
// HOME and END now mean the beginning/end of the document
|
||||
if (Base.isMacOS()) {
|
||||
// for 0176 changed this to a preference so that the Mac OS X people
|
||||
// can get the "normal" behavior as well if they prefer.
|
||||
if (Preferences.getBoolean("editor.keys.home_and_end_travel_far")) {
|
||||
inputHandler.addKeyBinding("HOME", InputHandler.DOCUMENT_HOME);
|
||||
inputHandler.addKeyBinding("END", InputHandler.DOCUMENT_END);
|
||||
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_DOC_HOME);
|
||||
|
@ -12,6 +12,7 @@
|
||||
package processing.app.syntax;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.syntax.im.CompositionTextPainter;
|
||||
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.text.*;
|
||||
@ -33,6 +34,9 @@ implements TabExpander, Printable
|
||||
/** Current setting for editor.antialias preference */
|
||||
boolean antialias;
|
||||
|
||||
/** A specific painter composed by the InputMethod.*/
|
||||
protected CompositionTextPainter compositionTextPainter;
|
||||
|
||||
/**
|
||||
* Creates a new repaint manager. This should be not be called
|
||||
* directly.
|
||||
@ -73,6 +77,16 @@ implements TabExpander, Printable
|
||||
eolMarkers = defaults.eolMarkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CompositionTextPainter. if CompositionTextPainter is not created, create it.
|
||||
*/
|
||||
public CompositionTextPainter getCompositionTextpainter(){
|
||||
if(compositionTextPainter == null){
|
||||
compositionTextPainter = new CompositionTextPainter(textArea);
|
||||
}
|
||||
return compositionTextPainter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this component can be traversed by pressing the
|
||||
* Tab key. This returns false.
|
||||
@ -602,7 +616,12 @@ implements TabExpander, Printable
|
||||
|
||||
y += fm.getHeight();
|
||||
x = Utilities.drawTabbedText(currentLine,x,y,gfx,this,0);
|
||||
|
||||
/*
|
||||
* Draw characters via input method.
|
||||
*/
|
||||
if (compositionTextPainter != null && compositionTextPainter.hasComposedTextLayout()) {
|
||||
compositionTextPainter.draw(gfx, lineHighlightColor);
|
||||
}
|
||||
if (eolMarkers) {
|
||||
gfx.setColor(eolMarkerColor);
|
||||
gfx.drawString(".",x,y);
|
||||
@ -625,7 +644,12 @@ implements TabExpander, Printable
|
||||
x = SyntaxUtilities.paintSyntaxLine(currentLine,
|
||||
currentLineTokens,
|
||||
styles, this, gfx, x, y);
|
||||
|
||||
/*
|
||||
* Draw characters via input method.
|
||||
*/
|
||||
if (compositionTextPainter != null && compositionTextPainter.hasComposedTextLayout()) {
|
||||
compositionTextPainter.draw(gfx, lineHighlightColor);
|
||||
}
|
||||
if (eolMarkers) {
|
||||
gfx.setColor(eolMarkerColor);
|
||||
gfx.drawString(".",x,y);
|
||||
|
187
app/src/processing/app/syntax/im/CompositionTextManager.java
Normal file
187
app/src/processing/app/syntax/im/CompositionTextManager.java
Normal file
@ -0,0 +1,187 @@
|
||||
package processing.app.syntax.im;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
||||
import javax.swing.text.BadLocationException;
|
||||
|
||||
import processing.app.syntax.JEditTextArea;
|
||||
import processing.app.syntax.TextAreaPainter;
|
||||
|
||||
/**
|
||||
* This class Manage texts from input method
|
||||
* by begin-process-end steps.
|
||||
*
|
||||
* First, if a user start inputing via input method,
|
||||
* beginCompositionText is called from InputMethodSupport.
|
||||
* Second, the user continues from input method, processCompositionText is called
|
||||
* and reflect user inputs to text area.
|
||||
* Finally the user try to commit text, endCompositionText is called.
|
||||
*
|
||||
* @author Takashi Maekawa (takachin@generative.info)
|
||||
*/
|
||||
|
||||
public class CompositionTextManager {
|
||||
private JEditTextArea textArea;
|
||||
private String prevComposeString;
|
||||
private int prevCommittedCount;
|
||||
private boolean isInputProcess;
|
||||
private int initialCaretPosition;
|
||||
public static final int COMPOSING_UNDERBAR_HEIGHT = 5;
|
||||
|
||||
/**
|
||||
* Create text manager class with a textarea.
|
||||
* @param textArea texarea component for PDE.
|
||||
*/
|
||||
public CompositionTextManager(JEditTextArea textArea) {
|
||||
this.textArea = textArea;
|
||||
prevComposeString = "";
|
||||
isInputProcess = false;
|
||||
prevCommittedCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this text manager is whether in input process or not.
|
||||
*/
|
||||
public boolean getIsInputProcess() {
|
||||
return isInputProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user begins input from input method.
|
||||
* This method initializes text manager.
|
||||
*
|
||||
* @param text Text from InputMethodEvent.
|
||||
* @param commited_count Numbers of committed characters in text.
|
||||
*/
|
||||
public void beginCompositionText(AttributedCharacterIterator text, int committed_count) {
|
||||
isInputProcess = true;
|
||||
prevComposeString = "";
|
||||
initialCaretPosition = textArea.getCaretPosition();
|
||||
processCompositionText(text, committed_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user processing input characters and
|
||||
* select candidates from input method.
|
||||
*
|
||||
* @param text Text from InputMethodEvent.
|
||||
* @param commited_count Numbers of committed characters in text.
|
||||
*/
|
||||
public void processCompositionText(AttributedCharacterIterator text, int committed_count) {
|
||||
int layoutCaretPosition = initialCaretPosition + committed_count;
|
||||
CompositionTextPainter compositionPainter = textArea.getPainter().getCompositionTextpainter();
|
||||
compositionPainter.setComposedTextLayout(getTextLayout(text, committed_count), layoutCaretPosition);
|
||||
int textLength = text.getEndIndex() - text.getBeginIndex() - committed_count;
|
||||
StringBuffer unCommitedStringBuf = new StringBuffer(textLength);
|
||||
char c;
|
||||
for (c = text.setIndex(committed_count); c != AttributedCharacterIterator.DONE
|
||||
&& textLength > 0; c = text.next(), --textLength) {
|
||||
unCommitedStringBuf.append(c);
|
||||
}
|
||||
String unCommittedString = unCommitedStringBuf.toString();
|
||||
try {
|
||||
if(canRemovePreviousInput(committed_count)){
|
||||
textArea.getDocument().remove(layoutCaretPosition, prevComposeString.length());
|
||||
}
|
||||
textArea.getDocument().insertString(layoutCaretPosition, unCommittedString, null);
|
||||
if(committed_count > 0){
|
||||
initialCaretPosition = initialCaretPosition + committed_count;
|
||||
}
|
||||
prevComposeString = unCommittedString;
|
||||
prevCommittedCount = committed_count;
|
||||
} catch (BadLocationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canRemovePreviousInput(int committed_count){
|
||||
return (prevCommittedCount == committed_count || prevCommittedCount > committed_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user fixed text from input method or delete all
|
||||
* composition text. This method resets CompositionTextPainter.
|
||||
*
|
||||
* @param text Text from InputMethodEvent.
|
||||
* @param commited_count Numbers of committed characters in text.
|
||||
*/
|
||||
public void endCompositionText(AttributedCharacterIterator text, int committed_count) {
|
||||
isInputProcess = false;
|
||||
/*
|
||||
* If there are no committed characters, remove it all from textarea.
|
||||
* This case will happen if a user delete all composing characters by backspace or delete key.
|
||||
* If it does, these previous characters are needed to be deleted.
|
||||
*/
|
||||
if(committed_count == 0){
|
||||
removeNotCommittedText(text);
|
||||
}
|
||||
CompositionTextPainter compositionPainter = textArea.getPainter().getCompositionTextpainter();
|
||||
compositionPainter.invalidateComposedTextLayout(initialCaretPosition + committed_count);
|
||||
prevComposeString = "";
|
||||
isInputProcess = false;
|
||||
}
|
||||
|
||||
private void removeNotCommittedText(AttributedCharacterIterator text){
|
||||
if (prevComposeString.length() == 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
textArea.getDocument().remove(initialCaretPosition, prevComposeString.length());
|
||||
} catch (BadLocationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private TextLayout getTextLayout(AttributedCharacterIterator text, int committed_count) {
|
||||
AttributedString composed = new AttributedString(text, committed_count, text.getEndIndex());
|
||||
Font font = textArea.getPainter().getFont();
|
||||
FontRenderContext context = ((Graphics2D) (textArea.getPainter().getGraphics())).getFontRenderContext();
|
||||
composed.addAttribute(TextAttribute.FONT, font);
|
||||
TextLayout layout = new TextLayout(composed.getIterator(), context);
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Point getCaretLocation() {
|
||||
Point loc = new Point();
|
||||
TextAreaPainter painter = textArea.getPainter();
|
||||
FontMetrics fm = painter.getFontMetrics();
|
||||
int offsetY = fm.getHeight() - COMPOSING_UNDERBAR_HEIGHT;
|
||||
int lineIndex = textArea.getCaretLine();
|
||||
loc.y = lineIndex * fm.getHeight() + offsetY;
|
||||
int offsetX = textArea.getCaretPosition()
|
||||
- textArea.getLineStartOffset(lineIndex);
|
||||
loc.x = textArea.offsetToX(lineIndex, offsetX);
|
||||
return loc;
|
||||
}
|
||||
|
||||
public Rectangle getTextLocation() {
|
||||
Point caret = getCaretLocation();
|
||||
return getCaretRectangle(caret.x, caret.y);
|
||||
}
|
||||
|
||||
private Rectangle getCaretRectangle(int x, int y) {
|
||||
TextAreaPainter painter = textArea.getPainter();
|
||||
Point origin = painter.getLocationOnScreen();
|
||||
int height = painter.getFontMetrics().getHeight();
|
||||
return new Rectangle(origin.x + x, origin.y + y, 0, height);
|
||||
}
|
||||
|
||||
public AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex) {
|
||||
int length = endIndex - beginIndex;
|
||||
String textAreaString = textArea.getText(beginIndex, length);
|
||||
return new AttributedString(textAreaString).getIterator();
|
||||
}
|
||||
|
||||
public int getInsertPositionOffset() {
|
||||
return textArea.getCaretPosition() * -1;
|
||||
}
|
||||
}
|
124
app/src/processing/app/syntax/im/CompositionTextPainter.java
Normal file
124
app/src/processing/app/syntax/im/CompositionTextPainter.java
Normal file
@ -0,0 +1,124 @@
|
||||
package processing.app.syntax.im;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.font.TextLayout;
|
||||
|
||||
import processing.app.syntax.JEditTextArea;
|
||||
import processing.app.syntax.TextAreaPainter;
|
||||
|
||||
/**
|
||||
* Paint texts from input method. Text via input method are transmitted by
|
||||
* AttributedCaharacterIterator. This class helps the PDE's TextAreaPainter
|
||||
* to handle AttributedCaharacterIterator.
|
||||
*
|
||||
* For practical purposes, paint to textarea is done by TextLayout class.
|
||||
* Because TextLayout class is easy to draw composing texts. (For example,
|
||||
* draw underline composing texts, focus when select from candidates text.)
|
||||
*
|
||||
* @author Takashi Maekawa (takachin@generative.info)
|
||||
*/
|
||||
public class CompositionTextPainter {
|
||||
private TextLayout composedTextLayout;
|
||||
private int composedBeginCaretPosition = 0;
|
||||
private JEditTextArea textArea;
|
||||
|
||||
/**
|
||||
* Constructor for painter.
|
||||
* @param textarea textarea used by PDE.
|
||||
*/
|
||||
public CompositionTextPainter(JEditTextArea textArea) {
|
||||
this.textArea = textArea;
|
||||
composedTextLayout = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the painter has TextLayout.
|
||||
* If a user input via InputMethod, this result will return true.
|
||||
* @param textarea textarea used by PDE.
|
||||
*/
|
||||
public boolean hasComposedTextLayout() {
|
||||
return (composedTextLayout != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TextLayout to the painter.
|
||||
* TextLayout will be created and set by CompositionTextManager.
|
||||
*
|
||||
* @see CompositionTextManager
|
||||
* @param textarea textarea used by PDE.
|
||||
*/
|
||||
public void setComposedTextLayout(TextLayout composedTextLayout, int composedStartCaretPosition) {
|
||||
this.composedTextLayout = composedTextLayout;
|
||||
this.composedBeginCaretPosition = composedStartCaretPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate this TextLayout to set null.
|
||||
* If a user end input via InputMethod, this method will called from CompositionTextManager.endCompositionText
|
||||
*/
|
||||
public void invalidateComposedTextLayout(int composedEndCaretPosition) {
|
||||
this.composedTextLayout = null;
|
||||
this.composedBeginCaretPosition = composedEndCaretPosition;
|
||||
//this.composedBeginCaretPosition = textArea.getCaretPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw text via input method with composed text information.
|
||||
* This method can draw texts with some underlines to illustrate converting characters.
|
||||
*
|
||||
* This method is workaround for TextAreaPainter.
|
||||
* Because, TextAreaPainter can't treat AttributedCharacterIterator directly.
|
||||
* AttributedCharacterIterator has very important information when composing text.
|
||||
* It has a map where are converted characters and committed characters.
|
||||
* Ideally, changing TextAreaPainter method can treat AttributedCharacterIterator is better. But it's very tough!!
|
||||
* So I choose to write some code as a workaround.
|
||||
*
|
||||
* This draw method is proceeded with the following steps.
|
||||
* 1. Original TextAreaPainter draws characters.
|
||||
* 2. This refillComposedArea method erase previous paint characters by textarea's background color.
|
||||
* The refill area is only square that width and height defined by characters with input method.
|
||||
* 3. CompositionTextPainter.draw method paints composed text. It was actually drawn by TextLayout.
|
||||
*
|
||||
* @param gfx set TextAreaPainter's Graphics object.
|
||||
* @param fillBackGroundColor set textarea's background.
|
||||
*/
|
||||
public void draw(Graphics gfx, Color fillBackGroundColor) {
|
||||
assert(composedTextLayout != null);
|
||||
Point composedLoc = getCaretLocation();
|
||||
refillComposedArea(fillBackGroundColor, composedLoc.x, composedLoc.y);
|
||||
composedTextLayout.draw((Graphics2D) gfx, composedLoc.x, composedLoc.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill color to erase characters drawn by original TextAreaPainter.
|
||||
*
|
||||
* @param fillColor fill color to erase characters drawn by original TextAreaPainter method.
|
||||
* @param x x-coordinate where to fill.
|
||||
* @param y y-coordinate where to fill.
|
||||
*/
|
||||
private void refillComposedArea(Color fillColor, int x, int y) {
|
||||
Graphics gfx = textArea.getPainter().getGraphics();
|
||||
gfx.setColor(fillColor);
|
||||
FontMetrics fm = textArea.getPainter().getFontMetrics();
|
||||
int newY = y - (fm.getHeight() - CompositionTextManager.COMPOSING_UNDERBAR_HEIGHT);
|
||||
int paintHeight = fm.getHeight();
|
||||
int paintWidth = (int) composedTextLayout.getBounds().getWidth();
|
||||
gfx.fillRect(x, newY, paintWidth, paintHeight);
|
||||
}
|
||||
|
||||
private Point getCaretLocation() {
|
||||
Point loc = new Point();
|
||||
TextAreaPainter painter = textArea.getPainter();
|
||||
FontMetrics fm = painter.getFontMetrics();
|
||||
int offsetY = fm.getHeight() - CompositionTextManager.COMPOSING_UNDERBAR_HEIGHT;
|
||||
int lineIndex = textArea.getCaretLine();
|
||||
loc.y = lineIndex * fm.getHeight() + offsetY;
|
||||
int offsetX = composedBeginCaretPosition - textArea.getLineStartOffset(lineIndex);
|
||||
loc.x = textArea.offsetToX(lineIndex, offsetX);
|
||||
return loc;
|
||||
}
|
||||
}
|
105
app/src/processing/app/syntax/im/InputMethodSupport.java
Normal file
105
app/src/processing/app/syntax/im/InputMethodSupport.java
Normal file
@ -0,0 +1,105 @@
|
||||
package processing.app.syntax.im;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.event.InputMethodListener;
|
||||
import java.awt.font.TextHitInfo;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
|
||||
import processing.app.syntax.JEditTextArea;
|
||||
|
||||
/**
|
||||
* Support in-line Japanese input for PDE. (Maybe Chinese, Korean and more)
|
||||
* This class is implemented by Java Input Method Framework and handles
|
||||
* If you would like to know more about Java Input Method Framework,
|
||||
* Please see http://java.sun.com/j2se/1.5.0/docs/guide/imf/
|
||||
*
|
||||
* This class is implemented to fix Bug #854.
|
||||
* http://dev.processing.org/bugs/show_bug.cgi?id=854
|
||||
*
|
||||
* @author Takashi Maekawa (takachin@generative.info)
|
||||
*/
|
||||
public class InputMethodSupport implements InputMethodRequests,
|
||||
InputMethodListener {
|
||||
|
||||
private int committed_count = 0;
|
||||
private CompositionTextManager textManager;
|
||||
|
||||
public InputMethodSupport(JEditTextArea textArea) {
|
||||
textManager = new CompositionTextManager(textArea);
|
||||
textArea.enableInputMethods(true);
|
||||
textArea.addInputMethodListener(this);
|
||||
}
|
||||
|
||||
public Rectangle getTextLocation(TextHitInfo offset) {
|
||||
return textManager.getTextLocation();
|
||||
}
|
||||
|
||||
public TextHitInfo getLocationOffset(int x, int y) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getInsertPositionOffset() {
|
||||
return textManager.getInsertPositionOffset();
|
||||
}
|
||||
|
||||
public AttributedCharacterIterator getCommittedText(int beginIndex,
|
||||
int endIndex, AttributedCharacterIterator.Attribute[] attributes) {
|
||||
return textManager.getCommittedText(beginIndex, endIndex);
|
||||
}
|
||||
|
||||
public int getCommittedTextLength() {
|
||||
return committed_count;
|
||||
}
|
||||
|
||||
public AttributedCharacterIterator cancelLatestCommittedText(
|
||||
AttributedCharacterIterator.Attribute[] attributes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttributedCharacterIterator getSelectedText(
|
||||
AttributedCharacterIterator.Attribute[] attributes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles events from InputMethod.
|
||||
* This method judges whether beginning of input or
|
||||
* progress of input or end and call related method.
|
||||
*
|
||||
* @param event event from Input Method.
|
||||
*/
|
||||
public void inputMethodTextChanged(InputMethodEvent event) {
|
||||
AttributedCharacterIterator text = event.getText();
|
||||
committed_count = event.getCommittedCharacterCount();
|
||||
if(isBeginInputProcess(text, textManager)){
|
||||
textManager.beginCompositionText(text, committed_count);
|
||||
caretPositionChanged(event);
|
||||
return;
|
||||
}
|
||||
if (isInputProcess(text)){
|
||||
textManager.processCompositionText(text, committed_count);
|
||||
caretPositionChanged(event);
|
||||
return;
|
||||
}
|
||||
textManager.endCompositionText(text, committed_count);
|
||||
caretPositionChanged(event);
|
||||
}
|
||||
|
||||
private boolean isBeginInputProcess(AttributedCharacterIterator text, CompositionTextManager textManager){
|
||||
if(text == null)
|
||||
return false;
|
||||
return (isInputProcess(text) && !textManager.getIsInputProcess());
|
||||
}
|
||||
|
||||
private boolean isInputProcess(AttributedCharacterIterator text){
|
||||
if(text == null)
|
||||
return false;
|
||||
return (text.getEndIndex() - (text.getBeginIndex() + committed_count) > 0);
|
||||
}
|
||||
|
||||
public void caretPositionChanged(InputMethodEvent event) {
|
||||
event.consume();
|
||||
}
|
||||
}
|
@ -120,6 +120,7 @@ public class ColorSelector implements Tool, DocumentListener {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
Base.setIcon(frame);
|
||||
|
||||
hueField.getDocument().addDocumentListener(this);
|
||||
@ -444,19 +445,25 @@ public class ColorSelector implements Tool, DocumentListener {
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
//System.out.println("getting pref " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
//System.out.println("getting min " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
//System.out.println("getting max " + WIDE + " " + HIGH);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -506,19 +513,25 @@ public class ColorSelector implements Tool, DocumentListener {
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
//System.out.println("s getting pref " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
//System.out.println("s getting min " + WIDE + " " + HIGH);
|
||||
return new Dimension(WIDE, HIGH);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
//System.out.println("s getting max " + WIDE + " " + HIGH);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -540,7 +553,7 @@ public class ColorSelector implements Tool, DocumentListener {
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
if (!allowHex) {
|
||||
return new Dimension(35, super.getPreferredSize().height);
|
||||
return new Dimension(45, super.getPreferredSize().height);
|
||||
}
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||
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
|
||||
@ -37,7 +37,7 @@ import javax.swing.event.*;
|
||||
|
||||
|
||||
/**
|
||||
* gui interface to font creation heaven/hell.
|
||||
* GUI tool for font creation heaven/hell.
|
||||
*/
|
||||
public class CreateFont extends JFrame implements Tool {
|
||||
Editor editor;
|
||||
@ -46,30 +46,22 @@ public class CreateFont extends JFrame implements Tool {
|
||||
Dimension windowSize;
|
||||
|
||||
JList fontSelector;
|
||||
//JComboBox styleSelector;
|
||||
JTextField sizeSelector;
|
||||
JCheckBox allBox;
|
||||
JButton charsetButton;
|
||||
JCheckBox smoothBox;
|
||||
JTextArea sample;
|
||||
JComponent sample;
|
||||
JButton okButton;
|
||||
JTextField filenameField;
|
||||
|
||||
Hashtable table;
|
||||
HashMap<String,Font> table;
|
||||
boolean smooth = true;
|
||||
boolean all = false;
|
||||
|
||||
Font font;
|
||||
|
||||
String[] list;
|
||||
int selection = -1;
|
||||
|
||||
|
||||
//static {
|
||||
//System.out.println("yep yep yep");
|
||||
//}
|
||||
//static final String styles[] = {
|
||||
//"Plain", "Bold", "Italic", "Bold Italic"
|
||||
//};
|
||||
CharacterSelector charSelector;
|
||||
|
||||
|
||||
public CreateFont() {
|
||||
@ -117,7 +109,7 @@ public class CreateFont extends JFrame implements Tool {
|
||||
Font fonts[] = ge.getAllFonts();
|
||||
|
||||
String flist[] = new String[fonts.length];
|
||||
table = new Hashtable();
|
||||
table = new HashMap<String,Font>();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < fonts.length; i++) {
|
||||
@ -150,20 +142,8 @@ public class CreateFont extends JFrame implements Tool {
|
||||
Dimension d1 = new Dimension(13, 13);
|
||||
pain.add(new Box.Filler(d1, d1, d1));
|
||||
|
||||
// see http://rinkworks.com/words/pangrams.shtml
|
||||
sample = new JTextArea("The quick brown fox blah blah.") {
|
||||
// Forsaking monastic tradition, twelve jovial friars gave up their
|
||||
// vocation for a questionable existence on the flying trapeze.
|
||||
public void paintComponent(Graphics g) {
|
||||
//System.out.println("disabling aa");
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
smooth ?
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_ON :
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
|
||||
super.paintComponent(g2);
|
||||
}
|
||||
};
|
||||
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));
|
||||
@ -193,14 +173,22 @@ public class CreateFont extends JFrame implements Tool {
|
||||
smoothBox.setSelected(smooth);
|
||||
panel.add(smoothBox);
|
||||
|
||||
allBox = new JCheckBox("All Characters");
|
||||
allBox.addActionListener(new ActionListener() {
|
||||
// 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) {
|
||||
all = allBox.isSelected();
|
||||
//showCharacterList();
|
||||
charSelector.setVisible(true);
|
||||
}
|
||||
});
|
||||
allBox.setSelected(all);
|
||||
panel.add(allBox);
|
||||
panel.add(charsetButton);
|
||||
|
||||
pain.add(panel);
|
||||
|
||||
@ -239,6 +227,7 @@ public class CreateFont extends JFrame implements Tool {
|
||||
Base.registerWindowCloseKeys(root, disposer);
|
||||
Base.setIcon(this);
|
||||
|
||||
setResizable(false);
|
||||
pack();
|
||||
|
||||
// do this after pack so it doesn't affect layout
|
||||
@ -251,6 +240,9 @@ public class CreateFont extends JFrame implements Tool {
|
||||
|
||||
setLocation((screen.width - windowSize.width) / 2,
|
||||
(screen.height - windowSize.height) / 2);
|
||||
|
||||
// create this behind the scenes
|
||||
charSelector = new CharacterSelector();
|
||||
}
|
||||
|
||||
|
||||
@ -259,26 +251,6 @@ public class CreateFont extends JFrame implements Tool {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void update() {
|
||||
int fontsize = 0;
|
||||
try {
|
||||
@ -313,7 +285,7 @@ public class CreateFont extends JFrame implements Tool {
|
||||
return;
|
||||
}
|
||||
|
||||
String filename = filenameField.getText();
|
||||
String filename = filenameField.getText().trim();
|
||||
if (filename.length() == 0) {
|
||||
JOptionPane.showMessageDialog(this, "Enter a file name for the font.",
|
||||
"Lameness", JOptionPane.WARNING_MESSAGE);
|
||||
@ -323,23 +295,519 @@ public class CreateFont extends JFrame implements Tool {
|
||||
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.DEFAULT_CHARSET);
|
||||
//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(this,
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2008 Ben Fry and Casey Reas
|
||||
Copyright (c) 2008-2009 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
|
||||
@ -25,6 +25,9 @@ package processing.app.windows;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Preferences;
|
||||
import processing.app.windows.Registry.REGISTRY_ROOT_KEY;
|
||||
@ -265,4 +268,38 @@ public class Platform extends processing.app.Platform {
|
||||
// not tested
|
||||
//Runtime.getRuntime().exec("start explorer \"" + folder + "\"");
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// Code partially thanks to Richard Quirk from:
|
||||
// http://quirkygba.blogspot.com/2009/11/setting-environment-variables-in-java.html
|
||||
|
||||
static WinLibC clib = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
|
||||
public interface WinLibC extends Library {
|
||||
//WinLibC INSTANCE = (WinLibC) Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
//libc = Native.loadLibrary("msvcrt", WinLibC.class);
|
||||
public int _putenv(String name);
|
||||
}
|
||||
|
||||
|
||||
public void setenv(String variable, String value) {
|
||||
//WinLibC clib = WinLibC.INSTANCE;
|
||||
clib._putenv(variable + "=" + value);
|
||||
}
|
||||
|
||||
|
||||
public String getenv(String variable) {
|
||||
return System.getenv(variable);
|
||||
}
|
||||
|
||||
|
||||
public int unsetenv(String variable) {
|
||||
//WinLibC clib = WinLibC.INSTANCE;
|
||||
//clib._putenv(variable + "=");
|
||||
//return 0;
|
||||
return clib._putenv(variable + "=");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user