mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-19 09:42:11 +03:00
Merging r327:r331 of the branches/processing-sync into the trunk. This adds the Processing core, and some new features including printing, copy for discourse, better auto-format, improved keyboard shortcuts, etc.
This commit is contained in:
533
app/Base.java
533
app/Base.java
@ -42,6 +42,7 @@ import javax.swing.undo.*;
|
|||||||
import com.apple.mrj.*;
|
import com.apple.mrj.*;
|
||||||
import com.ice.jni.registry.*;
|
import com.ice.jni.registry.*;
|
||||||
|
|
||||||
|
import processing.core.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,21 +53,8 @@ import com.ice.jni.registry.*;
|
|||||||
* files and images, etc) that comes from that.
|
* files and images, etc) that comes from that.
|
||||||
*/
|
*/
|
||||||
public class Base {
|
public class Base {
|
||||||
static final int VERSION = 3;
|
static final int VERSION = 10;
|
||||||
static final String VERSION_NAME = "0010 Alpha";
|
static final String VERSION_NAME = "0010 Alpha";
|
||||||
|
|
||||||
// platform IDs for PApplet.platform
|
|
||||||
|
|
||||||
static final int WINDOWS = 1;
|
|
||||||
static final int MACOS9 = 2;
|
|
||||||
static final int MACOSX = 3;
|
|
||||||
static final int LINUX = 4;
|
|
||||||
static final int OTHER = 0;
|
|
||||||
|
|
||||||
// used by split, all the standard whitespace chars
|
|
||||||
// (uncludes unicode nbsp, that little bostage)
|
|
||||||
|
|
||||||
static final String WHITESPACE = " \t\n\r\f\u00A0";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path of filename opened on the command line,
|
* Path of filename opened on the command line,
|
||||||
@ -76,79 +64,18 @@ public class Base {
|
|||||||
|
|
||||||
Editor editor;
|
Editor editor;
|
||||||
|
|
||||||
/**
|
|
||||||
* "1.3" or "1.1" or whatever (just the first three chars)
|
|
||||||
*/
|
|
||||||
public static final String javaVersionName =
|
|
||||||
System.getProperty("java.version").substring(0,3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version of Java that's in use, whether 1.1 or 1.3 or whatever,
|
|
||||||
* stored as a float.
|
|
||||||
* <P>
|
|
||||||
* Note that because this is stored as a float, the values may
|
|
||||||
* not be <EM>exactly</EM> 1.3 or 1.4. Instead, make sure you're
|
|
||||||
* comparing against 1.3f or 1.4f, which will have the same amount
|
|
||||||
* of error (i.e. 1.40000001). This could just be a double, but
|
|
||||||
* since Processing only uses floats, it's safer to do this,
|
|
||||||
* because there's no good way to specify a double with the preproc.
|
|
||||||
*/
|
|
||||||
public static final float javaVersion =
|
|
||||||
new Float(javaVersionName).floatValue();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current platform in use, one of the
|
|
||||||
* PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
|
|
||||||
*/
|
|
||||||
static public int platform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current platform in use.
|
|
||||||
* <P>
|
|
||||||
* Equivalent to System.getProperty("os.name"), just used internally.
|
|
||||||
*/
|
|
||||||
static public String platformName =
|
|
||||||
System.getProperty("os.name");
|
|
||||||
|
|
||||||
static {
|
|
||||||
// figure out which operating system
|
|
||||||
// this has to be first, since editor needs to know
|
|
||||||
|
|
||||||
if (platformName.toLowerCase().indexOf("mac") != -1) {
|
|
||||||
// can only check this property if running on a mac
|
|
||||||
// on a pc it throws a security exception and kills the applet
|
|
||||||
// (but on the mac it does just fine)
|
|
||||||
if (System.getProperty("mrj.version") != null) { // running on a mac
|
|
||||||
platform = (platformName.equals("Mac OS X")) ?
|
|
||||||
MACOSX : MACOS9;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
String osname = System.getProperty("os.name");
|
|
||||||
|
|
||||||
if (osname.indexOf("Windows") != -1) {
|
|
||||||
platform = WINDOWS;
|
|
||||||
|
|
||||||
} else if (osname.equals("Linux")) { // true for the ibm vm
|
|
||||||
platform = LINUX;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
platform = OTHER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void main(String args[]) {
|
static public void main(String args[]) {
|
||||||
|
|
||||||
// make sure that this is running on java 1.4
|
// make sure that this is running on java 1.4
|
||||||
|
|
||||||
//if (PApplet.javaVersion < 1.4f) {
|
if (PApplet.javaVersion < 1.4f) {
|
||||||
//System.err.println("no way man");
|
//System.err.println("no way man");
|
||||||
// Base.showError("Need to install Java 1.4",
|
Base.showError("Need to install Java 1.4",
|
||||||
// "This version of Arduino requires \n" +
|
"This version of Processing requires \n" +
|
||||||
// "Java 1.4 or later to run properly.\n" +
|
"Java 1.4 or later to run properly.\n" +
|
||||||
// "Please visit java.com to upgrade.", null);
|
"Please visit java.com to upgrade.", null);
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
// grab any opened file from the command line
|
// grab any opened file from the command line
|
||||||
@ -183,14 +110,34 @@ public class Base {
|
|||||||
// set the look and feel before opening the window
|
// set the look and feel before opening the window
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Base.isLinux()) {
|
if (Base.isMacOS()) {
|
||||||
// linux is by default (motif?) even uglier than metal
|
// Use the Quaqua L & F on OS X to make JFileChooser less awful
|
||||||
// actually, i'm using native menus, so they're ugly and
|
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
|
||||||
// motif-looking. ick. need to fix this.
|
// undo quaqua trying to fix the margins, since we've already
|
||||||
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
|
// hacked that in, bit by bit, over the years
|
||||||
|
UIManager.put("Component.visualMargin", new Insets(1, 1, 1, 1));
|
||||||
|
|
||||||
|
} else if (Base.isLinux()) {
|
||||||
|
// Linux is by default even uglier than metal (Motif?).
|
||||||
|
// Actually, i'm using native menus, so they're even uglier
|
||||||
|
// and Motif-looking (Lesstif?). Ick. Need to fix this.
|
||||||
|
//String lfname = UIManager.getCrossPlatformLookAndFeelClassName();
|
||||||
|
//UIManager.setLookAndFeel(lfname);
|
||||||
|
|
||||||
|
// For 0120, trying out the gtk+ look and feel as the default.
|
||||||
|
// This is available in Java 1.4.2 and later, and it can't possibly
|
||||||
|
// be any worse than Metal. (Ocean might also work, but that's for
|
||||||
|
// Java 1.5, and we aren't going there yet)
|
||||||
|
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
}
|
}
|
||||||
|
//} catch (ClassNotFoundException cnfe) {
|
||||||
|
// just default to the native look and feel for this platform
|
||||||
|
// i.e. appears that some linux systems don't have the gtk l&f
|
||||||
|
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -228,7 +175,7 @@ public class Base {
|
|||||||
* specifically a Mac OS X machine because it doesn't un on OS 9 anymore.
|
* specifically a Mac OS X machine because it doesn't un on OS 9 anymore.
|
||||||
*/
|
*/
|
||||||
static public boolean isMacOS() {
|
static public boolean isMacOS() {
|
||||||
return platform == MACOSX;
|
return PApplet.platform == PConstants.MACOSX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -236,7 +183,7 @@ public class Base {
|
|||||||
* returns true if running on windows.
|
* returns true if running on windows.
|
||||||
*/
|
*/
|
||||||
static public boolean isWindows() {
|
static public boolean isWindows() {
|
||||||
return platform == WINDOWS;
|
return PApplet.platform == PConstants.WINDOWS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -244,7 +191,7 @@ public class Base {
|
|||||||
* true if running on linux.
|
* true if running on linux.
|
||||||
*/
|
*/
|
||||||
static public boolean isLinux() {
|
static public boolean isLinux() {
|
||||||
return platform == LINUX;
|
return PApplet.platform == PConstants.LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -472,8 +419,9 @@ public class Base {
|
|||||||
sketchbookFolder = new File(documentsFolder, "Arduino");
|
sketchbookFolder = new File(documentsFolder, "Arduino");
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showError("sketch folder problem",
|
//showError("Could not find folder",
|
||||||
"Could not locate default sketch folder location.", e);
|
// "Could not locate the Documents folder.", e);
|
||||||
|
sketchbookFolder = promptSketchbookLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isWindows()) {
|
} else if (isWindows()) {
|
||||||
@ -502,11 +450,15 @@ public class Base {
|
|||||||
sketchbookFolder = new File(personalPath, "Arduino");
|
sketchbookFolder = new File(personalPath, "Arduino");
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showError("Problem getting documents folder",
|
//showError("Problem getting folder",
|
||||||
"Error getting the Arduino sketchbook folder.", e);
|
// "Could not locate the Documents folder.", e);
|
||||||
|
sketchbookFolder = promptSketchbookLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
sketchbookFolder = promptSketchbookLocation();
|
||||||
|
|
||||||
|
/*
|
||||||
// on linux (or elsewhere?) prompt the user for the location
|
// on linux (or elsewhere?) prompt the user for the location
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
fc.setDialogTitle("Select the folder where " +
|
fc.setDialogTitle("Select the folder where " +
|
||||||
@ -523,6 +475,7 @@ public class Base {
|
|||||||
} else {
|
} else {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the folder if it doesn't exist already
|
// create the folder if it doesn't exist already
|
||||||
@ -551,6 +504,68 @@ public class Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for a new sketchbook location.
|
||||||
|
*/
|
||||||
|
static protected File promptSketchbookLocation() {
|
||||||
|
File folder = null;
|
||||||
|
|
||||||
|
folder = new File(System.getProperty("user.home"), "sketchbook");
|
||||||
|
if (!folder.exists()) {
|
||||||
|
folder.mkdirs();
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
folder = Base.selectFolder("Select (or create new) folder for sketches...",
|
||||||
|
null, null);
|
||||||
|
if (folder == null) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation for choosing directories that handles both the
|
||||||
|
* Mac OS X hack to allow the native AWT file dialog, or uses
|
||||||
|
* the JFileChooser on other platforms. Mac AWT trick obtained from
|
||||||
|
* <A HREF="http://lists.apple.com/archives/java-dev/2003/Jul/msg00243.html">this post</A>
|
||||||
|
* on the OS X Java dev archive which explains the cryptic note in
|
||||||
|
* Apple's Java 1.4 release docs about the special System property.
|
||||||
|
*/
|
||||||
|
static public File selectFolder(String prompt, File folder, Frame frame) {
|
||||||
|
if (Base.isMacOS()) {
|
||||||
|
if (frame == null) frame = new Frame(); //.pack();
|
||||||
|
FileDialog fd = new FileDialog(frame, prompt, FileDialog.LOAD);
|
||||||
|
if (folder != null) {
|
||||||
|
fd.setDirectory(folder.getParent());
|
||||||
|
//fd.setFile(folder.getName());
|
||||||
|
}
|
||||||
|
System.setProperty("apple.awt.fileDialogForDirectories", "true");
|
||||||
|
fd.show();
|
||||||
|
System.setProperty("apple.awt.fileDialogForDirectories", "false");
|
||||||
|
if (fd.getFile() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new File(fd.getDirectory(), fd.getFile());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.setDialogTitle(prompt);
|
||||||
|
if (folder != null) {
|
||||||
|
fc.setSelectedFile(folder);
|
||||||
|
}
|
||||||
|
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
|
|
||||||
|
int returned = fc.showOpenDialog(new JDialog());
|
||||||
|
if (returned == JFileChooser.APPROVE_OPTION) {
|
||||||
|
return fc.getSelectedFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static public String cleanKey(String what) {
|
static public String cleanKey(String what) {
|
||||||
// jnireg seems to be reading the chars as bytes
|
// jnireg seems to be reading the chars as bytes
|
||||||
// so maybe be as simple as & 0xff and then running through decoder
|
// so maybe be as simple as & 0xff and then running through decoder
|
||||||
@ -631,20 +646,44 @@ public class Base {
|
|||||||
// .................................................................
|
// .................................................................
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the reference filename from the keywords list,
|
|
||||||
* builds a URL and passes it to openURL.
|
|
||||||
*/
|
|
||||||
static public void showReference(String referenceFile) {
|
static public void showReference(String referenceFile) {
|
||||||
String currentDir = System.getProperty("user.dir");
|
openURL(Base.getContents("reference" + File.separator + referenceFile));
|
||||||
openURL(currentDir + File.separator +
|
}
|
||||||
"reference" + File.separator +
|
|
||||||
referenceFile + ".html");
|
|
||||||
|
static public void showReference() {
|
||||||
|
showReference("index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public void showEnvironment() {
|
||||||
|
showReference("Guide_Environment.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public void showTroubleshooting() {
|
||||||
|
showReference("Guide_Troubleshooting.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the local copy of the FAQ that's included
|
||||||
|
* with the Processing download.
|
||||||
|
*/
|
||||||
|
static public void showFAQ() {
|
||||||
|
showReference("faq.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// .................................................................
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the cross-platform headache of opening URLs
|
* Implements the cross-platform headache of opening URLs
|
||||||
|
* TODO This code should be replaced by PApplet.link(),
|
||||||
|
* however that's not a static method (because it requires
|
||||||
|
* an AppletContext when used as an applet), so it's mildly
|
||||||
|
* trickier than just removing this method.
|
||||||
*/
|
*/
|
||||||
static public void openURL(String url) {
|
static public void openURL(String url) {
|
||||||
//System.out.println("opening url " + url);
|
//System.out.println("opening url " + url);
|
||||||
@ -707,11 +746,19 @@ public class Base {
|
|||||||
} else if (Base.isLinux()) {
|
} else if (Base.isLinux()) {
|
||||||
// how's mozilla sound to ya, laddie?
|
// how's mozilla sound to ya, laddie?
|
||||||
//Runtime.getRuntime().exec(new String[] { "mozilla", url });
|
//Runtime.getRuntime().exec(new String[] { "mozilla", url });
|
||||||
String browser = Preferences.get("browser");
|
//String browser = Preferences.get("browser");
|
||||||
Runtime.getRuntime().exec(new String[] { browser, url });
|
//Runtime.getRuntime().exec(new String[] { browser, url });
|
||||||
|
String launcher = Preferences.get("launcher.linux");
|
||||||
|
if (launcher != null) {
|
||||||
|
Runtime.getRuntime().exec(new String[] { launcher, url });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
System.err.println("unspecified platform");
|
String launcher = Preferences.get("launcher");
|
||||||
|
if (launcher != null) {
|
||||||
|
Runtime.getRuntime().exec(new String[] { launcher, url });
|
||||||
|
} else {
|
||||||
|
System.err.println("Unspecified platform, no launcher available.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -721,6 +768,36 @@ public class Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static boolean openFolderAvailable() {
|
||||||
|
if (Base.isWindows() || Base.isMacOS()) return true;
|
||||||
|
|
||||||
|
if (Base.isLinux()) {
|
||||||
|
// Assume that this is set to something valid
|
||||||
|
if (Preferences.get("launcher.linux") != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to use gnome-open
|
||||||
|
try {
|
||||||
|
Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
|
||||||
|
int result = p.waitFor();
|
||||||
|
// Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
|
||||||
|
Preferences.set("launcher.linux", "gnome-open");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) { }
|
||||||
|
|
||||||
|
// Attempt with kde-open
|
||||||
|
try {
|
||||||
|
Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
|
||||||
|
int result = p.waitFor();
|
||||||
|
Preferences.set("launcher.linux", "kde-open");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) { }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the other cross-platform headache of opening
|
* Implements the other cross-platform headache of opening
|
||||||
* a folder in the machine's native file browser.
|
* a folder in the machine's native file browser.
|
||||||
@ -742,6 +819,11 @@ public class Base {
|
|||||||
} else if (Base.isMacOS()) {
|
} else if (Base.isMacOS()) {
|
||||||
openURL(folder); // handles char replacement, etc
|
openURL(folder); // handles char replacement, etc
|
||||||
|
|
||||||
|
} else if (Base.isLinux()) {
|
||||||
|
String launcher = Preferences.get("launcher.linux");
|
||||||
|
if (launcher != null) {
|
||||||
|
Runtime.getRuntime().exec(new String[] { launcher, folder });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -780,7 +862,7 @@ public class Base {
|
|||||||
* for errors that allow P5 to continue running.
|
* for errors that allow P5 to continue running.
|
||||||
*/
|
*/
|
||||||
static public void showError(String title, String message,
|
static public void showError(String title, String message,
|
||||||
Exception e) {
|
Throwable e) {
|
||||||
if (title == null) title = "Error";
|
if (title == null) title = "Error";
|
||||||
JOptionPane.showMessageDialog(new Frame(), message, title,
|
JOptionPane.showMessageDialog(new Frame(), message, title,
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
@ -793,23 +875,29 @@ public class Base {
|
|||||||
// ...................................................................
|
// ...................................................................
|
||||||
|
|
||||||
|
|
||||||
|
static public String getContents(String what) {
|
||||||
|
String basePath = System.getProperty("user.dir");
|
||||||
|
/*
|
||||||
|
// do this later, when moving to .app package
|
||||||
|
if (PApplet.platform == PConstants.MACOSX) {
|
||||||
|
basePath = System.getProperty("processing.contents");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return basePath + File.separator + what;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public String getLibContents(String what) {
|
||||||
|
return getContents("lib" + File.separator + what);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static public Image getImage(String name, Component who) {
|
static public Image getImage(String name, Component who) {
|
||||||
Image image = null;
|
Image image = null;
|
||||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||||
|
|
||||||
//if ((Base.platform == Base.MACOSX) ||
|
image = tk.getImage(getLibContents(name));
|
||||||
//(Base.platform == Base.MACOS9)) {
|
MediaTracker tracker = new MediaTracker(who);
|
||||||
image = tk.getImage("lib/" + name);
|
|
||||||
//} else {
|
|
||||||
//image = tk.getImage(who.getClass().getResource(name));
|
|
||||||
//}
|
|
||||||
|
|
||||||
//image = tk.getImage("lib/" + name);
|
|
||||||
//URL url = PdeApplet.class.getResource(name);
|
|
||||||
//image = tk.getImage(url);
|
|
||||||
//}
|
|
||||||
//MediaTracker tracker = new MediaTracker(applet);
|
|
||||||
MediaTracker tracker = new MediaTracker(who); //frame);
|
|
||||||
tracker.addImage(image, 0);
|
tracker.addImage(image, 0);
|
||||||
try {
|
try {
|
||||||
tracker.waitForAll();
|
tracker.waitForAll();
|
||||||
@ -819,17 +907,7 @@ public class Base {
|
|||||||
|
|
||||||
|
|
||||||
static public InputStream getStream(String filename) throws IOException {
|
static public InputStream getStream(String filename) throws IOException {
|
||||||
//if (Base.platform == Base.MACOSX) {
|
return new FileInputStream(getLibContents(filename));
|
||||||
// macos doesn't seem to think that files in the lib folder
|
|
||||||
// are part of the resources, unlike windows or linux.
|
|
||||||
// actually, this is only the case when running as a .app,
|
|
||||||
// since it works fine from run.sh, but not Arduino.app
|
|
||||||
return new FileInputStream("lib/" + filename);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// all other, more reasonable operating systems
|
|
||||||
//return cls.getResource(filename).openStream();
|
|
||||||
//return Base.class.getResource(filename).openStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -965,7 +1043,7 @@ public class Base {
|
|||||||
if (!Preferences.getBoolean("compiler.save_build_files")) {
|
if (!Preferences.getBoolean("compiler.save_build_files")) {
|
||||||
if (!dead.delete()) {
|
if (!dead.delete()) {
|
||||||
// temporarily disabled
|
// temporarily disabled
|
||||||
//System.err.println("couldn't delete " + dead);
|
System.err.println("Could not delete " + dead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1040,197 +1118,4 @@ public class Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Equivalent to the one in PApplet, but static (die() is removed)
|
|
||||||
*/
|
|
||||||
static public String[] loadStrings(File file) {
|
|
||||||
try {
|
|
||||||
FileInputStream input = new FileInputStream(file);
|
|
||||||
BufferedReader reader =
|
|
||||||
new BufferedReader(new InputStreamReader(input));
|
|
||||||
|
|
||||||
String lines[] = new String[100];
|
|
||||||
int lineCount = 0;
|
|
||||||
String line = null;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
if (lineCount == lines.length) {
|
|
||||||
String temp[] = new String[lineCount << 1];
|
|
||||||
System.arraycopy(lines, 0, temp, 0, lineCount);
|
|
||||||
lines = temp;
|
|
||||||
}
|
|
||||||
lines[lineCount++] = line;
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
if (lineCount == lines.length) {
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resize array to appropraite amount for these lines
|
|
||||||
String output[] = new String[lineCount];
|
|
||||||
System.arraycopy(lines, 0, output, 0, lineCount);
|
|
||||||
return output;
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// STRINGS
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove whitespace characters from the beginning and ending
|
|
||||||
* of a String. Works like String.trim() but includes the
|
|
||||||
* unicode nbsp character as well.
|
|
||||||
*/
|
|
||||||
static public String trim(String str) {
|
|
||||||
return str.replace('\u00A0', ' ').trim();
|
|
||||||
|
|
||||||
/*
|
|
||||||
int left = 0;
|
|
||||||
int right = str.length() - 1;
|
|
||||||
|
|
||||||
while ((left <= right) &&
|
|
||||||
(WHITESPACE.indexOf(str.charAt(left)) != -1)) left++;
|
|
||||||
if (left == right) return "";
|
|
||||||
|
|
||||||
while (WHITESPACE.indexOf(str.charAt(right)) != -1) --right;
|
|
||||||
|
|
||||||
return str.substring(left, right-left+1);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join an array of Strings together as a single String,
|
|
||||||
* separated by the whatever's passed in for the separator.
|
|
||||||
*/
|
|
||||||
static public String join(String str[], char separator) {
|
|
||||||
return join(str, String.valueOf(separator));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join an array of Strings together as a single String,
|
|
||||||
* separated by the whatever's passed in for the separator.
|
|
||||||
* <P>
|
|
||||||
* To use this on numbers, first pass the array to nf() or nfs()
|
|
||||||
* to get a list of String objects, then use join on that.
|
|
||||||
* <PRE>
|
|
||||||
* e.g. String stuff[] = { "apple", "bear", "cat" };
|
|
||||||
* String list = join(stuff, ", ");
|
|
||||||
* // list is now "apple, bear, cat"</PRE>
|
|
||||||
*/
|
|
||||||
static public String join(String str[], String separator) {
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
for (int i = 0; i < str.length; i++) {
|
|
||||||
if (i != 0) buffer.append(separator);
|
|
||||||
buffer.append(str[i]);
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split the provided String at wherever whitespace occurs.
|
|
||||||
* Multiple whitespace (extra spaces or tabs or whatever)
|
|
||||||
* between items will count as a single break.
|
|
||||||
* <P>
|
|
||||||
* The whitespace characters are "\t\n\r\f", which are the defaults
|
|
||||||
* for java.util.StringTokenizer, plus the unicode non-breaking space
|
|
||||||
* character, which is found commonly on files created by or used
|
|
||||||
* in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
|
|
||||||
* <PRE>
|
|
||||||
* i.e. split("a b") -> { "a", "b" }
|
|
||||||
* split("a b") -> { "a", "b" }
|
|
||||||
* split("a\tb") -> { "a", "b" }
|
|
||||||
* split("a \t b ") -> { "a", "b" }</PRE>
|
|
||||||
*/
|
|
||||||
static public String[] split(String what) {
|
|
||||||
return split(what, WHITESPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a string into pieces, using any of the chars in the
|
|
||||||
* String 'delim' as separator characters. For instance,
|
|
||||||
* in addition to white space, you might want to treat commas
|
|
||||||
* as a separator. The delimeter characters won't appear in
|
|
||||||
* the returned String array.
|
|
||||||
* <PRE>
|
|
||||||
* i.e. split("a, b", " ,") -> { "a", "b" }
|
|
||||||
* </PRE>
|
|
||||||
* To include all the whitespace possibilities, use the variable
|
|
||||||
* WHITESPACE, found in PConstants:
|
|
||||||
* <PRE>
|
|
||||||
* i.e. split("a | b", WHITESPACE + "|"); -> { "a", "b" }</PRE>
|
|
||||||
*/
|
|
||||||
static public String[] split(String what, String delim) {
|
|
||||||
StringTokenizer toker = new StringTokenizer(what, delim);
|
|
||||||
String pieces[] = new String[toker.countTokens()];
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
while (toker.hasMoreTokens()) {
|
|
||||||
pieces[index++] = toker.nextToken();
|
|
||||||
}
|
|
||||||
return pieces;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split a string into pieces along a specific character.
|
|
||||||
* Most commonly used to break up a String along tab characters.
|
|
||||||
* <P>
|
|
||||||
* This operates differently than the others, where the
|
|
||||||
* single delimeter is the only breaking point, and consecutive
|
|
||||||
* delimeters will produce an empty string (""). This way,
|
|
||||||
* one can split on tab characters, but maintain the column
|
|
||||||
* alignments (of say an excel file) where there are empty columns.
|
|
||||||
*/
|
|
||||||
static public String[] split(String what, char delim) {
|
|
||||||
// do this so that the exception occurs inside the user's
|
|
||||||
// program, rather than appearing to be a bug inside split()
|
|
||||||
if (what == null) return null;
|
|
||||||
//return split(what, String.valueOf(delim)); // huh
|
|
||||||
|
|
||||||
char chars[] = what.toCharArray();
|
|
||||||
int splitCount = 0; //1;
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
if (chars[i] == delim) splitCount++;
|
|
||||||
}
|
|
||||||
// make sure that there is something in the input string
|
|
||||||
//if (chars.length > 0) {
|
|
||||||
// if the last char is a delimeter, get rid of it..
|
|
||||||
//if (chars[chars.length-1] == delim) splitCount--;
|
|
||||||
// on second thought, i don't agree with this, will disable
|
|
||||||
//}
|
|
||||||
if (splitCount == 0) {
|
|
||||||
String splits[] = new String[1];
|
|
||||||
splits[0] = new String(what);
|
|
||||||
return splits;
|
|
||||||
}
|
|
||||||
//int pieceCount = splitCount + 1;
|
|
||||||
String splits[] = new String[splitCount + 1];
|
|
||||||
int splitIndex = 0;
|
|
||||||
int startIndex = 0;
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
if (chars[i] == delim) {
|
|
||||||
splits[splitIndex++] =
|
|
||||||
new String(chars, startIndex, i-startIndex);
|
|
||||||
startIndex = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//if (startIndex != chars.length) {
|
|
||||||
splits[splitIndex] =
|
|
||||||
new String(chars, startIndex, chars.length-startIndex);
|
|
||||||
//}
|
|
||||||
return splits;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
415
app/Editor.java
415
app/Editor.java
@ -28,11 +28,13 @@ package processing.app;
|
|||||||
|
|
||||||
import processing.app.syntax.*;
|
import processing.app.syntax.*;
|
||||||
import processing.app.tools.*;
|
import processing.app.tools.*;
|
||||||
|
import processing.core.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.datatransfer.*;
|
import java.awt.datatransfer.*;
|
||||||
import java.awt.dnd.*;
|
import java.awt.dnd.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
import java.awt.print.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
@ -45,7 +47,9 @@ import javax.swing.event.*;
|
|||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
import javax.swing.undo.*;
|
import javax.swing.undo.*;
|
||||||
|
|
||||||
|
import com.apple.mrj.*;
|
||||||
import com.oroinc.text.regex.*;
|
import com.oroinc.text.regex.*;
|
||||||
|
//import de.hunsicker.jalopy.*;
|
||||||
|
|
||||||
import com.apple.mrj.*;
|
import com.apple.mrj.*;
|
||||||
import gnu.io.*;
|
import gnu.io.*;
|
||||||
@ -78,6 +82,9 @@ public class Editor extends JFrame
|
|||||||
boolean handleNewShift;
|
boolean handleNewShift;
|
||||||
boolean handleNewLibrary;
|
boolean handleNewLibrary;
|
||||||
|
|
||||||
|
PageFormat pageFormat;
|
||||||
|
PrinterJob printerJob;
|
||||||
|
|
||||||
EditorButtons buttons;
|
EditorButtons buttons;
|
||||||
EditorHeader header;
|
EditorHeader header;
|
||||||
EditorStatus status;
|
EditorStatus status;
|
||||||
@ -133,14 +140,12 @@ public class Editor extends JFrame
|
|||||||
// used internally, and only briefly
|
// used internally, and only briefly
|
||||||
CompoundEdit compoundEdit;
|
CompoundEdit compoundEdit;
|
||||||
|
|
||||||
//static public UndoManager undo = new UndoManager(); // editor needs this guy
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
//SketchHistory history; // TODO re-enable history
|
//SketchHistory history; // TODO re-enable history
|
||||||
Sketchbook sketchbook;
|
Sketchbook sketchbook;
|
||||||
//Preferences preferences;
|
//Preferences preferences;
|
||||||
//FindReplace find;
|
FindReplace find;
|
||||||
|
|
||||||
//static Properties keywords; // keyword -> reference html lookup
|
//static Properties keywords; // keyword -> reference html lookup
|
||||||
|
|
||||||
@ -167,9 +172,13 @@ public class Editor extends JFrame
|
|||||||
// add listener to handle window close box hit event
|
// add listener to handle window close box hit event
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
handleQuit();
|
handleQuitInternal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// don't close the window when clicked, the app will take care
|
||||||
|
// of that via the handleQuitInternal() methods
|
||||||
|
// http://dev.processing.org/bugs/show_bug.cgi?id=440
|
||||||
|
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||||
|
|
||||||
PdeKeywords keywords = new PdeKeywords();
|
PdeKeywords keywords = new PdeKeywords();
|
||||||
sketchbook = new Sketchbook(this);
|
sketchbook = new Sketchbook(this);
|
||||||
@ -188,8 +197,14 @@ public class Editor extends JFrame
|
|||||||
// doesn't matter when this is created, just make it happen at some point
|
// doesn't matter when this is created, just make it happen at some point
|
||||||
//find = new FindReplace(Editor.this);
|
//find = new FindReplace(Editor.this);
|
||||||
|
|
||||||
Container pain = getContentPane();
|
//Container pain = getContentPane();
|
||||||
|
//pain.setLayout(new BorderLayout());
|
||||||
|
// for rev 0120, placing things inside a JPanel because
|
||||||
|
Container contentPain = getContentPane();
|
||||||
|
contentPain.setLayout(new BorderLayout());
|
||||||
|
JPanel pain = new JPanel();
|
||||||
pain.setLayout(new BorderLayout());
|
pain.setLayout(new BorderLayout());
|
||||||
|
contentPain.add(pain, BorderLayout.CENTER);
|
||||||
|
|
||||||
Box box = Box.createVerticalBox();
|
Box box = Box.createVerticalBox();
|
||||||
Box upper = Box.createVerticalBox();
|
Box upper = Box.createVerticalBox();
|
||||||
@ -251,6 +266,17 @@ public class Editor extends JFrame
|
|||||||
listener = new EditorListener(this, textarea);
|
listener = new EditorListener(this, textarea);
|
||||||
pain.add(box);
|
pain.add(box);
|
||||||
|
|
||||||
|
pain.setTransferHandler(new TransferHandler() {
|
||||||
|
|
||||||
|
public boolean canImport(JComponent dest, DataFlavor[] flavors) {
|
||||||
|
// claim that we can import everything
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean importData(JComponent src, Transferable transferable) {
|
||||||
|
DataFlavor[] flavors = transferable.getTransferDataFlavors();
|
||||||
|
|
||||||
|
/*
|
||||||
DropTarget dt = new DropTarget(this, new DropTargetListener() {
|
DropTarget dt = new DropTarget(this, new DropTargetListener() {
|
||||||
|
|
||||||
public void dragEnter(DropTargetDragEvent event) {
|
public void dragEnter(DropTargetDragEvent event) {
|
||||||
@ -278,14 +304,17 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
Transferable transferable = event.getTransferable();
|
Transferable transferable = event.getTransferable();
|
||||||
DataFlavor flavors[] = transferable.getTransferDataFlavors();
|
DataFlavor flavors[] = transferable.getTransferDataFlavors();
|
||||||
|
*/
|
||||||
int successful = 0;
|
int successful = 0;
|
||||||
|
|
||||||
for (int i = 0; i < flavors.length; i++) {
|
for (int i = 0; i < flavors.length; i++) {
|
||||||
try {
|
try {
|
||||||
//System.out.println(flavors[i]);
|
//System.out.println(flavors[i]);
|
||||||
//System.out.println(transferable.getTransferData(flavors[i]));
|
//System.out.println(transferable.getTransferData(flavors[i]));
|
||||||
java.util.List list =
|
Object stuff = transferable.getTransferData(flavors[i]);
|
||||||
(java.util.List) transferable.getTransferData(flavors[i]);
|
if (!(stuff instanceof java.util.List)) continue;
|
||||||
|
java.util.List list = (java.util.List) stuff;
|
||||||
|
|
||||||
for (int j = 0; j < list.size(); j++) {
|
for (int j = 0; j < list.size(); j++) {
|
||||||
Object item = list.get(j);
|
Object item = list.get(j);
|
||||||
if (item instanceof File) {
|
if (item instanceof File) {
|
||||||
@ -298,7 +327,7 @@ public class Editor extends JFrame
|
|||||||
File parent = file.getParentFile();
|
File parent = file.getParentFile();
|
||||||
if (name.equals(parent.getName())) {
|
if (name.equals(parent.getName())) {
|
||||||
handleOpenFile(file);
|
handleOpenFile(file);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +339,7 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,6 +352,7 @@ public class Editor extends JFrame
|
|||||||
} else {
|
} else {
|
||||||
message(successful + " files added to the sketch.");
|
message(successful + " files added to the sketch.");
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -488,7 +519,9 @@ public class Editor extends JFrame
|
|||||||
listener.applyPreferences();
|
listener.applyPreferences();
|
||||||
|
|
||||||
// in case moved to a new location
|
// in case moved to a new location
|
||||||
sketchbook.rebuildMenus();
|
// For 0125, changing to async version (to be implemented later)
|
||||||
|
//sketchbook.rebuildMenus();
|
||||||
|
sketchbook.rebuildMenusAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -576,11 +609,19 @@ public class Editor extends JFrame
|
|||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
item = newJMenuItem("Page Setup", 'P', true);
|
item = newJMenuItem("Page Setup", 'P', true);
|
||||||
item.setEnabled(false);
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handlePageSetup();
|
||||||
|
}
|
||||||
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
item = newJMenuItem("Print", 'P');
|
item = newJMenuItem("Print", 'P');
|
||||||
item.setEnabled(false);
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handlePrint();
|
||||||
|
}
|
||||||
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
// macosx already has its own preferences and quit menu
|
// macosx already has its own preferences and quit menu
|
||||||
@ -600,7 +641,7 @@ public class Editor extends JFrame
|
|||||||
item = newJMenuItem("Quit", 'Q');
|
item = newJMenuItem("Quit", 'Q');
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleQuit();
|
handleQuitInternal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
@ -639,17 +680,9 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
item = new JMenuItem("Add File...");
|
|
||||||
item.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
sketch.addFile();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(item);
|
|
||||||
|
|
||||||
menu.add(sketchbook.getImportMenu());
|
menu.add(sketchbook.getImportMenu());
|
||||||
|
|
||||||
if (Base.isWindows() || Base.isMacOS()) {
|
//if (Base.isWindows() || Base.isMacOS()) {
|
||||||
// no way to do an 'open in file browser' on other platforms
|
// no way to do an 'open in file browser' on other platforms
|
||||||
// since there isn't any sort of standard
|
// since there isn't any sort of standard
|
||||||
item = newJMenuItem("Show Sketch Folder", 'K', false);
|
item = newJMenuItem("Show Sketch Folder", 'K', false);
|
||||||
@ -660,8 +693,20 @@ public class Editor extends JFrame
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
if (!Base.openFolderAvailable()) {
|
||||||
|
item.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//menu.addSeparator();
|
||||||
|
|
||||||
|
item = new JMenuItem("Add File...");
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
sketch.addFile();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
// TODO re-enable history
|
// TODO re-enable history
|
||||||
//history.attachMenu(menu);
|
//history.attachMenu(menu);
|
||||||
return menu;
|
return menu;
|
||||||
@ -681,20 +726,39 @@ public class Editor extends JFrame
|
|||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
synchronized public void actionPerformed(ActionEvent e) {
|
synchronized public void actionPerformed(ActionEvent e) {
|
||||||
new AutoFormat(Editor.this).show();
|
new AutoFormat(Editor.this).show();
|
||||||
//handleBeautify();
|
|
||||||
|
/*
|
||||||
|
Jalopy jalopy = new Jalopy();
|
||||||
|
jalopy.setInput(getText(), sketch.current.file.getAbsolutePath());
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
jalopy.setOutput(buffer);
|
||||||
|
jalopy.setInspect(false);
|
||||||
|
jalopy.format();
|
||||||
|
setText(buffer.toString(), 0, 0);
|
||||||
|
|
||||||
|
if (jalopy.getState() == Jalopy.State.OK)
|
||||||
|
System.out.println("successfully formatted");
|
||||||
|
else if (jalopy.getState() == Jalopy.State.WARN)
|
||||||
|
System.out.println(" formatted with warnings");
|
||||||
|
else if (jalopy.getState() == Jalopy.State.ERROR)
|
||||||
|
System.out.println(" could not be formatted");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
/*item = new JMenuItem("Create Font...");
|
item = new JMenuItem("Copy for Discourse");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
//new CreateFont().show(sketch.dataFolder);
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
new CreateFont(Editor.this).show();
|
public void run() {
|
||||||
|
new DiscourseFormat(Editor.this).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
*/
|
|
||||||
item = new JMenuItem("Archive Sketch");
|
item = new JMenuItem("Archive Sketch");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -706,13 +770,17 @@ public class Editor extends JFrame
|
|||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
|
/*
|
||||||
item = new JMenuItem("Export Folder...");
|
item = new JMenuItem("Export Folder...");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
new ExportFolder(Editor.this).show();
|
new ExportFolder(Editor.this).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
*/
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
mcuMenu = new JMenu("Microcontroller (MCU)");
|
mcuMenu = new JMenu("Microcontroller (MCU)");
|
||||||
@ -946,21 +1014,18 @@ public class Editor extends JFrame
|
|||||||
menu.add(item);
|
menu.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
item = new JMenuItem("Troubleshooting");
|
item = new JMenuItem("Environment");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
Base.showEnvironment();
|
||||||
"reference" + File.separator +
|
|
||||||
"Guide_Troubleshooting.html");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem("Environment");
|
item = new JMenuItem("Troubleshooting");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
Base.showTroubleshooting();
|
||||||
"reference" + File.separator + "Guide_Environment.html");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
@ -968,8 +1033,17 @@ public class Editor extends JFrame
|
|||||||
item = new JMenuItem("Reference");
|
item = new JMenuItem("Reference");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
Base.showReference();
|
||||||
"reference" + File.separator + "index.html");
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
item = newJMenuItem("Find in Reference", 'F', true);
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (textarea.isSelectionActive()) {
|
||||||
|
handleReference();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
@ -977,33 +1051,11 @@ public class Editor extends JFrame
|
|||||||
item = new JMenuItem("Frequently Asked Questions");
|
item = new JMenuItem("Frequently Asked Questions");
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
Base.showFAQ();
|
||||||
"reference" + File.separator + "FAQ.html");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
// item = newJMenuItem("Find in Reference", 'F', true);
|
|
||||||
// item.addActionListener(new ActionListener() {
|
|
||||||
// public void actionPerformed(ActionEvent e) {
|
|
||||||
// if (textarea.isSelectionActive()) {
|
|
||||||
// String text = textarea.getSelectedText();
|
|
||||||
// if (text.length() == 0) {
|
|
||||||
// message("First select a word to find in the reference.");
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// String referenceFile = PdeKeywords.getReference(text);
|
|
||||||
// if (referenceFile == null) {
|
|
||||||
// message("No reference available for \"" + text + "\"");
|
|
||||||
// } else {
|
|
||||||
// Base.showReference(referenceFile);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// menu.add(item);
|
|
||||||
|
|
||||||
item = newJMenuItem("Visit www.arduino.cc", '5');
|
item = newJMenuItem("Visit www.arduino.cc", '5');
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -1083,22 +1135,27 @@ public class Editor extends JFrame
|
|||||||
item = newJMenuItem("Find...", 'F');
|
item = newJMenuItem("Find...", 'F');
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
new FindReplace(Editor.this).show();
|
if (find == null) {
|
||||||
//find.show();
|
find = new FindReplace(Editor.this);
|
||||||
|
}
|
||||||
|
//new FindReplace(Editor.this).show();
|
||||||
|
find.show();
|
||||||
//find.setVisible(true);
|
//find.setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
|
// TODO find next should only be enabled after a
|
||||||
|
// search has actually taken place
|
||||||
item = newJMenuItem("Find Next", 'G');
|
item = newJMenuItem("Find Next", 'G');
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// TODO find next should only be enabled after a
|
if (find != null) {
|
||||||
// search has actually taken place
|
|
||||||
//find.find(true);
|
//find.find(true);
|
||||||
FindReplace find = new FindReplace(Editor.this); //.show();
|
//FindReplace find = new FindReplace(Editor.this); //.show();
|
||||||
find.find(true);
|
find.find(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
|
|
||||||
@ -1116,9 +1173,9 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A software engineer, somewhere, needs to have his abstraction
|
* A software engineer, somewhere, needs to have his abstraction
|
||||||
* taken away. In some countries they jail people for writing the
|
* taken away. In some countries they jail or beat people for writing
|
||||||
* sort of crappy api that would require a four line helper function
|
* the sort of API that would require a five line helper function
|
||||||
* to set the command key for a menu item.
|
* just to set the command key for a menu item.
|
||||||
*/
|
*/
|
||||||
static public JMenuItem newJMenuItem(String title,
|
static public JMenuItem newJMenuItem(String title,
|
||||||
int what, boolean shift) {
|
int what, boolean shift) {
|
||||||
@ -1191,7 +1248,6 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
protected void updateRedoState() {
|
protected void updateRedoState() {
|
||||||
if (undo.canRedo()) {
|
if (undo.canRedo()) {
|
||||||
//this.setEnabled(true);
|
|
||||||
redoItem.setEnabled(true);
|
redoItem.setEnabled(true);
|
||||||
redoItem.setText(undo.getRedoPresentationName());
|
redoItem.setText(undo.getRedoPresentationName());
|
||||||
putValue(Action.NAME, undo.getRedoPresentationName());
|
putValue(Action.NAME, undo.getRedoPresentationName());
|
||||||
@ -1339,10 +1395,12 @@ public class Editor extends JFrame
|
|||||||
redoAction.updateRedoState();
|
redoAction.updateRedoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void beginCompoundEdit() {
|
public void beginCompoundEdit() {
|
||||||
compoundEdit = new CompoundEdit();
|
compoundEdit = new CompoundEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void endCompoundEdit() {
|
public void endCompoundEdit() {
|
||||||
compoundEdit.end();
|
compoundEdit.end();
|
||||||
undo.addEdit(compoundEdit);
|
undo.addEdit(compoundEdit);
|
||||||
@ -1352,6 +1410,8 @@ public class Editor extends JFrame
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ...................................................................
|
||||||
|
|
||||||
|
|
||||||
public void handleRun(final boolean present) {
|
public void handleRun(final boolean present) {
|
||||||
doClose();
|
doClose();
|
||||||
@ -1576,42 +1636,71 @@ public class Editor extends JFrame
|
|||||||
String prompt = "Save changes to " + sketch.name + "? ";
|
String prompt = "Save changes to " + sketch.name + "? ";
|
||||||
|
|
||||||
if (checkModifiedMode != HANDLE_QUIT) {
|
if (checkModifiedMode != HANDLE_QUIT) {
|
||||||
// if the user is not quitting, then use the nicer
|
// if the user is not quitting, then use simpler nicer
|
||||||
// dialog that's actually inside the p5 window.
|
// dialog that's actually inside the p5 window.
|
||||||
status.prompt(prompt);
|
status.prompt(prompt);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if the user selected quit, then this has to be done with
|
if (!Base.isMacOS() || PApplet.javaVersion < 1.5f) {
|
||||||
// a JOptionPane instead of internally in the editor.
|
int result =
|
||||||
// TODO this is actually just a bug to be fixed.
|
JOptionPane.showConfirmDialog(this, prompt, "Quit",
|
||||||
|
JOptionPane.YES_NO_CANCEL_OPTION,
|
||||||
// macosx java kills the app even though cancel might get hit
|
JOptionPane.QUESTION_MESSAGE);
|
||||||
// so the cancel button is (temporarily) left off
|
|
||||||
// this may be treated differently in macosx java 1.4,
|
|
||||||
// but 1.4 isn't currently stable enough to use.
|
|
||||||
|
|
||||||
// turns out windows has the same problem (sometimes)
|
|
||||||
// disable cancel for now until a fix can be found.
|
|
||||||
|
|
||||||
Object[] options = { "Yes", "No" };
|
|
||||||
int result = JOptionPane.showOptionDialog(this,
|
|
||||||
prompt,
|
|
||||||
"Quit",
|
|
||||||
JOptionPane.YES_NO_OPTION,
|
|
||||||
JOptionPane.QUESTION_MESSAGE,
|
|
||||||
null,
|
|
||||||
options,
|
|
||||||
options[0]);
|
|
||||||
|
|
||||||
if (result == JOptionPane.YES_OPTION) {
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
handleSave(true);
|
handleSave(true);
|
||||||
checkModified2();
|
checkModified2();
|
||||||
|
|
||||||
} else if (result == JOptionPane.NO_OPTION) {
|
} else if (result == JOptionPane.NO_OPTION) {
|
||||||
checkModified2(); // though this may just quit
|
checkModified2();
|
||||||
|
}
|
||||||
|
// cancel is ignored altogether
|
||||||
|
|
||||||
} else if (result == JOptionPane.CANCEL_OPTION) {
|
} else {
|
||||||
// ignored
|
// This code is disabled unless Java 1.5 is being used on Mac OS X
|
||||||
|
// because of a Java bug that prevents the initial value of the
|
||||||
|
// dialog from being set properly (at least on my MacBook Pro).
|
||||||
|
// The bug causes the "Don't Save" option to be the highlighted,
|
||||||
|
// blinking, default. This sucks. But I'll tell you what doesn't
|
||||||
|
// suck--workarounds for the Mac and Apple's snobby attitude about it!
|
||||||
|
|
||||||
|
// 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(this, null);
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
Object result = pane.getValue();
|
||||||
|
if (result == options[0]) { // save (and quit)
|
||||||
|
handleSave(true);
|
||||||
|
checkModified2();
|
||||||
|
|
||||||
|
} else if (result == options[2]) { // don't save (still quit)
|
||||||
|
checkModified2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1739,9 +1828,15 @@ public class Editor extends JFrame
|
|||||||
* Open a sketch from a particular path, but don't check to save changes.
|
* Open a sketch from a particular path, but don't check to save changes.
|
||||||
* Used by Sketch.saveAs() to re-open a sketch after the "Save As"
|
* Used by Sketch.saveAs() to re-open a sketch after the "Save As"
|
||||||
*/
|
*/
|
||||||
public void handleOpenUnchecked(String path) {
|
public void handleOpenUnchecked(String path, int codeIndex,
|
||||||
|
int selStart, int selStop, int scrollPos) {
|
||||||
doClose();
|
doClose();
|
||||||
handleOpen2(path);
|
handleOpen2(path);
|
||||||
|
|
||||||
|
sketch.setCurrent(codeIndex);
|
||||||
|
textarea.select(selStart, selStop);
|
||||||
|
//textarea.updateScrollBars();
|
||||||
|
textarea.setScrollPosition(scrollPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1761,7 +1856,8 @@ public class Editor extends JFrame
|
|||||||
if (!oldPath.equals(newPath)) {
|
if (!oldPath.equals(newPath)) {
|
||||||
if (Base.calcFolderSize(sketch.folder) == 0) {
|
if (Base.calcFolderSize(sketch.folder) == 0) {
|
||||||
Base.removeDir(sketch.folder);
|
Base.removeDir(sketch.folder);
|
||||||
sketchbook.rebuildMenus();
|
//sketchbook.rebuildMenus();
|
||||||
|
sketchbook.rebuildMenusAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) { } // oh well
|
} catch (Exception e) { } // oh well
|
||||||
@ -1893,7 +1989,11 @@ public class Editor extends JFrame
|
|||||||
message(EMPTY);
|
message(EMPTY);
|
||||||
}
|
}
|
||||||
// rebuild sketch menu in case a save-as was forced
|
// rebuild sketch menu in case a save-as was forced
|
||||||
sketchbook.rebuildMenus();
|
// Disabling this for 0125, instead rebuild the menu inside
|
||||||
|
// the Save As method of the Sketch object, since that's the
|
||||||
|
// only one who knows whether something was renamed.
|
||||||
|
//sketchbook.rebuildMenus();
|
||||||
|
//sketchbook.rebuildMenusAsync();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// show the error as a message in the window
|
// show the error as a message in the window
|
||||||
@ -1918,7 +2018,10 @@ public class Editor extends JFrame
|
|||||||
try {
|
try {
|
||||||
if (sketch.saveAs()) {
|
if (sketch.saveAs()) {
|
||||||
message("Done Saving.");
|
message("Done Saving.");
|
||||||
sketchbook.rebuildMenus();
|
// Disabling this for 0125, instead rebuild the menu inside
|
||||||
|
// the Save As method of the Sketch object, since that's the
|
||||||
|
// only one who knows whether something was renamed.
|
||||||
|
//sketchbook.rebuildMenusAsync();
|
||||||
} else {
|
} else {
|
||||||
message("Save Cancelled.");
|
message("Save Cancelled.");
|
||||||
}
|
}
|
||||||
@ -2007,6 +2110,7 @@ public class Editor extends JFrame
|
|||||||
null,
|
null,
|
||||||
options,
|
options,
|
||||||
options[0]);
|
options[0]);
|
||||||
|
|
||||||
if (result == JOptionPane.OK_OPTION) {
|
if (result == JOptionPane.OK_OPTION) {
|
||||||
handleSave(true);
|
handleSave(true);
|
||||||
|
|
||||||
@ -2021,13 +2125,57 @@ public class Editor extends JFrame
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handlePageSetup() {
|
||||||
|
//printerJob = null;
|
||||||
|
if (printerJob == null) {
|
||||||
|
printerJob = PrinterJob.getPrinterJob();
|
||||||
|
}
|
||||||
|
if (pageFormat == null) {
|
||||||
|
pageFormat = printerJob.defaultPage();
|
||||||
|
}
|
||||||
|
pageFormat = printerJob.pageDialog(pageFormat);
|
||||||
|
//System.out.println("page format is " + pageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handlePrint() {
|
||||||
|
message("Printing...");
|
||||||
|
//printerJob = null;
|
||||||
|
if (printerJob == null) {
|
||||||
|
printerJob = PrinterJob.getPrinterJob();
|
||||||
|
}
|
||||||
|
if (pageFormat != null) {
|
||||||
|
//System.out.println("setting page format " + pageFormat);
|
||||||
|
printerJob.setPrintable(textarea.getPainter(), pageFormat);
|
||||||
|
} else {
|
||||||
|
printerJob.setPrintable(textarea.getPainter());
|
||||||
|
}
|
||||||
|
// set the name of the job to the code name
|
||||||
|
printerJob.setJobName(sketch.current.name);
|
||||||
|
|
||||||
|
if (printerJob.printDialog()) {
|
||||||
|
try {
|
||||||
|
printerJob.print();
|
||||||
|
message("Done printing.");
|
||||||
|
|
||||||
|
} catch (PrinterException pe) {
|
||||||
|
error("Error while printing.");
|
||||||
|
pe.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message("Printing canceled.");
|
||||||
|
}
|
||||||
|
//printerJob = null; // clear this out?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quit, but first ask user if it's ok. Also store preferences
|
* Quit, but first ask user if it's ok. Also store preferences
|
||||||
* to disk just in case they want to quit. Final exit() happens
|
* to disk just in case they want to quit. Final exit() happens
|
||||||
* in Editor since it has the callback from EditorStatus.
|
* in Editor since it has the callback from EditorStatus.
|
||||||
*/
|
*/
|
||||||
public void handleQuit() {
|
public void handleQuitInternal() {
|
||||||
// doStop() isn't sufficient with external vm & quit
|
// doStop() isn't sufficient with external vm & quit
|
||||||
// instead use doClose() which will kill the external vm
|
// instead use doClose() which will kill the external vm
|
||||||
doClose();
|
doClose();
|
||||||
@ -2036,6 +2184,27 @@ public class Editor extends JFrame
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for the MRJQuitHandler, needs to be dealt with differently
|
||||||
|
* than the regular handler because OS X has an annoying implementation
|
||||||
|
* <A HREF="http://developer.apple.com/qa/qa2001/qa1187.html">quirk</A>
|
||||||
|
* that requires an exception to be thrown in order to properly cancel
|
||||||
|
* a quit message.
|
||||||
|
*/
|
||||||
|
public void handleQuit() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
handleQuitInternal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Throw IllegalStateException so new thread can execute.
|
||||||
|
// If showing dialog on this thread in 10.2, we would throw
|
||||||
|
// upon JOptionPane.NO_OPTION
|
||||||
|
throw new IllegalStateException("Quit Pending User Confirmation");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually do the quit action.
|
* Actually do the quit action.
|
||||||
*/
|
*/
|
||||||
@ -2050,6 +2219,26 @@ public class Editor extends JFrame
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected void handleReference() {
|
||||||
|
String text = textarea.getSelectedText().trim();
|
||||||
|
|
||||||
|
if (text.length() == 0) {
|
||||||
|
message("First select a word to find in the reference.");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String referenceFile = PdeKeywords.getReference(text);
|
||||||
|
//System.out.println("reference file is " + referenceFile);
|
||||||
|
if (referenceFile == null) {
|
||||||
|
message("No reference available for \"" + text + "\"");
|
||||||
|
} else {
|
||||||
|
Base.showReference(referenceFile + ".html");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void handleBurnBootloader(final String target, final boolean parallel) {
|
protected void handleBurnBootloader(final String target, final boolean parallel) {
|
||||||
if(debugging)
|
if(debugging)
|
||||||
doStop();
|
doStop();
|
||||||
@ -2083,6 +2272,7 @@ public class Editor extends JFrame
|
|||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void highlightLine(int lnum) {
|
public void highlightLine(int lnum) {
|
||||||
if (lnum < 0) {
|
if (lnum < 0) {
|
||||||
textarea.select(0, 0);
|
textarea.select(0, 0);
|
||||||
@ -2169,7 +2359,7 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
|
|
||||||
public void error(RunnerException e) {
|
public void error(RunnerException e) {
|
||||||
//System.out.println("ERORROOROROR 2");
|
//System.out.println("file and line is " + e.file + " " + e.line);
|
||||||
if (e.file >= 0) sketch.setCurrent(e.file);
|
if (e.file >= 0) sketch.setCurrent(e.file);
|
||||||
if (e.line >= 0) highlightLine(e.line);
|
if (e.line >= 0) highlightLine(e.line);
|
||||||
|
|
||||||
@ -2205,7 +2395,7 @@ public class Editor extends JFrame
|
|||||||
* Returns the edit popup menu.
|
* Returns the edit popup menu.
|
||||||
*/
|
*/
|
||||||
class TextAreaPopup extends JPopupMenu {
|
class TextAreaPopup extends JPopupMenu {
|
||||||
String currentDir = System.getProperty("user.dir");
|
//String currentDir = System.getProperty("user.dir");
|
||||||
String referenceFile = null;
|
String referenceFile = null;
|
||||||
|
|
||||||
JMenuItem cutItem, copyItem;
|
JMenuItem cutItem, copyItem;
|
||||||
@ -2251,13 +2441,14 @@ public class Editor extends JFrame
|
|||||||
|
|
||||||
this.addSeparator();
|
this.addSeparator();
|
||||||
|
|
||||||
// referenceItem = new JMenuItem("Find in Reference");
|
referenceItem = new JMenuItem("Find in Reference");
|
||||||
// referenceItem.addActionListener(new ActionListener() {
|
referenceItem.addActionListener(new ActionListener() {
|
||||||
// public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// Base.showReference(referenceFile);
|
//Base.showReference(referenceFile + ".html");
|
||||||
// }
|
handleReference(); //textarea.getSelectedText());
|
||||||
// });
|
}
|
||||||
// this.add(referenceItem);
|
});
|
||||||
|
this.add(referenceItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no text is selected, disable copy and cut menu items
|
// if no text is selected, disable copy and cut menu items
|
||||||
@ -2266,14 +2457,14 @@ public class Editor extends JFrame
|
|||||||
cutItem.setEnabled(true);
|
cutItem.setEnabled(true);
|
||||||
copyItem.setEnabled(true);
|
copyItem.setEnabled(true);
|
||||||
|
|
||||||
//referenceFile = PdeKeywords.getReference(textarea.getSelectedText());
|
String sel = textarea.getSelectedText().trim();
|
||||||
//if (referenceFile != null) {
|
referenceFile = PdeKeywords.getReference(sel);
|
||||||
//referenceItem.setEnabled(true);
|
referenceItem.setEnabled(referenceFile != null);
|
||||||
//}
|
|
||||||
} else {
|
} else {
|
||||||
cutItem.setEnabled(false);
|
cutItem.setEnabled(false);
|
||||||
copyItem.setEnabled(false);
|
copyItem.setEnabled(false);
|
||||||
//referenceItem.setEnabled(false);
|
referenceItem.setEnabled(false);
|
||||||
}
|
}
|
||||||
super.show(component, x, y);
|
super.show(component, x, y);
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,7 @@ public class EditorHeader extends JComponent {
|
|||||||
|
|
||||||
|
|
||||||
public void rebuildMenu() {
|
public void rebuildMenu() {
|
||||||
|
//System.out.println("rebuilding");
|
||||||
if (menu != null) {
|
if (menu != null) {
|
||||||
menu.removeAll();
|
menu.removeAll();
|
||||||
|
|
||||||
@ -248,6 +249,9 @@ public class EditorHeader extends JComponent {
|
|||||||
menu = new JMenu();
|
menu = new JMenu();
|
||||||
popup = menu.getPopupMenu();
|
popup = menu.getPopupMenu();
|
||||||
add(popup);
|
add(popup);
|
||||||
|
popup.setLightWeightPopupEnabled(true);
|
||||||
|
|
||||||
|
/*
|
||||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
popup.addPopupMenuListener(new PopupMenuListener() {
|
||||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||||
// on redraw, the isVisible() will get checked.
|
// on redraw, the isVisible() will get checked.
|
||||||
@ -259,6 +263,7 @@ public class EditorHeader extends JComponent {
|
|||||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
|
||||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
|
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
JMenuItem item;
|
JMenuItem item;
|
||||||
|
|
||||||
@ -352,6 +357,43 @@ public class EditorHeader extends JComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
menu.add(unhide);
|
menu.add(unhide);
|
||||||
|
menu.addSeparator();
|
||||||
|
|
||||||
|
// KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep
|
||||||
|
|
||||||
|
int ctrlAlt = ActionEvent.ALT_MASK |
|
||||||
|
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
|
||||||
|
//item = Editor.newJMenuItem("Previous Tab", '[', true);
|
||||||
|
item = new JMenuItem("Previous Tab");
|
||||||
|
//int shortcut = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
KeyStroke ctrlAltLeft = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAlt);
|
||||||
|
item.setAccelerator(ctrlAltLeft);
|
||||||
|
//int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
//KeyStroke tabby = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, modifiers);
|
||||||
|
|
||||||
|
// this didn't want to work consistently
|
||||||
|
/*
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
editor.sketch.prevCode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
|
//item = Editor.newJMenuItem("Next Tab", ']', true);
|
||||||
|
item = new JMenuItem("Next Tab");
|
||||||
|
KeyStroke ctrlAltRight = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAlt);
|
||||||
|
item.setAccelerator(ctrlAltRight);
|
||||||
|
/*
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
editor.sketch.nextCode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
if (sketch != null) {
|
if (sketch != null) {
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
@ -60,6 +60,10 @@ public class EditorListener {
|
|||||||
int selectionStart, selectionEnd;
|
int selectionStart, selectionEnd;
|
||||||
int position;
|
int position;
|
||||||
|
|
||||||
|
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
|
||||||
|
static final int CTRL_ALT = ActionEvent.ALT_MASK |
|
||||||
|
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
|
||||||
|
|
||||||
public EditorListener(Editor editor, JEditTextArea textarea) {
|
public EditorListener(Editor editor, JEditTextArea textarea) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
@ -105,6 +109,16 @@ public class EditorListener {
|
|||||||
//System.out.println(c + " " + code + " " + event);
|
//System.out.println(c + " " + code + " " + event);
|
||||||
//System.out.println();
|
//System.out.println();
|
||||||
|
|
||||||
|
if ((event.getModifiers() & CTRL_ALT) == CTRL_ALT) {
|
||||||
|
if (code == KeyEvent.VK_LEFT) {
|
||||||
|
editor.sketch.prevCode();
|
||||||
|
return true;
|
||||||
|
} else if (code == KeyEvent.VK_RIGHT) {
|
||||||
|
editor.sketch.nextCode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((event.getModifiers() & KeyEvent.META_MASK) != 0) {
|
if ((event.getModifiers() & KeyEvent.META_MASK) != 0) {
|
||||||
//event.consume(); // does nothing
|
//event.consume(); // does nothing
|
||||||
return false;
|
return false;
|
||||||
@ -195,8 +209,8 @@ public class EditorListener {
|
|||||||
|
|
||||||
switch ((int) c) {
|
switch ((int) c) {
|
||||||
|
|
||||||
case 9: // expand tabs
|
case 9:
|
||||||
if (tabsExpand) {
|
if (tabsExpand) { // expand tabs
|
||||||
textarea.setSelectedText(tabString);
|
textarea.setSelectedText(tabString);
|
||||||
event.consume();
|
event.consume();
|
||||||
return true;
|
return true;
|
||||||
@ -286,12 +300,40 @@ public class EditorListener {
|
|||||||
origIndex += offset; // ARGH!#(* WINDOWS#@($*
|
origIndex += offset; // ARGH!#(* WINDOWS#@($*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// if the previous thing is a brace (whether prev line or
|
||||||
|
// up farther) then the correct indent is the number of spaces
|
||||||
|
// on that line + 'indent'.
|
||||||
|
// if the previous line is not a brace, then just use the
|
||||||
|
// identical indentation to the previous line
|
||||||
|
|
||||||
|
// calculate the amount of indent on the previous line
|
||||||
|
// this will be used *only if the prev line is not an indent*
|
||||||
int spaceCount = calcSpaceCount(origIndex, contents);
|
int spaceCount = calcSpaceCount(origIndex, contents);
|
||||||
//int origCount = spaceCount;
|
|
||||||
|
// If the last character was a left curly brace, then indent.
|
||||||
|
// For 0122, walk backwards a bit to make sure that the there
|
||||||
|
// isn't a curly brace several spaces (or lines) back. Also
|
||||||
|
// moved this before calculating extraCount, since it'll affect
|
||||||
|
// that as well.
|
||||||
|
int index2 = origIndex;
|
||||||
|
while ((index2 >= 0) &&
|
||||||
|
Character.isWhitespace(contents[index2])) {
|
||||||
|
index2--;
|
||||||
|
}
|
||||||
|
if (index2 != -1) {
|
||||||
|
// still won't catch a case where prev stuff is a comment
|
||||||
|
if (contents[index2] == '{') {
|
||||||
|
// intermediate lines be damned,
|
||||||
|
// use the indent for this line instead
|
||||||
|
spaceCount = calcSpaceCount(index2, contents);
|
||||||
|
spaceCount += tabSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.out.println("spaceCount should be " + spaceCount);
|
||||||
|
|
||||||
// now before inserting this many spaces, walk forward from
|
// now before inserting this many spaces, walk forward from
|
||||||
// the caret position, so that the number of spaces aren't
|
// the caret position and count the number of spaces,
|
||||||
// just being duplicated again
|
// so that the number of spaces aren't duplicated again
|
||||||
int index = origIndex + 1;
|
int index = origIndex + 1;
|
||||||
int extraCount = 0;
|
int extraCount = 0;
|
||||||
while ((index < contents.length) &&
|
while ((index < contents.length) &&
|
||||||
@ -300,23 +342,58 @@ public class EditorListener {
|
|||||||
extraCount++;
|
extraCount++;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
int braceCount = 0;
|
||||||
|
while ((index < contents.length) && (contents[index] != '\n')) {
|
||||||
|
if (contents[index] == '}') {
|
||||||
|
braceCount++;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
// hitting return on a line with spaces *after* the caret
|
// hitting return on a line with spaces *after* the caret
|
||||||
// can cause trouble. for simplicity's sake, just ignore this case.
|
// can cause trouble. for 0099, was ignoring the case, but this is
|
||||||
//if (spaceCount < 0) spaceCount = origCount;
|
// annoying, so in 0122 we're trying to fix that.
|
||||||
|
/*
|
||||||
if (spaceCount - extraCount > 0) {
|
if (spaceCount - extraCount > 0) {
|
||||||
spaceCount -= extraCount;
|
spaceCount -= extraCount;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
spaceCount -= extraCount;
|
||||||
|
//if (spaceCount < 0) spaceCount = 0;
|
||||||
|
//System.out.println("extraCount is " + extraCount);
|
||||||
|
|
||||||
// if the last character was a left curly brace, then indent
|
// now, check to see if the current line contains a } and if so,
|
||||||
if (origIndex != -1) {
|
// outdent again by indent
|
||||||
if (contents[origIndex] == '{') {
|
//if (braceCount > 0) {
|
||||||
spaceCount += tabSize;
|
//spaceCount -= 2;
|
||||||
}
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (spaceCount < 0) {
|
||||||
|
// for rev 0122, actually delete extra space
|
||||||
|
//textarea.setSelectionStart(origIndex + 1);
|
||||||
|
textarea.setSelectionEnd(textarea.getSelectionEnd() - spaceCount);
|
||||||
|
textarea.setSelectedText("\n");
|
||||||
|
} else {
|
||||||
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
|
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
|
||||||
textarea.setSelectedText(insertion);
|
textarea.setSelectedText(insertion);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not gonna bother handling more than one brace
|
||||||
|
if (braceCount > 0) {
|
||||||
|
int sel = textarea.getSelectionStart();
|
||||||
|
// sel - tabSize will be -1 if start/end parens on the same line
|
||||||
|
// http://dev.processing.org/bugs/show_bug.cgi?id=484
|
||||||
|
if (sel - tabSize >= 0) {
|
||||||
|
textarea.select(sel - tabSize, sel);
|
||||||
|
String s = Editor.EMPTY.substring(0, tabSize);
|
||||||
|
// if these are spaces that we can delete
|
||||||
|
if (textarea.getSelectedText().equals(s)) {
|
||||||
|
textarea.setSelectedText("");
|
||||||
|
} else {
|
||||||
|
textarea.select(sel, sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// mark this event as already handled
|
// mark this event as already handled
|
||||||
event.consume();
|
event.consume();
|
||||||
@ -424,6 +501,34 @@ public class EditorListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Cmd-Shift or Ctrl-Shift depending on the platform */
|
||||||
|
//static final int CMD_SHIFT = ActionEvent.SHIFT_MASK |
|
||||||
|
// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
|
||||||
|
//static final int CTRL_ALT = ActionEvent.ALT_MASK |
|
||||||
|
// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
|
||||||
|
/*
|
||||||
|
public boolean keyTyped(KeyEvent event) {
|
||||||
|
char c = event.getKeyChar();
|
||||||
|
int code = event.getKeyCode();
|
||||||
|
|
||||||
|
if ((event.getModifiers() & CMD_ALT) == CMD_ALT) {
|
||||||
|
if (code == KeyEvent.VK_LEFT) {
|
||||||
|
//if (c == '[') {
|
||||||
|
editor.sketch.prevCode();
|
||||||
|
return true;
|
||||||
|
} else if (code == KeyEvent.VK_RIGHT) {
|
||||||
|
//} else if (c == ']') {
|
||||||
|
editor.sketch.nextCode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the index for the first character on this line.
|
* Return the index for the first character on this line.
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +57,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
|
|
||||||
JButton replaceButton;
|
JButton replaceButton;
|
||||||
JButton replaceAllButton;
|
JButton replaceAllButton;
|
||||||
|
JButton replaceFindButton;
|
||||||
JButton findButton;
|
JButton findButton;
|
||||||
|
|
||||||
JCheckBox ignoreCaseBox;
|
JCheckBox ignoreCaseBox;
|
||||||
@ -132,12 +133,14 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
|
|
||||||
// ordering is different on mac versus pc
|
// ordering is different on mac versus pc
|
||||||
if (Base.isMacOS()) {
|
if (Base.isMacOS()) {
|
||||||
buttons.add(replaceButton = new JButton("Replace"));
|
|
||||||
buttons.add(replaceAllButton = new JButton("Replace All"));
|
buttons.add(replaceAllButton = new JButton("Replace All"));
|
||||||
|
buttons.add(replaceButton = new JButton("Replace"));
|
||||||
|
buttons.add(replaceFindButton = new JButton("Replace & Find"));
|
||||||
buttons.add(findButton = new JButton("Find"));
|
buttons.add(findButton = new JButton("Find"));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(findButton = new JButton("Find"));
|
buttons.add(findButton = new JButton("Find"));
|
||||||
|
buttons.add(replaceFindButton = new JButton("Replace & Find"));
|
||||||
buttons.add(replaceButton = new JButton("Replace"));
|
buttons.add(replaceButton = new JButton("Replace"));
|
||||||
buttons.add(replaceAllButton = new JButton("Replace All"));
|
buttons.add(replaceAllButton = new JButton("Replace All"));
|
||||||
}
|
}
|
||||||
@ -169,10 +172,12 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
|
|
||||||
replaceButton.addActionListener(this);
|
replaceButton.addActionListener(this);
|
||||||
replaceAllButton.addActionListener(this);
|
replaceAllButton.addActionListener(this);
|
||||||
|
replaceFindButton.addActionListener(this);
|
||||||
findButton.addActionListener(this);
|
findButton.addActionListener(this);
|
||||||
|
|
||||||
// you mustn't replace what you haven't found, my son
|
// you mustn't replace what you haven't found, my son
|
||||||
replaceButton.setEnabled(false);
|
replaceButton.setEnabled(false);
|
||||||
|
replaceFindButton.setEnabled(false);
|
||||||
|
|
||||||
// so that typing will go straight to this field
|
// so that typing will go straight to this field
|
||||||
//findField.requestFocus();
|
//findField.requestFocus();
|
||||||
@ -189,44 +194,28 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
setBounds((screen.width - wide) / 2,
|
setBounds((screen.width - wide) / 2,
|
||||||
(screen.height - high) / 2, wide, high);
|
(screen.height - high) / 2, wide, high);
|
||||||
|
|
||||||
// add key listener to trap esc and ctrl/cmd-w
|
|
||||||
/*
|
|
||||||
KeyListener listener = new KeyAdapter() {
|
|
||||||
public void keyPressed(KeyEvent e) {
|
|
||||||
if (Base.isCloseWindowEvent(e)) hide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
findField.addKeyListener(listener);
|
|
||||||
replaceField.addKeyListener(listener);
|
|
||||||
addKeyListener(listener);
|
|
||||||
*/
|
|
||||||
ActionListener disposer = new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
|
||||||
//hide();
|
|
||||||
handleClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
handleClose();
|
handleClose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Base.registerWindowCloseKeys(getRootPane(), disposer);
|
Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
//hide();
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
// hack to to get first field to focus properly on osx
|
// hack to to get first field to focus properly on osx
|
||||||
// though this still doesn't seem to work
|
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
public void windowActivated(WindowEvent e) {
|
public void windowActivated(WindowEvent e) {
|
||||||
//System.out.println("activating");
|
//System.out.println("activating");
|
||||||
//boolean ok = findField.requestFocusInWindow();
|
boolean ok = findField.requestFocusInWindow();
|
||||||
//System.out.println("got " + ok);
|
//System.out.println("got " + ok);
|
||||||
//findField.selectAll();
|
findField.selectAll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -256,6 +245,10 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
if (source == findButton) {
|
if (source == findButton) {
|
||||||
find(true);
|
find(true);
|
||||||
|
|
||||||
|
} else if (source == replaceFindButton) {
|
||||||
|
replace();
|
||||||
|
find(true);
|
||||||
|
|
||||||
} else if (source == replaceButton) {
|
} else if (source == replaceButton) {
|
||||||
replace();
|
replace();
|
||||||
|
|
||||||
@ -276,6 +269,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
found = false;
|
found = false;
|
||||||
|
|
||||||
String search = findField.getText();
|
String search = findField.getText();
|
||||||
|
//System.out.println("finding for " + search + " " + findString);
|
||||||
// this will catch "find next" being called when no search yet
|
// this will catch "find next" being called when no search yet
|
||||||
if (search.length() == 0) return;
|
if (search.length() == 0) return;
|
||||||
|
|
||||||
@ -299,12 +293,14 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
if (nextIndex == -1) {
|
if (nextIndex == -1) {
|
||||||
found = false;
|
found = false;
|
||||||
replaceButton.setEnabled(false);
|
replaceButton.setEnabled(false);
|
||||||
|
replaceFindButton.setEnabled(false);
|
||||||
//Toolkit.getDefaultToolkit().beep();
|
//Toolkit.getDefaultToolkit().beep();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
replaceButton.setEnabled(true);
|
replaceButton.setEnabled(true);
|
||||||
|
replaceFindButton.setEnabled(true);
|
||||||
editor.textarea.select(nextIndex, nextIndex + search.length());
|
editor.textarea.select(nextIndex, nextIndex + search.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,6 +318,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
if (sel.equals(replaceField.getText())) {
|
if (sel.equals(replaceField.getText())) {
|
||||||
found = false;
|
found = false;
|
||||||
replaceButton.setEnabled(false);
|
replaceButton.setEnabled(false);
|
||||||
|
replaceFindButton.setEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +329,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
|||||||
|
|
||||||
// don't allow a double replace
|
// don't allow a double replace
|
||||||
replaceButton.setEnabled(false);
|
replaceButton.setEnabled(false);
|
||||||
|
replaceFindButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ import java.awt.event.*;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
|
|
||||||
|
import processing.core.*;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Provides information about and builds a library
|
* Provides information about and builds a library
|
||||||
*/
|
*/
|
||||||
@ -552,7 +554,7 @@ public class Library implements MessageConsumer{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String pieces[] = Base.split(line, '\t');
|
String pieces[] = PApplet.split(line, '\t');
|
||||||
|
|
||||||
if (pieces.length >= 2) {
|
if (pieces.length >= 2) {
|
||||||
String keyword = pieces[0].trim();
|
String keyword = pieces[0].trim();
|
||||||
|
@ -41,7 +41,12 @@ import javax.swing.filechooser.*;
|
|||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
import javax.swing.undo.*;
|
import javax.swing.undo.*;
|
||||||
|
|
||||||
//import processing.core.PApplet;
|
import processing.core.PApplet;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO change this to use the Java Preferences API
|
||||||
|
// http://www.onjava.com/pub/a/onjava/synd/2001/10/17/j2se.html
|
||||||
|
// http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter10/Preferences.html
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +55,10 @@ import javax.swing.undo.*;
|
|||||||
* This class no longer uses the Properties class, since
|
* This class no longer uses the Properties class, since
|
||||||
* properties files are iso8859-1, which is highly likely to
|
* properties files are iso8859-1, which is highly likely to
|
||||||
* be a problem when trying to save sketch folders and locations.
|
* be a problem when trying to save sketch folders and locations.
|
||||||
|
* <p>
|
||||||
|
* This is very poorly put together, that the prefs panel and the
|
||||||
|
* actual prefs i/o is part of the same code. But there hasn't yet
|
||||||
|
* been a compelling reason to bother with the separation.
|
||||||
*/
|
*/
|
||||||
public class Preferences {
|
public class Preferences {
|
||||||
|
|
||||||
@ -88,9 +97,12 @@ public class Preferences {
|
|||||||
* inside a static block.
|
* inside a static block.
|
||||||
*/
|
*/
|
||||||
static public int BUTTON_HEIGHT = 24;
|
static public int BUTTON_HEIGHT = 24;
|
||||||
|
/*
|
||||||
|
// remove this for 0121, because quaqua takes care of it
|
||||||
static {
|
static {
|
||||||
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
|
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// value for the size bars, buttons, etc
|
// value for the size bars, buttons, etc
|
||||||
|
|
||||||
@ -107,15 +119,18 @@ public class Preferences {
|
|||||||
|
|
||||||
// gui elements
|
// gui elements
|
||||||
|
|
||||||
JDialog dialog;
|
//JDialog dialog;
|
||||||
|
JFrame dialog;
|
||||||
int wide, high;
|
int wide, high;
|
||||||
|
|
||||||
JTextField sketchbookLocationField;
|
JTextField sketchbookLocationField;
|
||||||
|
JCheckBox exportSeparateBox;
|
||||||
JCheckBox sketchPromptBox;
|
JCheckBox sketchPromptBox;
|
||||||
JCheckBox sketchCleanBox;
|
JCheckBox sketchCleanBox;
|
||||||
JCheckBox externalEditorBox;
|
JCheckBox externalEditorBox;
|
||||||
|
JCheckBox memoryOverrideBox;
|
||||||
|
JTextField memoryField;
|
||||||
JCheckBox checkUpdatesBox;
|
JCheckBox checkUpdatesBox;
|
||||||
|
|
||||||
JTextField fontSizeField;
|
JTextField fontSizeField;
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +160,7 @@ public class Preferences {
|
|||||||
// check for platform-specific properties in the defaults
|
// check for platform-specific properties in the defaults
|
||||||
|
|
||||||
String platformExtension = "." +
|
String platformExtension = "." +
|
||||||
platforms[Base.platform];
|
platforms[processing.core.PApplet.platform];
|
||||||
int extensionLength = platformExtension.length();
|
int extensionLength = platformExtension.length();
|
||||||
|
|
||||||
Enumeration e = table.keys(); //properties.propertyNames();
|
Enumeration e = table.keys(); //properties.propertyNames();
|
||||||
@ -195,7 +210,8 @@ public class Preferences {
|
|||||||
|
|
||||||
// setup dialog for the prefs
|
// setup dialog for the prefs
|
||||||
|
|
||||||
dialog = new JDialog(editor, "Preferences", true);
|
//dialog = new JDialog(editor, "Preferences", true);
|
||||||
|
dialog = new JFrame("Preferences");
|
||||||
dialog.setResizable(false);
|
dialog.setResizable(false);
|
||||||
|
|
||||||
Container pain = dialog.getContentPane();
|
Container pain = dialog.getContentPane();
|
||||||
@ -249,6 +265,7 @@ public class Preferences {
|
|||||||
button = new JButton(PROMPT_BROWSE);
|
button = new JButton(PROMPT_BROWSE);
|
||||||
button.addActionListener(new ActionListener() {
|
button.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
/*
|
||||||
JFileChooser fc = new JFileChooser();
|
JFileChooser fc = new JFileChooser();
|
||||||
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
|
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
|
||||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
@ -258,6 +275,13 @@ public class Preferences {
|
|||||||
File file = fc.getSelectedFile();
|
File file = fc.getSelectedFile();
|
||||||
sketchbookLocationField.setText(file.getAbsolutePath());
|
sketchbookLocationField.setText(file.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
File dflt = new File(sketchbookLocationField.getText());
|
||||||
|
File file =
|
||||||
|
Base.selectFolder("Select new sketchbook location", dflt, dialog);
|
||||||
|
if (file != null) {
|
||||||
|
sketchbookLocationField.setText(file.getAbsolutePath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pain.add(button);
|
pain.add(button);
|
||||||
@ -286,6 +310,8 @@ public class Preferences {
|
|||||||
box.add(label);
|
box.add(label);
|
||||||
fontSizeField = new JTextField(4);
|
fontSizeField = new JTextField(4);
|
||||||
box.add(fontSizeField);
|
box.add(fontSizeField);
|
||||||
|
label = new JLabel(" (requires restart of Arduino)");
|
||||||
|
box.add(label);
|
||||||
pain.add(box);
|
pain.add(box);
|
||||||
d = box.getPreferredSize();
|
d = box.getPreferredSize();
|
||||||
box.setBounds(left, top, d.width, d.height);
|
box.setBounds(left, top, d.width, d.height);
|
||||||
@ -468,9 +494,9 @@ public class Preferences {
|
|||||||
String newSizeText = fontSizeField.getText();
|
String newSizeText = fontSizeField.getText();
|
||||||
try {
|
try {
|
||||||
int newSize = Integer.parseInt(newSizeText.trim());
|
int newSize = Integer.parseInt(newSizeText.trim());
|
||||||
String pieces[] = Base.split(get("editor.font"), ',');
|
String pieces[] = PApplet.split(get("editor.font"), ',');
|
||||||
pieces[2] = String.valueOf(newSize);
|
pieces[2] = String.valueOf(newSize);
|
||||||
set("editor.font", Base.join(pieces, ','));
|
set("editor.font", PApplet.join(pieces, ','));
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("ignoring invalid font size " + newSizeText);
|
System.err.println("ignoring invalid font size " + newSizeText);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
//import processing.core.*;
|
import processing.core.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
@ -40,7 +40,7 @@ import com.oroinc.text.regex.*;
|
|||||||
*/
|
*/
|
||||||
public class Runner implements MessageConsumer {
|
public class Runner implements MessageConsumer {
|
||||||
|
|
||||||
//PApplet applet;
|
PApplet applet;
|
||||||
RunnerException exception;
|
RunnerException exception;
|
||||||
Window window;
|
Window window;
|
||||||
PrintStream leechErr;
|
PrintStream leechErr;
|
||||||
@ -497,6 +497,7 @@ java.lang.NullPointerException
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (codeIndex != -1) {
|
if (codeIndex != -1) {
|
||||||
|
//System.out.println("got line num " + lineNumber);
|
||||||
// in case this was a tab that got embedded into the main .java
|
// in case this was a tab that got embedded into the main .java
|
||||||
lineNumber -= sketch.code[codeIndex].preprocOffset;
|
lineNumber -= sketch.code[codeIndex].preprocOffset;
|
||||||
|
|
||||||
|
257
app/Sketch.java
257
app/Sketch.java
@ -24,7 +24,7 @@
|
|||||||
package processing.app;
|
package processing.app;
|
||||||
|
|
||||||
import processing.app.preproc.*;
|
import processing.app.preproc.*;
|
||||||
//import processing.core.*;
|
import processing.core.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -73,6 +73,7 @@ public class Sketch {
|
|||||||
static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
|
static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
|
||||||
|
|
||||||
public SketchCode current;
|
public SketchCode current;
|
||||||
|
int currentIndex;
|
||||||
int codeCount;
|
int codeCount;
|
||||||
SketchCode code[];
|
SketchCode code[];
|
||||||
|
|
||||||
@ -225,7 +226,11 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any entries that didn't load properly
|
// some of the hidden files may be bad too, so use hiddenCounter
|
||||||
|
// added for rev 0121, fixes bug found by axel
|
||||||
|
hiddenCount = hiddenCounter;
|
||||||
|
|
||||||
|
// remove any entries that didn't load properly from codeCount
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index < codeCount) {
|
while (index < codeCount) {
|
||||||
if ((code[index] == null) ||
|
if ((code[index] == null) ||
|
||||||
@ -330,7 +335,7 @@ public class Sketch {
|
|||||||
// ask for new name of file (internal to window)
|
// ask for new name of file (internal to window)
|
||||||
// TODO maybe just popup a text area?
|
// TODO maybe just popup a text area?
|
||||||
renamingCode = true;
|
renamingCode = true;
|
||||||
String prompt = (current == code[0]) ?
|
String prompt = (currentIndex == 0) ?
|
||||||
"New name for sketch:" : "New name for file:";
|
"New name for sketch:" : "New name for file:";
|
||||||
String oldName = current.name + flavorExtensionsShown[current.flavor];
|
String oldName = current.name + flavorExtensionsShown[current.flavor];
|
||||||
editor.status.edit(prompt, oldName);
|
editor.status.edit(prompt, oldName);
|
||||||
@ -436,7 +441,7 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (renamingCode) {
|
if (renamingCode) {
|
||||||
if (current == code[0]) {
|
if (currentIndex == 0) {
|
||||||
// get the new folder name/location
|
// get the new folder name/location
|
||||||
File newFolder = new File(folder.getParentFile(), newName);
|
File newFolder = new File(folder.getParentFile(), newName);
|
||||||
if (newFolder.exists()) {
|
if (newFolder.exists()) {
|
||||||
@ -494,43 +499,17 @@ public class Sketch {
|
|||||||
// having saved everything and renamed the folder and the main .pde,
|
// having saved everything and renamed the folder and the main .pde,
|
||||||
// use the editor to re-open the sketch to re-init state
|
// use the editor to re-open the sketch to re-init state
|
||||||
// (unfortunately this will kill positions for carets etc)
|
// (unfortunately this will kill positions for carets etc)
|
||||||
editor.handleOpenUnchecked(mainFilename);
|
editor.handleOpenUnchecked(mainFilename,
|
||||||
|
currentIndex,
|
||||||
/*
|
editor.textarea.getSelectionStart(),
|
||||||
// backtrack and don't rename the sketch folder
|
editor.textarea.getSelectionEnd(),
|
||||||
success = newFolder.renameTo(folder);
|
editor.textarea.getScrollPosition());
|
||||||
if (!success) {
|
|
||||||
String msg =
|
|
||||||
"Started renaming sketch and then ran into\n" +
|
|
||||||
"nasty trouble. Try to salvage with Copy & Paste\n" +
|
|
||||||
"or attempt a \"Save As\" to see if that works.";
|
|
||||||
Base.showWarning("Serious Error", msg, null);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// set the sketch name... used by the pde and whatnot.
|
|
||||||
// the name is only set in the sketch constructor,
|
|
||||||
// so it's important here
|
|
||||||
name = newName;
|
|
||||||
|
|
||||||
code[0].name = newName;
|
|
||||||
code[0].file = mainFile;
|
|
||||||
code[0].program = editor.getText();
|
|
||||||
code[0].save();
|
|
||||||
|
|
||||||
folder = newFolder;
|
|
||||||
|
|
||||||
// get the changes into the sketchbook menu
|
// get the changes into the sketchbook menu
|
||||||
|
// (re-enabled in 0115 to fix bug #332)
|
||||||
editor.sketchbook.rebuildMenus();
|
editor.sketchbook.rebuildMenus();
|
||||||
|
|
||||||
// reload the sketch
|
} else { // else if something besides code[0]
|
||||||
load();
|
|
||||||
*/
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (!current.file.renameTo(newFile)) {
|
if (!current.file.renameTo(newFile)) {
|
||||||
Base.showWarning("Error",
|
Base.showWarning("Error",
|
||||||
"Could not rename \"" + current.file.getName() +
|
"Could not rename \"" + current.file.getName() +
|
||||||
@ -593,7 +572,7 @@ public class Sketch {
|
|||||||
|
|
||||||
// confirm deletion with user, yes/no
|
// confirm deletion with user, yes/no
|
||||||
Object[] options = { "OK", "Cancel" };
|
Object[] options = { "OK", "Cancel" };
|
||||||
String prompt = (current == code[0]) ?
|
String prompt = (currentIndex == 0) ?
|
||||||
"Are you sure you want to delete this sketch?" :
|
"Are you sure you want to delete this sketch?" :
|
||||||
"Are you sure you want to delete \"" + current.name +
|
"Are you sure you want to delete \"" + current.name +
|
||||||
flavorExtensionsShown[current.flavor] + "\"?";
|
flavorExtensionsShown[current.flavor] + "\"?";
|
||||||
@ -606,7 +585,7 @@ public class Sketch {
|
|||||||
options,
|
options,
|
||||||
options[0]);
|
options[0]);
|
||||||
if (result == JOptionPane.YES_OPTION) {
|
if (result == JOptionPane.YES_OPTION) {
|
||||||
if (current == code[0]) {
|
if (currentIndex == 0) {
|
||||||
// need to unset all the modified flags, otherwise tries
|
// need to unset all the modified flags, otherwise tries
|
||||||
// to do a save on the handleNew()
|
// to do a save on the handleNew()
|
||||||
|
|
||||||
@ -672,7 +651,7 @@ public class Sketch {
|
|||||||
|
|
||||||
// don't allow hide of the main code
|
// don't allow hide of the main code
|
||||||
// TODO maybe gray out the menu on setCurrent(0)
|
// TODO maybe gray out the menu on setCurrent(0)
|
||||||
if (current == code[0]) {
|
if (currentIndex == 0) {
|
||||||
Base.showMessage("Can't do that",
|
Base.showMessage("Can't do that",
|
||||||
"You cannot hide the main " +
|
"You cannot hide the main " +
|
||||||
".pde file from a sketch\n");
|
".pde file from a sketch\n");
|
||||||
@ -933,57 +912,14 @@ public class Sketch {
|
|||||||
File newFile = new File(newFolder, newName + ".pde");
|
File newFile = new File(newFolder, newName + ".pde");
|
||||||
code[0].saveAs(newFile);
|
code[0].saveAs(newFile);
|
||||||
|
|
||||||
editor.handleOpenUnchecked(newFile.getPath());
|
editor.handleOpenUnchecked(newFile.getPath(),
|
||||||
|
currentIndex,
|
||||||
|
editor.textarea.getSelectionStart(),
|
||||||
|
editor.textarea.getSelectionEnd(),
|
||||||
|
editor.textarea.getScrollPosition());
|
||||||
|
|
||||||
/*
|
// Name changed, rebuild the sketch menus
|
||||||
// copy the entire contents of the sketch folder
|
editor.sketchbook.rebuildMenusAsync();
|
||||||
Base.copyDir(folder, newFolder);
|
|
||||||
|
|
||||||
// change the references to the dir location in SketchCode files
|
|
||||||
for (int i = 0; i < codeCount; i++) {
|
|
||||||
code[i].file = new File(newFolder, code[i].file.getName());
|
|
||||||
}
|
|
||||||
for (int i = 0; i < hiddenCount; i++) {
|
|
||||||
hidden[i].file = new File(newFolder, hidden[i].file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the old sketch file from the new dir
|
|
||||||
code[0].file.delete();
|
|
||||||
// name for the new main .pde file
|
|
||||||
code[0].file = new File(newFolder, newName + ".pde");
|
|
||||||
code[0].name = newName;
|
|
||||||
// write the contents to the renamed file
|
|
||||||
// (this may be resaved if the code is modified)
|
|
||||||
code[0].modified = true;
|
|
||||||
//code[0].save();
|
|
||||||
//System.out.println("modified is " + modified);
|
|
||||||
|
|
||||||
// change the other paths
|
|
||||||
String oldName = name;
|
|
||||||
name = newName;
|
|
||||||
File oldFolder = folder;
|
|
||||||
folder = newFolder;
|
|
||||||
dataFolder = new File(folder, "data");
|
|
||||||
codeFolder = new File(folder, "code");
|
|
||||||
|
|
||||||
// remove the 'applet', 'application', 'library' folders
|
|
||||||
// from the copied version.
|
|
||||||
// otherwise their .class and .jar files can cause conflicts.
|
|
||||||
Base.removeDir(new File(folder, "applet"));
|
|
||||||
Base.removeDir(new File(folder, "application"));
|
|
||||||
//Base.removeDir(new File(folder, "library"));
|
|
||||||
|
|
||||||
// do a "save"
|
|
||||||
// this will take care of the unsaved changes in each of the tabs
|
|
||||||
save();
|
|
||||||
|
|
||||||
// get the changes into the sketchbook menu
|
|
||||||
//sketchbook.rebuildMenu();
|
|
||||||
// done inside Editor instead
|
|
||||||
|
|
||||||
// update the tabs for the name change
|
|
||||||
editor.header.repaint();
|
|
||||||
*/
|
|
||||||
|
|
||||||
// let Editor know that the save was successful
|
// let Editor know that the save was successful
|
||||||
return true;
|
return true;
|
||||||
@ -1168,8 +1104,8 @@ public class Sketch {
|
|||||||
* </OL>
|
* </OL>
|
||||||
*/
|
*/
|
||||||
public void setCurrent(int which) {
|
public void setCurrent(int which) {
|
||||||
if (current == code[which]) {
|
// if current is null, then this is the first setCurrent(0)
|
||||||
//System.out.println("already current, ignoring");
|
if ((currentIndex == which) && (current != null)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,6 +1118,7 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
current = code[which];
|
current = code[which];
|
||||||
|
currentIndex = which;
|
||||||
editor.setCode(current);
|
editor.setCode(current);
|
||||||
//editor.setDocument(current.document,
|
//editor.setDocument(current.document,
|
||||||
// current.selectionStart, current.selectionStop,
|
// current.selectionStart, current.selectionStop,
|
||||||
@ -1286,6 +1223,9 @@ public class Sketch {
|
|||||||
//handleOpen(sketch);
|
//handleOpen(sketch);
|
||||||
//history.lastRecorded = historySaved;
|
//history.lastRecorded = historySaved;
|
||||||
|
|
||||||
|
// set current to null so that the tab gets updated
|
||||||
|
// http://dev.processing.org/bugs/show_bug.cgi?id=515
|
||||||
|
current = null;
|
||||||
// nuke previous files and settings, just get things loaded
|
// nuke previous files and settings, just get things loaded
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
@ -1746,7 +1686,12 @@ public class Sketch {
|
|||||||
// make sure the user didn't hide the sketch folder
|
// make sure the user didn't hide the sketch folder
|
||||||
ensureExistence();
|
ensureExistence();
|
||||||
|
|
||||||
current.program = editor.getText();
|
// fix for issue posted on the board. make sure that the code
|
||||||
|
// is reloaded when exporting and an external editor is being used.
|
||||||
|
if (Preferences.getBoolean("editor.external")) {
|
||||||
|
// nuke previous files and settings
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
zipFileContents = new Hashtable();
|
zipFileContents = new Hashtable();
|
||||||
|
|
||||||
@ -1773,6 +1718,7 @@ public class Sketch {
|
|||||||
|
|
||||||
/* int wide = PApplet.DEFAULT_WIDTH;
|
/* int wide = PApplet.DEFAULT_WIDTH;
|
||||||
int high = PApplet.DEFAULT_HEIGHT;
|
int high = PApplet.DEFAULT_HEIGHT;
|
||||||
|
String renderer = "";
|
||||||
|
|
||||||
PatternMatcher matcher = new Perl5Matcher();
|
PatternMatcher matcher = new Perl5Matcher();
|
||||||
PatternCompiler compiler = new Perl5Compiler();
|
PatternCompiler compiler = new Perl5Compiler();
|
||||||
@ -1785,20 +1731,26 @@ public class Sketch {
|
|||||||
// modified for 83 to match size(XXX, ddd so that it'll
|
// modified for 83 to match size(XXX, ddd so that it'll
|
||||||
// properly handle size(200, 200) and size(200, 200, P3D)
|
// properly handle size(200, 200) and size(200, 200, P3D)
|
||||||
String sizing =
|
String sizing =
|
||||||
"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+)";
|
// match the renderer string as well
|
||||||
|
"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+),?\\s*([^\\)]*)\\s*\\)";
|
||||||
|
// match just the width and height
|
||||||
|
//"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+)(.*)\\)";
|
||||||
Pattern pattern = compiler.compile(sizing);
|
Pattern pattern = compiler.compile(sizing);
|
||||||
|
|
||||||
// adds a space at the beginning, in case size() is the very
|
// adds a space at the beginning, in case size() is the very
|
||||||
// first thing in the program (very common), since the regexp
|
// first thing in the program (very common), since the regexp
|
||||||
// needs to check for things in front of it.
|
// needs to check for things in front of it.
|
||||||
PatternMatcherInput input =
|
PatternMatcherInput input =
|
||||||
new PatternMatcherInput(" " + code[0].program);
|
new PatternMatcherInput(" " + scrubComments(code[0].program));
|
||||||
if (matcher.contains(input, pattern)) {
|
if (matcher.contains(input, pattern)) {
|
||||||
MatchResult result = matcher.getMatch();
|
MatchResult result = matcher.getMatch();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
wide = Integer.parseInt(result.group(1).toString());
|
wide = Integer.parseInt(result.group(1).toString());
|
||||||
high = Integer.parseInt(result.group(2).toString());
|
high = Integer.parseInt(result.group(2).toString());
|
||||||
|
|
||||||
|
renderer = result.group(3).toString(); //.trim();
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// found a reference to size, but it didn't
|
// found a reference to size, but it didn't
|
||||||
// seem to contain numbers
|
// seem to contain numbers
|
||||||
@ -1865,45 +1817,6 @@ public class Sketch {
|
|||||||
if (is == null) {
|
if (is == null) {
|
||||||
is = Base.getStream("applet.html");
|
is = Base.getStream("applet.html");
|
||||||
}
|
}
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
|
||||||
|
|
||||||
String line = null;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
if (line.indexOf("@@") != -1) {
|
|
||||||
StringBuffer sb = new StringBuffer(line);
|
|
||||||
int index = 0;
|
|
||||||
while ((index = sb.indexOf("@@sketch@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@sketch@@".length(),
|
|
||||||
name);
|
|
||||||
}
|
|
||||||
while ((index = sb.indexOf("@@source@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@source@@".length(),
|
|
||||||
sources.toString());
|
|
||||||
}
|
|
||||||
while ((index = sb.indexOf("@@archive@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@archive@@".length(),
|
|
||||||
name + ".jar");
|
|
||||||
}
|
|
||||||
while ((index = sb.indexOf("@@width@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@width@@".length(),
|
|
||||||
String.valueOf(wide));
|
|
||||||
}
|
|
||||||
while ((index = sb.indexOf("@@height@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@height@@".length(),
|
|
||||||
String.valueOf(high));
|
|
||||||
}
|
|
||||||
while ((index = sb.indexOf("@@description@@")) != -1) {
|
|
||||||
sb.replace(index, index + "@@description@@".length(),
|
|
||||||
description);
|
|
||||||
}
|
|
||||||
line = sb.toString();
|
|
||||||
}
|
|
||||||
ps.println(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.close();
|
|
||||||
ps.flush();
|
|
||||||
ps.close();
|
|
||||||
|
|
||||||
// copy the loading gif to the applet
|
// copy the loading gif to the applet
|
||||||
String LOADING_IMAGE = "loading.gif";
|
String LOADING_IMAGE = "loading.gif";
|
||||||
@ -1929,13 +1842,13 @@ public class Sketch {
|
|||||||
new FileOutputStream(new File(appletFolder, name + ".jar"));
|
new FileOutputStream(new File(appletFolder, name + ".jar"));
|
||||||
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
|
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
|
archives.append(name + ".jar");
|
||||||
|
|
||||||
// add the manifest file
|
// add the manifest file
|
||||||
addManifest(zos);
|
addManifest(zos);
|
||||||
|
|
||||||
// add the contents of the code folder to the jar
|
// add the contents of the code folder to the jar
|
||||||
// unpacks all jar files
|
// unpacks all jar files, unless multi jar files selected in prefs
|
||||||
//File codeFolder = new File(folder, "code");
|
|
||||||
if (codeFolder.exists()) {
|
if (codeFolder.exists()) {
|
||||||
String includes = Compiler.contentsToClassPath(codeFolder);
|
String includes = Compiler.contentsToClassPath(codeFolder);
|
||||||
packClassPathIntoZipFile(includes, zos);
|
packClassPathIntoZipFile(includes, zos);
|
||||||
@ -1980,7 +1893,18 @@ public class Sketch {
|
|||||||
|
|
||||||
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
|
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
|
||||||
exportFile.getName().toLowerCase().endsWith(".jar")) {
|
exportFile.getName().toLowerCase().endsWith(".jar")) {
|
||||||
|
if (separateJar) {
|
||||||
|
String exportFilename = exportFile.getName();
|
||||||
|
Base.copyFile(exportFile, new File(appletFolder, exportFilename));
|
||||||
|
if (renderer.equals("OPENGL") &&
|
||||||
|
exportFilename.indexOf("natives") != -1) {
|
||||||
|
// don't add these to the archives list
|
||||||
|
} else {
|
||||||
|
archives.append("," + exportFilename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
packClassPathIntoZipFile(exportFile.getAbsolutePath(), zos);
|
packClassPathIntoZipFile(exportFile.getAbsolutePath(), zos);
|
||||||
|
}
|
||||||
|
|
||||||
} else { // just copy the file over.. prolly a .dll or something
|
} else { // just copy the file over.. prolly a .dll or something
|
||||||
Base.copyFile(exportFile,
|
Base.copyFile(exportFile,
|
||||||
@ -1991,6 +1915,7 @@ public class Sketch {
|
|||||||
*/
|
*/
|
||||||
/* String bagelJar = "lib/core.jar";
|
/* String bagelJar = "lib/core.jar";
|
||||||
packClassPathIntoZipFile(bagelJar, zos);
|
packClassPathIntoZipFile(bagelJar, zos);
|
||||||
|
}
|
||||||
|
|
||||||
// files to include from data directory
|
// files to include from data directory
|
||||||
// TODO this needs to be recursive
|
// TODO this needs to be recursive
|
||||||
@ -2049,6 +1974,53 @@ public class Sketch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public String scrubComments(String what) {
|
||||||
|
char p[] = what.toCharArray();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
while (index < p.length) {
|
||||||
|
// for any double slash comments, ignore until the end of the line
|
||||||
|
if ((p[index] == '/') &&
|
||||||
|
(index < p.length - 1) &&
|
||||||
|
(p[index+1] == '/')) {
|
||||||
|
p[index++] = ' ';
|
||||||
|
p[index++] = ' ';
|
||||||
|
while ((index < p.length) &&
|
||||||
|
(p[index] != '\n')) {
|
||||||
|
p[index++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if this is the start of a new multiline comment.
|
||||||
|
// if it is, then make sure it's actually terminated somewhere.
|
||||||
|
} else if ((p[index] == '/') &&
|
||||||
|
(index < p.length - 1) &&
|
||||||
|
(p[index+1] == '*')) {
|
||||||
|
p[index++] = ' ';
|
||||||
|
p[index++] = ' ';
|
||||||
|
boolean endOfRainbow = false;
|
||||||
|
while (index < p.length - 1) {
|
||||||
|
if ((p[index] == '*') && (p[index+1] == '/')) {
|
||||||
|
p[index++] = ' ';
|
||||||
|
p[index++] = ' ';
|
||||||
|
endOfRainbow = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!endOfRainbow) {
|
||||||
|
throw new RuntimeException("Missing the */ from the end of a " +
|
||||||
|
"/* comment */");
|
||||||
|
}
|
||||||
|
} else { // any old character, move along
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export to application.
|
* Export to application.
|
||||||
* <PRE>
|
* <PRE>
|
||||||
@ -2135,7 +2107,6 @@ public class Sketch {
|
|||||||
|
|
||||||
for (int i = 0; i < pieces.length; i++) {
|
for (int i = 0; i < pieces.length; i++) {
|
||||||
if (pieces[i].length() == 0) continue;
|
if (pieces[i].length() == 0) continue;
|
||||||
//System.out.println("checking piece " + pieces[i]);
|
|
||||||
|
|
||||||
// is it a jar file or directory?
|
// is it a jar file or directory?
|
||||||
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
||||||
@ -2299,4 +2270,16 @@ public class Sketch {
|
|||||||
public String getMainFilePath() {
|
public String getMainFilePath() {
|
||||||
return code[0].file.getAbsolutePath();
|
return code[0].file.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void prevCode() {
|
||||||
|
int prev = currentIndex - 1;
|
||||||
|
if (prev < 0) prev = codeCount-1;
|
||||||
|
setCurrent(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void nextCode() {
|
||||||
|
setCurrent((currentIndex + 1) % codeCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ public class Sketchbook {
|
|||||||
|
|
||||||
//System.out.println("resetting sketchbook path");
|
//System.out.println("resetting sketchbook path");
|
||||||
File sketchbookFolder = Base.getDefaultSketchbookFolder();
|
File sketchbookFolder = Base.getDefaultSketchbookFolder();
|
||||||
|
//System.out.println("default is " + sketchbookFolder);
|
||||||
Preferences.set("sketchbook.path",
|
Preferences.set("sketchbook.path",
|
||||||
sketchbookFolder.getAbsolutePath());
|
sketchbookFolder.getAbsolutePath());
|
||||||
|
|
||||||
@ -170,11 +171,8 @@ public class Sketchbook {
|
|||||||
if (noPrompt) prompt = false;
|
if (noPrompt) prompt = false;
|
||||||
|
|
||||||
if (prompt) {
|
if (prompt) {
|
||||||
//if (!startup) {
|
|
||||||
// prompt for the filename and location for the new sketch
|
// prompt for the filename and location for the new sketch
|
||||||
|
FileDialog fd = new FileDialog(editor,
|
||||||
FileDialog fd = new FileDialog(editor, //new Frame(),
|
|
||||||
//"Create new sketch named",
|
|
||||||
"Create sketch folder named:",
|
"Create sketch folder named:",
|
||||||
FileDialog.SAVE);
|
FileDialog.SAVE);
|
||||||
fd.setDirectory(getSketchbookPath());
|
fd.setDirectory(getSketchbookPath());
|
||||||
@ -228,7 +226,7 @@ public class Sketchbook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make a note of a newly added sketch in the sketchbook menu
|
// make a note of a newly added sketch in the sketchbook menu
|
||||||
rebuildMenus();
|
rebuildMenusAsync();
|
||||||
|
|
||||||
// now open it up
|
// now open it up
|
||||||
//handleOpen(newbieName, newbieFile, newbieDir);
|
//handleOpen(newbieName, newbieFile, newbieDir);
|
||||||
@ -257,10 +255,25 @@ public class Sketchbook {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java classes are pretty limited about what you can use
|
* Return true if the name is valid for a Processing sketch.
|
||||||
* for their naming. This helper function replaces everything
|
*/
|
||||||
* but A-Z, a-z, and 0-9 with underscores. Also disallows
|
static public boolean isSanitary(String name) {
|
||||||
* starting the sketch name with a digit.
|
return sanitizedName(name).equals(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produce a sanitized name that fits our standards for likely to work.
|
||||||
|
* <p/>
|
||||||
|
* Java classes have a wider range of names that are technically allowed
|
||||||
|
* (supposedly any Unicode name) than what we support. The reason for
|
||||||
|
* going more narrow is to avoid situations with text encodings and
|
||||||
|
* converting during the process of moving files between operating
|
||||||
|
* systems, i.e. uploading from a Windows machine to a Linux server,
|
||||||
|
* or reading a FAT32 partition in OS X and using a thumb drive.
|
||||||
|
* <p/>
|
||||||
|
* This helper function replaces everything but A-Z, a-z, and 0-9 with
|
||||||
|
* underscores. Also disallows starting the sketch name with a digit.
|
||||||
*/
|
*/
|
||||||
static public String sanitizedName(String origName) {
|
static public String sanitizedName(String origName) {
|
||||||
char c[] = origName.toCharArray();
|
char c[] = origName.toCharArray();
|
||||||
@ -280,7 +293,12 @@ public class Sketchbook {
|
|||||||
buffer.append('_');
|
buffer.append('_');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// let's not be ridiculous about the length of filenames
|
// let's not be ridiculous about the length of filenames.
|
||||||
|
// in fact, Mac OS 9 can handle 255 chars, though it can't really
|
||||||
|
// deal with filenames longer than 31 chars in the Finder.
|
||||||
|
// but limiting to that for sketches would mean setting the
|
||||||
|
// upper-bound on the character limit here to 25 characters
|
||||||
|
// (to handle the base name + ".class")
|
||||||
if (buffer.length() > 63) {
|
if (buffer.length() > 63) {
|
||||||
buffer.setLength(63);
|
buffer.setLength(63);
|
||||||
}
|
}
|
||||||
@ -290,12 +308,12 @@ public class Sketchbook {
|
|||||||
|
|
||||||
public String handleOpen() {
|
public String handleOpen() {
|
||||||
// swing's file choosers are ass ugly, so we use the
|
// swing's file choosers are ass ugly, so we use the
|
||||||
// native (awt peered) dialogs instead
|
// native (awt peered) dialogs where possible
|
||||||
FileDialog fd = new FileDialog(editor, //new Frame(),
|
FileDialog fd = new FileDialog(editor, //new Frame(),
|
||||||
"Open a Processing sketch...",
|
"Open a Processing sketch...",
|
||||||
FileDialog.LOAD);
|
FileDialog.LOAD);
|
||||||
//fd.setDirectory(Preferences.get("sketchbook.path"));
|
//fd.setDirectory(Preferences.get("sketchbook.path"));
|
||||||
fd.setDirectory(getSketchbookPath());
|
//fd.setDirectory(getSketchbookPath());
|
||||||
|
|
||||||
// only show .pde files as eligible bachelors
|
// only show .pde files as eligible bachelors
|
||||||
// TODO this doesn't seem to ever be used. AWESOME.
|
// TODO this doesn't seem to ever be used. AWESOME.
|
||||||
@ -324,6 +342,23 @@ public class Sketchbook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous version of menu rebuild to be used on 'new' and 'save',
|
||||||
|
* to prevent the interface from locking up until the menus are done.
|
||||||
|
*/
|
||||||
|
public void rebuildMenusAsync() {
|
||||||
|
// disabling the async option for actual release, this hasn't been tested
|
||||||
|
/*
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
rebuildMenus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
rebuildMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuild the menu full of sketches based on the
|
* Rebuild the menu full of sketches based on the
|
||||||
* contents of the sketchbook.
|
* contents of the sketchbook.
|
||||||
@ -333,6 +368,7 @@ public class Sketchbook {
|
|||||||
* the menu will disappear from its original location.
|
* the menu will disappear from its original location.
|
||||||
*/
|
*/
|
||||||
public void rebuildMenus() {
|
public void rebuildMenus() {
|
||||||
|
//EditorConsole.systemOut.println("rebuilding menus");
|
||||||
try {
|
try {
|
||||||
// rebuild file/open and the toolbar popup menus
|
// rebuild file/open and the toolbar popup menus
|
||||||
buildMenu(openMenu);
|
buildMenu(openMenu);
|
||||||
@ -359,6 +395,7 @@ public class Sketchbook {
|
|||||||
"sketchbook menu. Things might get a little\n" +
|
"sketchbook menu. Things might get a little\n" +
|
||||||
"kooky around here.", e);
|
"kooky around here.", e);
|
||||||
}
|
}
|
||||||
|
//EditorConsole.systemOut.println("done rebuilding menus");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -444,25 +481,8 @@ public class Sketchbook {
|
|||||||
if (list == null) return false;
|
if (list == null) return false;
|
||||||
|
|
||||||
// alphabetize list, since it's not always alpha order
|
// alphabetize list, since it's not always alpha order
|
||||||
// use cheapie bubble-style sort which should be fine
|
// replaced hella slow bubble sort with this feller for 0093
|
||||||
// since not a tone of files, and things will mostly be sorted
|
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
|
||||||
// or may be completely sorted already by the os
|
|
||||||
for (int i = 0; i < list.length; i++) {
|
|
||||||
int who = i;
|
|
||||||
for (int j = i+1; j < list.length; j++) {
|
|
||||||
if (list[j].compareToIgnoreCase(list[who]) < 0) {
|
|
||||||
who = j; // this guy is earlier in the alphabet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (who != i) { // swap with someone if changes made
|
|
||||||
String temp = list[who];
|
|
||||||
list[who] = list[i];
|
|
||||||
list[i] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//SketchbookMenuListener listener =
|
|
||||||
//new SketchbookMenuListener(folder.getAbsolutePath());
|
|
||||||
|
|
||||||
ActionListener listener = new ActionListener() {
|
ActionListener listener = new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -477,18 +497,23 @@ public class Sketchbook {
|
|||||||
list[i].equals("CVS")) continue;
|
list[i].equals("CVS")) continue;
|
||||||
|
|
||||||
File subfolder = new File(folder, list[i]);
|
File subfolder = new File(folder, list[i]);
|
||||||
File lib = new File(subfolder, "library");
|
if (!subfolder.isDirectory()) continue;
|
||||||
|
|
||||||
File entry = new File(subfolder, list[i] + ".pde");
|
File entry = new File(subfolder, list[i] + ".pde");
|
||||||
// if a .pde file of the same prefix as the folder exists..
|
// if a .pde file of the same prefix as the folder exists..
|
||||||
if (entry.exists()) {
|
if (entry.exists()) {
|
||||||
String sanityCheck = sanitizedName(list[i]);
|
//String sanityCheck = sanitizedName(list[i]);
|
||||||
if (!sanityCheck.equals(list[i])) {
|
//if (!sanityCheck.equals(list[i])) {
|
||||||
|
if (!Sketchbook.isSanitary(list[i])) {
|
||||||
if (!builtOnce) {
|
if (!builtOnce) {
|
||||||
String mess =
|
String complaining =
|
||||||
"The sketch \"" + list[i] + "\" cannot be used.\n" +
|
"The sketch \"" + list[i] + "\" cannot be used.\n" +
|
||||||
"Sketch names must contain only basic letters and numbers.\n" +
|
"Sketch names must contain only basic letters and numbers\n" +
|
||||||
"(ascii only and no spaces, and it cannot start with a number)";
|
"(ASCII-only with no spaces, " +
|
||||||
Base.showMessage("Ignoring bad sketch name", mess);
|
"and it cannot start with a number).\n" +
|
||||||
|
"To get rid of this message, remove the sketch from\n" +
|
||||||
|
entry.getAbsolutePath();
|
||||||
|
Base.showMessage("Ignoring sketch with bad name", complaining);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -499,7 +524,8 @@ public class Sketchbook {
|
|||||||
menu.add(item);
|
menu.add(item);
|
||||||
ifound = true;
|
ifound = true;
|
||||||
|
|
||||||
} else { // might contain other dirs, get recursive
|
} else {
|
||||||
|
// not a sketch folder, but maybe a subfolder containing sketches
|
||||||
JMenu submenu = new JMenu(list[i]);
|
JMenu submenu = new JMenu(list[i]);
|
||||||
// needs to be separate var
|
// needs to be separate var
|
||||||
// otherwise would set ifound to false
|
// otherwise would set ifound to false
|
||||||
@ -523,22 +549,8 @@ public class Sketchbook {
|
|||||||
if (list == null) return false;
|
if (list == null) return false;
|
||||||
|
|
||||||
// alphabetize list, since it's not always alpha order
|
// alphabetize list, since it's not always alpha order
|
||||||
// use cheapie bubble-style sort which should be fine
|
// replaced hella slow bubble sort with this feller for 0093
|
||||||
// since not a tone of files, and things will mostly be sorted
|
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
|
||||||
// or may be completely sorted already by the os
|
|
||||||
for (int i = 0; i < list.length; i++) {
|
|
||||||
int who = i;
|
|
||||||
for (int j = i+1; j < list.length; j++) {
|
|
||||||
if (list[j].compareToIgnoreCase(list[who]) < 0) {
|
|
||||||
who = j; // this guy is earlier in the alphabet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (who != i) { // swap with someone if changes made
|
|
||||||
String temp = list[who];
|
|
||||||
list[who] = list[i];
|
|
||||||
list[i] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActionListener listener = new ActionListener() {
|
ActionListener listener = new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -591,6 +603,8 @@ public class Sketchbook {
|
|||||||
String packages[] =
|
String packages[] =
|
||||||
Compiler.packageListFromClassPath(libraryClassPath);
|
Compiler.packageListFromClassPath(libraryClassPath);
|
||||||
for (int k = 0; k < packages.length; k++) {
|
for (int k = 0; k < packages.length; k++) {
|
||||||
|
//System.out.println(packages[k] + " -> " + exported);
|
||||||
|
//String already = (String) importToLibraryTable.get(packages[k]);
|
||||||
importToLibraryTable.put(packages[k], exported);
|
importToLibraryTable.put(packages[k], exported);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -600,11 +614,10 @@ public class Sketchbook {
|
|||||||
menu.add(item);
|
menu.add(item);
|
||||||
ifound = true;
|
ifound = true;
|
||||||
|
|
||||||
} else { // might contain other dirs, get recursive
|
} else { // not a library, but is still a folder, so recurse
|
||||||
JMenu submenu = new JMenu(list[i]);
|
JMenu submenu = new JMenu(list[i]);
|
||||||
// needs to be separate var
|
// needs to be separate var, otherwise would set ifound to false
|
||||||
// otherwise would set ifound to false
|
boolean found = addLibraries(submenu, subfolder);
|
||||||
boolean found = addLibraries(submenu, subfolder); //, false);
|
|
||||||
if (found) {
|
if (found) {
|
||||||
menu.add(submenu);
|
menu.add(submenu);
|
||||||
ifound = true;
|
ifound = true;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
package processing.app.preproc;
|
package processing.app.preproc;
|
||||||
|
|
||||||
import processing.app.*;
|
import processing.app.*;
|
||||||
//import processing.core.*;
|
import processing.core.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
@ -99,6 +99,7 @@ public class PdePreprocessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* preprocesses a pde file and write out a java file
|
* preprocesses a pde file and write out a java file
|
||||||
|
* @param pretty true if should also space out/indent lines
|
||||||
* @return the classname of the exported Java
|
* @return the classname of the exported Java
|
||||||
*/
|
*/
|
||||||
//public String write(String program, String buildPath, String name,
|
//public String write(String program, String buildPath, String name,
|
||||||
@ -109,10 +110,19 @@ public class PdePreprocessor {
|
|||||||
throws java.lang.Exception {
|
throws java.lang.Exception {
|
||||||
// if the program ends with no CR or LF an OutOfMemoryError will happen.
|
// 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:
|
// not gonna track down the bug now, so here's a hack for it:
|
||||||
if ((program.length() > 0) &&
|
// bug filed at http://dev.processing.org/bugs/show_bug.cgi?id=5
|
||||||
program.charAt(program.length()-1) != '\n') {
|
//if ((program.length() > 0) &&
|
||||||
|
//program.charAt(program.length()-1) != '\n') {
|
||||||
program += "\n";
|
program += "\n";
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
// if the program ends with an unterminated multiline comment,
|
||||||
|
// 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.
|
||||||
|
|
||||||
if (Preferences.getBoolean("preproc.substitute_unicode")) {
|
if (Preferences.getBoolean("preproc.substitute_unicode")) {
|
||||||
// check for non-ascii chars (these will be/must be in unicode format)
|
// check for non-ascii chars (these will be/must be in unicode format)
|
||||||
@ -193,26 +203,6 @@ public class PdePreprocessor {
|
|||||||
extraImports = new String[imports.size()];
|
extraImports = new String[imports.size()];
|
||||||
imports.copyInto(extraImports);
|
imports.copyInto(extraImports);
|
||||||
|
|
||||||
// if using opengl, add it to the special imports
|
|
||||||
/*
|
|
||||||
if (Preferences.get("renderer").equals("opengl")) {
|
|
||||||
extraImports = new String[imports.size() + 1];
|
|
||||||
imports.copyInto(extraImports);
|
|
||||||
extraImports[extraImports.length - 1] = "processing.opengl.*";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (codeFolderPackages != null) {
|
|
||||||
extraImports = new String[importsCount + codeFolderPackages.length];
|
|
||||||
imports.copyInto(extraImports);
|
|
||||||
for (int i = 0; i < codeFolderPackages.length; i++) {
|
|
||||||
extraImports[importsCount + i] = codeFolderPackages[i] + ".*";
|
|
||||||
}
|
|
||||||
codeFolderImports = null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (codeFolderPackages != null) {
|
if (codeFolderPackages != null) {
|
||||||
codeFolderImports = new String[codeFolderPackages.length];
|
codeFolderImports = new String[codeFolderPackages.length];
|
||||||
for (int i = 0; i < codeFolderPackages.length; i++) {
|
for (int i = 0; i < codeFolderPackages.length; i++) {
|
||||||
|
@ -136,9 +136,10 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
{
|
{
|
||||||
String name = (String)en.nextElement();
|
String name = (String)en.nextElement();
|
||||||
ActionListener _listener = getAction(name);
|
ActionListener _listener = getAction(name);
|
||||||
if(_listener == listener)
|
if(_listener == listener) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +181,6 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
/**
|
/**
|
||||||
* Grabs the next key typed event and invokes the specified
|
* Grabs the next key typed event and invokes the specified
|
||||||
* action with the key as a the action command.
|
* action with the key as a the action command.
|
||||||
* @param action The action
|
|
||||||
*/
|
*/
|
||||||
public void grabNextKeyStroke(ActionListener listener)
|
public void grabNextKeyStroke(ActionListener listener)
|
||||||
{
|
{
|
||||||
@ -743,19 +743,32 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
{
|
{
|
||||||
JEditTextArea textArea = getTextArea(evt);
|
JEditTextArea textArea = getTextArea(evt);
|
||||||
int caret = textArea.getCaretPosition();
|
int caret = textArea.getCaretPosition();
|
||||||
|
|
||||||
if(caret == textArea.getDocumentLength())
|
if(caret == textArea.getDocumentLength())
|
||||||
{
|
{
|
||||||
|
if (textArea.getSelectionStart() !=
|
||||||
|
textArea.getSelectionEnd()) {
|
||||||
|
// just move to the end of the selection
|
||||||
|
textArea.select(caret, caret);
|
||||||
|
} else {
|
||||||
|
// beep at the user for being annoying
|
||||||
textArea.getToolkit().beep();
|
textArea.getToolkit().beep();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(select)
|
} else if (select) {
|
||||||
textArea.select(textArea.getMarkPosition(),
|
textArea.select(textArea.getMarkPosition(), caret+1);
|
||||||
caret + 1);
|
|
||||||
else
|
} else {
|
||||||
|
int start = textArea.getSelectionStart();
|
||||||
|
int end = textArea.getSelectionEnd();
|
||||||
|
if (start != end) {
|
||||||
|
textArea.select(end, end);
|
||||||
|
} else {
|
||||||
textArea.setCaretPosition(caret + 1);
|
textArea.setCaretPosition(caret + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class next_line implements ActionListener
|
public static class next_line implements ActionListener
|
||||||
{
|
{
|
||||||
@ -774,7 +787,13 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
|
|
||||||
if(line == textArea.getLineCount() - 1)
|
if(line == textArea.getLineCount() - 1)
|
||||||
{
|
{
|
||||||
textArea.getToolkit().beep();
|
//textArea.getToolkit().beep();
|
||||||
|
int doc = textArea.getDocumentLength();
|
||||||
|
if (select) {
|
||||||
|
textArea.select(textArea.getMarkPosition(), doc);
|
||||||
|
} else {
|
||||||
|
textArea.setCaretPosition(doc);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,13 +920,19 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(select)
|
if (select) {
|
||||||
textArea.select(textArea.getMarkPosition(),
|
textArea.select(textArea.getMarkPosition(), caret-1);
|
||||||
caret - 1);
|
} else {
|
||||||
else
|
int start = textArea.getSelectionStart();
|
||||||
|
int end = textArea.getSelectionEnd();
|
||||||
|
if (start != end) {
|
||||||
|
textArea.select(start, start);
|
||||||
|
} else {
|
||||||
textArea.setCaretPosition(caret - 1);
|
textArea.setCaretPosition(caret - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class prev_line implements ActionListener
|
public static class prev_line implements ActionListener
|
||||||
{
|
{
|
||||||
@ -926,7 +951,14 @@ public abstract class InputHandler extends KeyAdapter
|
|||||||
|
|
||||||
if(line == 0)
|
if(line == 0)
|
||||||
{
|
{
|
||||||
textArea.getToolkit().beep();
|
if (select) {
|
||||||
|
if (textArea.getSelectionStart() != 0) {
|
||||||
|
textArea.select(textArea.getMarkPosition(), 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
textArea.setCaretPosition(0);
|
||||||
|
}
|
||||||
|
//textArea.getToolkit().beep();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,22 +888,20 @@ public class JEditTextArea extends JComponent
|
|||||||
*/
|
*/
|
||||||
public void setText(String text)
|
public void setText(String text)
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
document.beginCompoundEdit();
|
document.beginCompoundEdit();
|
||||||
document.remove(0,document.getLength());
|
document.remove(0,document.getLength());
|
||||||
document.insertString(0,text,null);
|
document.insertString(0,text,null);
|
||||||
}
|
|
||||||
catch(BadLocationException bl)
|
} catch (BadLocationException bl) {
|
||||||
{
|
|
||||||
bl.printStackTrace();
|
bl.printStackTrace();
|
||||||
}
|
|
||||||
finally
|
} finally {
|
||||||
{
|
|
||||||
document.endCompoundEdit();
|
document.endCompoundEdit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the specified substring of the document.
|
* Returns the specified substring of the document.
|
||||||
* @param start The start offset
|
* @param start The start offset
|
||||||
@ -1502,7 +1500,7 @@ public class JEditTextArea extends JComponent
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if the selection should be rectangular.
|
* Sets if the selection should be rectangular.
|
||||||
* @param overwrite True if the selection should be rectangular,
|
* @param rectSelect True if the selection should be rectangular,
|
||||||
* false otherwise.
|
* false otherwise.
|
||||||
*/
|
*/
|
||||||
public final void setSelectionRectangular(boolean rectSelect)
|
public final void setSelectionRectangular(boolean rectSelect)
|
||||||
@ -1644,6 +1642,7 @@ public class JEditTextArea extends JComponent
|
|||||||
|
|
||||||
switch(evt.getID()) {
|
switch(evt.getID()) {
|
||||||
case KeyEvent.KEY_TYPED:
|
case KeyEvent.KEY_TYPED:
|
||||||
|
//if ((editorListener != null) && !editorListener.keyTyped(evt)) {
|
||||||
inputHandler.keyTyped(evt);
|
inputHandler.keyTyped(evt);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEY_PRESSED:
|
case KeyEvent.KEY_PRESSED:
|
||||||
@ -2145,21 +2144,52 @@ public class JEditTextArea extends JComponent
|
|||||||
bl.printStackTrace();
|
bl.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, it's not a bracket... select the word
|
|
||||||
String lineText = getLineText(line);
|
|
||||||
char ch = lineText.charAt(Math.max(0,offset - 1));
|
|
||||||
|
|
||||||
String noWordSep = (String)document.getProperty("noWordSep");
|
String noWordSep = (String)document.getProperty("noWordSep");
|
||||||
if(noWordSep == null)
|
if(noWordSep == null)
|
||||||
noWordSep = "";
|
noWordSep = "";
|
||||||
|
|
||||||
// If the user clicked on a non-letter char,
|
// Ok, it's not a bracket... select the word
|
||||||
// we select the surrounding non-letters
|
String lineText = getLineText(line);
|
||||||
boolean selectNoLetter = (!Character
|
|
||||||
.isLetterOrDigit(ch)
|
|
||||||
&& noWordSep.indexOf(ch) == -1);
|
|
||||||
|
|
||||||
int wordStart = 0;
|
int wordStart = 0;
|
||||||
|
int wordEnd = lineText.length();
|
||||||
|
|
||||||
|
char ch = lineText.charAt(Math.max(0,offset - 1));
|
||||||
|
|
||||||
|
// special case for whitespace (fry 0122, bug #348)
|
||||||
|
// this is really nasty.. turns out that double-clicking any non-letter
|
||||||
|
// or digit char gets lumped together.. sooo, this quickly gets messy,
|
||||||
|
// because really it needs to check whether the chars are of the same
|
||||||
|
// type.. so a double space or double - might be grouped together,
|
||||||
|
// but what about a +=1? do + and - get grouped but not the 1? blech,
|
||||||
|
// coming back to this later. it's not a difficult fix, just a
|
||||||
|
// time-consuming one to track down all the proper cases.
|
||||||
|
/*
|
||||||
|
if (ch == ' ') {
|
||||||
|
//System.out.println("yeehaa");
|
||||||
|
|
||||||
|
for(int i = offset - 1; i >= 0; i--) {
|
||||||
|
if (lineText.charAt(i) == ' ') {
|
||||||
|
wordStart = i;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = offset; i < lineText.length(); i++) {
|
||||||
|
if (lineText.charAt(i) == ' ') {
|
||||||
|
wordEnd = i + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If the user clicked on a non-letter char,
|
||||||
|
// we select the surrounding non-letters
|
||||||
|
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
|
||||||
|
&& noWordSep.indexOf(ch) == -1);
|
||||||
|
|
||||||
for(int i = offset - 1; i >= 0; i--) {
|
for(int i = offset - 1; i >= 0; i--) {
|
||||||
ch = lineText.charAt(i);
|
ch = lineText.charAt(i);
|
||||||
@ -2170,18 +2200,15 @@ public class JEditTextArea extends JComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int wordEnd = lineText.length();
|
for(int i = offset; i < lineText.length(); i++) {
|
||||||
for(int i = offset; i < lineText.length(); i++)
|
|
||||||
{
|
|
||||||
ch = lineText.charAt(i);
|
ch = lineText.charAt(i);
|
||||||
if(selectNoLetter ^ (!Character
|
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
|
||||||
.isLetterOrDigit(ch) &&
|
noWordSep.indexOf(ch) == -1)) {
|
||||||
noWordSep.indexOf(ch) == -1))
|
|
||||||
{
|
|
||||||
wordEnd = i;
|
wordEnd = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
int lineStart = getLineStartOffset(line);
|
int lineStart = getLineStartOffset(line);
|
||||||
select(lineStart + wordStart,lineStart + wordEnd);
|
select(lineStart + wordStart,lineStart + wordEnd);
|
||||||
|
@ -76,7 +76,7 @@ public class KeywordMap
|
|||||||
/**
|
/**
|
||||||
* Adds a key-value mapping.
|
* Adds a key-value mapping.
|
||||||
* @param keyword The key
|
* @param keyword The key
|
||||||
* @Param id The value
|
* @param id The value
|
||||||
*/
|
*/
|
||||||
public void add(String keyword, byte id)
|
public void add(String keyword, byte id)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +76,7 @@ public class PdeKeywords extends CTokenMarker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String pieces[] = Base.split(line, '\t');
|
String pieces[] = processing.core.PApplet.split(line, '\t');
|
||||||
if (pieces.length >= 2) {
|
if (pieces.length >= 2) {
|
||||||
//int tab = line.indexOf('\t');
|
//int tab = line.indexOf('\t');
|
||||||
// any line with no tab is ignored
|
// any line with no tab is ignored
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
PdeTextAreaDefaults - grabs font/color settings for the editor
|
PdeTextAreaDefaults - grabs font/color settings for the editor
|
||||||
Part of the Processing project - http://Proce55ing.net
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
Except where noted, code is written by Ben Fry
|
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||||
Copyright (c) 2001-03 Massachusetts Institute of Technology
|
Copyright (c) 2001-03 Massachusetts Institute of Technology
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -32,41 +32,65 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
|||||||
public PdeTextAreaDefaults() {
|
public PdeTextAreaDefaults() {
|
||||||
|
|
||||||
inputHandler = new DefaultInputHandler();
|
inputHandler = new DefaultInputHandler();
|
||||||
inputHandler.addDefaultKeyBindings();
|
//inputHandler.addDefaultKeyBindings(); // 0122
|
||||||
|
|
||||||
// use option on mac for things that are ctrl on windows/linux
|
// use option on mac for things that are ctrl on windows/linux
|
||||||
String mod = Base.isMacOS() ? "A" : "C";
|
String mod = Base.isMacOS() ? "A" : "C";
|
||||||
|
|
||||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
// right now, ctrl-up/down is select up/down, but mod should be
|
||||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
|
// used instead, because the mac expects it to be option(alt)
|
||||||
|
|
||||||
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
|
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
|
||||||
inputHandler.addKeyBinding("C+BACK_SPACE", InputHandler.BACKSPACE_WORD);
|
|
||||||
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
|
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
|
||||||
inputHandler.addKeyBinding("C+DELETE", InputHandler.DELETE_WORD);
|
|
||||||
|
|
||||||
inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
|
//inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||||
inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
|
// 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
|
||||||
|
inputHandler.addKeyBinding(mod+"+BACK_SPACE", InputHandler.BACKSPACE_WORD);
|
||||||
|
inputHandler.addKeyBinding(mod+"+DELETE", InputHandler.DELETE_WORD);
|
||||||
|
|
||||||
|
// handled by listener, don't bother here
|
||||||
|
//inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
|
||||||
|
//inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
|
||||||
|
|
||||||
inputHandler.addKeyBinding("INSERT", InputHandler.OVERWRITE);
|
inputHandler.addKeyBinding("INSERT", InputHandler.OVERWRITE);
|
||||||
inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
|
// disabling for 0122, not sure what this does
|
||||||
|
//inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
|
||||||
|
|
||||||
// beginning and ending of the current line
|
// for 0122, these have been changed for better compatability
|
||||||
|
// HOME and END now mean the beginning/end of the document
|
||||||
|
if (Base.isMacOS()) {
|
||||||
|
inputHandler.addKeyBinding("HOME", InputHandler.DOCUMENT_HOME);
|
||||||
|
inputHandler.addKeyBinding("END", InputHandler.DOCUMENT_END);
|
||||||
|
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_DOC_HOME);
|
||||||
|
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_DOC_END);
|
||||||
|
} else {
|
||||||
|
// for 0123 added the proper windows defaults
|
||||||
inputHandler.addKeyBinding("HOME", InputHandler.HOME);
|
inputHandler.addKeyBinding("HOME", InputHandler.HOME);
|
||||||
inputHandler.addKeyBinding("END", InputHandler.END);
|
inputHandler.addKeyBinding("END", InputHandler.END);
|
||||||
|
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_HOME);
|
||||||
|
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_END);
|
||||||
|
inputHandler.addKeyBinding("C+HOME", InputHandler.DOCUMENT_HOME);
|
||||||
|
inputHandler.addKeyBinding("C+END", InputHandler.DOCUMENT_END);
|
||||||
|
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_DOC_HOME);
|
||||||
|
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_DOC_END);
|
||||||
|
}
|
||||||
|
|
||||||
if (Base.isMacOS()) {
|
if (Base.isMacOS()) {
|
||||||
inputHandler.addKeyBinding("M+LEFT", InputHandler.HOME);
|
inputHandler.addKeyBinding("M+LEFT", InputHandler.HOME);
|
||||||
inputHandler.addKeyBinding("M+RIGHT", InputHandler.END);
|
inputHandler.addKeyBinding("M+RIGHT", InputHandler.END);
|
||||||
|
inputHandler.addKeyBinding("MS+LEFT", InputHandler.SELECT_HOME); // 0122
|
||||||
|
inputHandler.addKeyBinding("MS+RIGHT", InputHandler.SELECT_END); // 0122
|
||||||
|
} else {
|
||||||
|
inputHandler.addKeyBinding("C+LEFT", InputHandler.HOME); // 0122
|
||||||
|
inputHandler.addKeyBinding("C+RIGHT", InputHandler.END); // 0122
|
||||||
|
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_HOME); // 0122
|
||||||
|
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_END); // 0122
|
||||||
}
|
}
|
||||||
|
|
||||||
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_HOME);
|
|
||||||
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_END);
|
|
||||||
inputHandler.addKeyBinding(mod + "+HOME", InputHandler.DOCUMENT_HOME);
|
|
||||||
inputHandler.addKeyBinding(mod + "+END", InputHandler.DOCUMENT_END);
|
|
||||||
inputHandler.addKeyBinding(mod + "S+HOME", InputHandler.SELECT_DOC_HOME);
|
|
||||||
inputHandler.addKeyBinding(mod + "S+END", InputHandler.SELECT_DOC_END);
|
|
||||||
|
|
||||||
inputHandler.addKeyBinding("PAGE_UP", InputHandler.PREV_PAGE);
|
inputHandler.addKeyBinding("PAGE_UP", InputHandler.PREV_PAGE);
|
||||||
inputHandler.addKeyBinding("PAGE_DOWN", InputHandler.NEXT_PAGE);
|
inputHandler.addKeyBinding("PAGE_DOWN", InputHandler.NEXT_PAGE);
|
||||||
inputHandler.addKeyBinding("S+PAGE_UP", InputHandler.SELECT_PREV_PAGE);
|
inputHandler.addKeyBinding("S+PAGE_UP", InputHandler.SELECT_PREV_PAGE);
|
||||||
@ -80,6 +104,7 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
|||||||
inputHandler.addKeyBinding("S+RIGHT", InputHandler.SELECT_NEXT_CHAR);
|
inputHandler.addKeyBinding("S+RIGHT", InputHandler.SELECT_NEXT_CHAR);
|
||||||
inputHandler.addKeyBinding(mod + "+RIGHT", InputHandler.NEXT_WORD);
|
inputHandler.addKeyBinding(mod + "+RIGHT", InputHandler.NEXT_WORD);
|
||||||
inputHandler.addKeyBinding(mod + "S+RIGHT", InputHandler.SELECT_NEXT_WORD);
|
inputHandler.addKeyBinding(mod + "S+RIGHT", InputHandler.SELECT_NEXT_WORD);
|
||||||
|
|
||||||
inputHandler.addKeyBinding("UP", InputHandler.PREV_LINE);
|
inputHandler.addKeyBinding("UP", InputHandler.PREV_LINE);
|
||||||
inputHandler.addKeyBinding(mod + "+UP", InputHandler.PREV_LINE); // p5
|
inputHandler.addKeyBinding(mod + "+UP", InputHandler.PREV_LINE); // p5
|
||||||
inputHandler.addKeyBinding("S+UP", InputHandler.SELECT_PREV_LINE);
|
inputHandler.addKeyBinding("S+UP", InputHandler.SELECT_PREV_LINE);
|
||||||
@ -87,6 +112,11 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
|||||||
inputHandler.addKeyBinding(mod + "+DOWN", InputHandler.NEXT_LINE); // p5
|
inputHandler.addKeyBinding(mod + "+DOWN", InputHandler.NEXT_LINE); // p5
|
||||||
inputHandler.addKeyBinding("S+DOWN", InputHandler.SELECT_NEXT_LINE);
|
inputHandler.addKeyBinding("S+DOWN", InputHandler.SELECT_NEXT_LINE);
|
||||||
|
|
||||||
|
inputHandler.addKeyBinding("MS+UP", InputHandler.SELECT_DOC_HOME);
|
||||||
|
inputHandler.addKeyBinding("CS+UP", InputHandler.SELECT_DOC_HOME);
|
||||||
|
inputHandler.addKeyBinding("MS+DOWN", InputHandler.SELECT_DOC_END);
|
||||||
|
inputHandler.addKeyBinding("CS+DOWN", InputHandler.SELECT_DOC_END);
|
||||||
|
|
||||||
inputHandler.addKeyBinding(mod + "+ENTER", InputHandler.REPEAT);
|
inputHandler.addKeyBinding(mod + "+ENTER", InputHandler.REPEAT);
|
||||||
|
|
||||||
document = new SyntaxDocument();
|
document = new SyntaxDocument();
|
||||||
|
@ -18,6 +18,7 @@ import javax.swing.text.*;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.print.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text area repaint manager. It performs double buffering and paints
|
* The text area repaint manager. It performs double buffering and paints
|
||||||
@ -25,8 +26,12 @@ import java.awt.*;
|
|||||||
* @author Slava Pestov
|
* @author Slava Pestov
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class TextAreaPainter extends JComponent implements TabExpander
|
public class TextAreaPainter extends JComponent
|
||||||
|
implements TabExpander, Printable
|
||||||
{
|
{
|
||||||
|
/** True if inside printing, will handle disabling the highlight */
|
||||||
|
boolean printing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new repaint manager. This should be not be called
|
* Creates a new repaint manager. This should be not be called
|
||||||
* directly.
|
* directly.
|
||||||
@ -405,6 +410,32 @@ public class TextAreaPainter extends JComponent implements TabExpander
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
|
||||||
|
int lineHeight = fm.getHeight();
|
||||||
|
int linesPerPage = (int) (pageFormat.getImageableHeight() / lineHeight);
|
||||||
|
int lineCount = textArea.getLineCount();
|
||||||
|
int lastPage = lineCount / linesPerPage;
|
||||||
|
|
||||||
|
if (pageIndex > lastPage) {
|
||||||
|
return NO_SUCH_PAGE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Graphics2D g2d = (Graphics2D)g;
|
||||||
|
TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
|
||||||
|
int firstLine = pageIndex*linesPerPage;
|
||||||
|
g2d.translate(Math.max(54, pageFormat.getImageableX()),
|
||||||
|
pageFormat.getImageableY() - firstLine*lineHeight);
|
||||||
|
printing = true;
|
||||||
|
for (int line = firstLine; line < firstLine + linesPerPage; line++) {
|
||||||
|
paintLine(g2d, tokenMarker, line, 0);
|
||||||
|
}
|
||||||
|
printing = false;
|
||||||
|
return PAGE_EXISTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a line as needing a repaint.
|
* Marks a line as needing a repaint.
|
||||||
* @param line The line to invalidate
|
* @param line The line to invalidate
|
||||||
@ -600,6 +631,7 @@ public class TextAreaPainter extends JComponent implements TabExpander
|
|||||||
|
|
||||||
protected void paintHighlight(Graphics gfx, int line, int y)
|
protected void paintHighlight(Graphics gfx, int line, int y)
|
||||||
{
|
{
|
||||||
|
if (!printing) {
|
||||||
if (line >= textArea.getSelectionStartLine()
|
if (line >= textArea.getSelectionStartLine()
|
||||||
&& line <= textArea.getSelectionEndLine())
|
&& line <= textArea.getSelectionEndLine())
|
||||||
paintLineHighlight(gfx,line,y);
|
paintLineHighlight(gfx,line,y);
|
||||||
@ -613,6 +645,7 @@ public class TextAreaPainter extends JComponent implements TabExpander
|
|||||||
if (line == textArea.getCaretLine())
|
if (line == textArea.getCaretLine())
|
||||||
paintCaret(gfx,line,y);
|
paintCaret(gfx,line,y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void paintLineHighlight(Graphics gfx, int line, int y)
|
protected void paintLineHighlight(Graphics gfx, int line, int y)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ package processing.app.tools;
|
|||||||
|
|
||||||
import processing.app.*;
|
import processing.app.*;
|
||||||
|
|
||||||
|
import java.awt.FileDialog;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -35,7 +36,7 @@ public class Archiver {
|
|||||||
Editor editor;
|
Editor editor;
|
||||||
|
|
||||||
// someday these will be settable
|
// someday these will be settable
|
||||||
boolean useDate = true; //false;
|
boolean useDate;
|
||||||
int digits = 3;
|
int digits = 3;
|
||||||
|
|
||||||
NumberFormat numberFormat;
|
NumberFormat numberFormat;
|
||||||
@ -79,6 +80,9 @@ public class Archiver {
|
|||||||
String namely = null;
|
String namely = null;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
do {
|
do {
|
||||||
|
// only use the date if the sketch name isn't the default name
|
||||||
|
useDate = !name.startsWith("sketch_");
|
||||||
|
|
||||||
if (useDate) {
|
if (useDate) {
|
||||||
String purty = dateFormat.format(new Date());
|
String purty = dateFormat.format(new Date());
|
||||||
String stamp = purty + ((char) ('a' + index));
|
String stamp = purty + ((char) ('a' + index));
|
||||||
@ -93,6 +97,20 @@ public class Archiver {
|
|||||||
index++;
|
index++;
|
||||||
} while (newbie.exists());
|
} while (newbie.exists());
|
||||||
|
|
||||||
|
// open up a prompt for where to save this fella
|
||||||
|
FileDialog fd =
|
||||||
|
new FileDialog(editor, "Archive sketch as:", FileDialog.SAVE);
|
||||||
|
fd.setDirectory(parent.getAbsolutePath());
|
||||||
|
fd.setFile(newbie.getName());
|
||||||
|
fd.show();
|
||||||
|
|
||||||
|
String directory = fd.getDirectory();
|
||||||
|
String filename = fd.getFile();
|
||||||
|
|
||||||
|
// only write the file if not canceled
|
||||||
|
if (filename != null) {
|
||||||
|
newbie = new File(directory, filename);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//System.out.println(newbie);
|
//System.out.println(newbie);
|
||||||
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
|
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
|
||||||
@ -110,6 +128,9 @@ public class Archiver {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
editor.message("Archive sketch canceled.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
package processing.app.tools;
|
package processing.app.tools;
|
||||||
|
|
||||||
import processing.app.*;
|
import processing.app.*;
|
||||||
//import processing.core.*;
|
import processing.core.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -915,26 +915,25 @@ public class AutoFormat {
|
|||||||
if (formattedText.equals(originalText)) {
|
if (formattedText.equals(originalText)) {
|
||||||
editor.message("No changes necessary for Auto Format.");
|
editor.message("No changes necessary for Auto Format.");
|
||||||
|
|
||||||
} else {
|
} else if (paren != 0) {
|
||||||
// replace with new bootiful text
|
|
||||||
// selectionEnd hopefully at least in the neighborhood
|
|
||||||
editor.setText(formattedText, selectionEnd, selectionEnd);
|
|
||||||
editor.sketch.setModified(true);
|
|
||||||
|
|
||||||
// warn user if there are too many parens in either direction
|
// warn user if there are too many parens in either direction
|
||||||
if (paren != 0) {
|
editor.error("Auto Format Canceled: Too many " +
|
||||||
editor.error("Warning: Too many " +
|
|
||||||
((paren < 0) ? "right" : "left") +
|
((paren < 0) ? "right" : "left") +
|
||||||
" parentheses.");
|
" parentheses.");
|
||||||
|
|
||||||
} else if (c_level != 0) { // check braces only if parens are ok
|
} else if (c_level != 0) { // check braces only if parens are ok
|
||||||
editor.error("Warning: Too many " +
|
editor.error("Auto Format Canceled: Too many " +
|
||||||
((c_level < 0) ? "right" : "left") +
|
((c_level < 0) ? "right" : "left") +
|
||||||
" curly braces.");
|
" curly braces.");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// replace with new bootiful text
|
||||||
|
// selectionEnd hopefully at least in the neighborhood
|
||||||
|
editor.setText(formattedText, selectionEnd, selectionEnd);
|
||||||
|
editor.sketch.setModified(true);
|
||||||
|
// mark as finished
|
||||||
editor.message("Auto Format finished.");
|
editor.message("Auto Format finished.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
editor.error(e);
|
editor.error(e);
|
||||||
|
313
app/tools/DiscourseFormat.java
Normal file
313
app/tools/DiscourseFormat.java
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
|
Copyright (c) 2005-06 Ignacio Manuel Gonz<6E>lez Moreta
|
||||||
|
Copyright (c) 2006 Ben Fry and Casey Reas
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.app.tools;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.datatransfer.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.text.Segment;
|
||||||
|
|
||||||
|
import processing.app.*;
|
||||||
|
import processing.app.syntax.*;
|
||||||
|
import processing.core.PApplet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format for Discourse Tool
|
||||||
|
* <p/>
|
||||||
|
* Original code by <A HREF="http://usuarios.iponet.es/imoreta">owd</A>.
|
||||||
|
* Revised and updated for revision 0108 by Ben Fry (10 March 2006).
|
||||||
|
* This code will later be removed but is included with release 0108+
|
||||||
|
* while features for the "Tools" menu are in testing.
|
||||||
|
* <p/>
|
||||||
|
* Updated for 0122 to simply copy the code directly to the clipboard,
|
||||||
|
* rather than opening a new window.
|
||||||
|
* <p/>
|
||||||
|
* Notes from the original source:
|
||||||
|
* Discourse.java This is a dirty-mix source.
|
||||||
|
* NOTE that: No macs and no keyboard. Unreliable source.
|
||||||
|
* Only format processing code using fontMetrics.
|
||||||
|
* It works under my windows XP + PentiumIV + Processing 0091.
|
||||||
|
*/
|
||||||
|
public class DiscourseFormat {
|
||||||
|
|
||||||
|
//static final String WINDOW_TITLE = "Format for Discourse by owd";
|
||||||
|
|
||||||
|
// p5 icon for the window
|
||||||
|
//static Image icon;
|
||||||
|
|
||||||
|
Editor editor;
|
||||||
|
//JEditTextArea textarea;
|
||||||
|
|
||||||
|
// JTextArea of the actual Editor
|
||||||
|
JEditTextArea parent;
|
||||||
|
|
||||||
|
//JFrame frame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new window with the formated (YaBB tags) sketchcode
|
||||||
|
* from the actual Processing Tab ready to send to the processing discourse
|
||||||
|
* web (copy & paste)
|
||||||
|
*/
|
||||||
|
public DiscourseFormat(Editor editor) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.parent = editor.textarea;
|
||||||
|
|
||||||
|
/*
|
||||||
|
textarea = new JEditTextArea(new PdeTextAreaDefaults());
|
||||||
|
textarea.setRightClickPopup(new DiscourseTextAreaPopup());
|
||||||
|
textarea.setTokenMarker(new PdeKeywords());
|
||||||
|
textarea.setHorizontalOffset(6);
|
||||||
|
|
||||||
|
textarea.setEditable(false);
|
||||||
|
|
||||||
|
// Create and set up the window.
|
||||||
|
frame = new JFrame(WINDOW_TITLE);
|
||||||
|
frame.setSize(500, 500);
|
||||||
|
|
||||||
|
// set the window icon
|
||||||
|
try {
|
||||||
|
icon = Base.getImage("icon.gif", frame);
|
||||||
|
frame.setIconImage(icon);
|
||||||
|
} catch (Exception e) { } // fail silently, no big whup
|
||||||
|
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
|
||||||
|
Container pain = frame.getContentPane();
|
||||||
|
pain.setLayout(new BorderLayout());
|
||||||
|
pain.add(textarea, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
frame.setResizable(true);
|
||||||
|
|
||||||
|
frame.pack();
|
||||||
|
frame.setLocation(100, 100);
|
||||||
|
//frame.setVisible(true);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
// Format and render sketchcode
|
||||||
|
|
||||||
|
// [code] tag cancels other tags, using [quote]
|
||||||
|
StringBuffer cf = new StringBuffer("[quote] \n \n");
|
||||||
|
|
||||||
|
// Line by line
|
||||||
|
for (int i = 0; i < parent.getLineCount(); i++) {
|
||||||
|
cf.append(formatCode(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
cf.append("\n [/quote]");
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Send the text to the textarea
|
||||||
|
textarea.setText(cf.toString());
|
||||||
|
textarea.select(0, 0);
|
||||||
|
|
||||||
|
frame.show();
|
||||||
|
*/
|
||||||
|
|
||||||
|
StringSelection formatted = new StringSelection(cf.toString());
|
||||||
|
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||||
|
clipboard.setContents(formatted, new ClipboardOwner() {
|
||||||
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||||
|
// i don't care about ownership
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.message("Discourse-formatted code has been " +
|
||||||
|
"copied to the clipboard.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A terrible headache...
|
||||||
|
public String formatCode(int line) {
|
||||||
|
StringBuffer cf = new StringBuffer();
|
||||||
|
|
||||||
|
// Segment
|
||||||
|
Segment lineSegment = new Segment();
|
||||||
|
|
||||||
|
TextAreaPainter painter = parent.getPainter();
|
||||||
|
TokenMarker tokenMarker = parent.getTokenMarker();
|
||||||
|
|
||||||
|
// Use painter's cached info for speed
|
||||||
|
FontMetrics fm = painter.getFontMetrics();
|
||||||
|
|
||||||
|
// get line text from parent textarea
|
||||||
|
parent.getLineText(line, lineSegment);
|
||||||
|
|
||||||
|
char[] segmentArray = lineSegment.array;
|
||||||
|
int limit = lineSegment.getEndIndex();
|
||||||
|
int segmentOffset = lineSegment.offset;
|
||||||
|
int segmentCount = lineSegment.count;
|
||||||
|
int width = 0; //parent.getHorizontalOffset();
|
||||||
|
|
||||||
|
int x = 0; //parent.getHorizontalOffset();
|
||||||
|
|
||||||
|
// If syntax coloring is disabled, do simple translation
|
||||||
|
if (tokenMarker == null) {
|
||||||
|
for (int j = 0; j < segmentCount; j++) {
|
||||||
|
char c = segmentArray[j + segmentOffset];
|
||||||
|
cf = cf.append(c); //concat(character(c));
|
||||||
|
int charWidth;
|
||||||
|
if (c == '\t') {
|
||||||
|
charWidth = (int) painter.nextTabStop(width, j) - width;
|
||||||
|
} else {
|
||||||
|
charWidth = fm.charWidth(c);
|
||||||
|
}
|
||||||
|
width += charWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If syntax coloring is enabled, we have to do this
|
||||||
|
// because tokens can vary in width
|
||||||
|
Token tokens;
|
||||||
|
if ((painter.getCurrentLineIndex() == line) &&
|
||||||
|
(painter.getCurrentLineTokens() != null)) {
|
||||||
|
tokens = painter.getCurrentLineTokens();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
painter.setCurrentLineIndex(line);
|
||||||
|
//painter.currentLineIndex = line;
|
||||||
|
painter.setCurrentLineTokens(tokenMarker.markTokens(lineSegment, line));
|
||||||
|
tokens = painter.getCurrentLineTokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
Toolkit toolkit = painter.getToolkit();
|
||||||
|
Font defaultFont = painter.getFont();
|
||||||
|
SyntaxStyle[] styles = painter.getStyles();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
byte id = tokens.id;
|
||||||
|
if (id == Token.END) {
|
||||||
|
char c = segmentArray[segmentOffset + offset];
|
||||||
|
if (segmentOffset + offset < limit) {
|
||||||
|
cf.append(c);
|
||||||
|
} else {
|
||||||
|
cf.append('\n');
|
||||||
|
}
|
||||||
|
return cf.toString();
|
||||||
|
}
|
||||||
|
if (id == Token.NULL) {
|
||||||
|
fm = painter.getFontMetrics();
|
||||||
|
} else {
|
||||||
|
// Place open tags []
|
||||||
|
//cf.append("[color=" + color() + "]");
|
||||||
|
cf.append("[color=#");
|
||||||
|
cf.append(PApplet.hex(styles[id].getColor().getRGB() & 0xFFFFFF, 6));
|
||||||
|
cf.append("]");
|
||||||
|
|
||||||
|
if (styles[id].isBold())
|
||||||
|
cf.append("[b]");
|
||||||
|
|
||||||
|
fm = styles[id].getFontMetrics(defaultFont);
|
||||||
|
}
|
||||||
|
int length = tokens.length;
|
||||||
|
|
||||||
|
for (int j = 0; j < length; j++) {
|
||||||
|
char c = segmentArray[segmentOffset + offset + j];
|
||||||
|
cf.append(c);
|
||||||
|
// Place close tags [/]
|
||||||
|
if (j == (length - 1) && id != Token.NULL && styles[id].isBold())
|
||||||
|
cf.append("[/b]");
|
||||||
|
if (j == (length - 1) && id != Token.NULL)
|
||||||
|
cf.append("[/color]");
|
||||||
|
int charWidth;
|
||||||
|
if (c == '\t') {
|
||||||
|
charWidth = (int) painter
|
||||||
|
.nextTabStop(width, offset + j)
|
||||||
|
- width;
|
||||||
|
} else {
|
||||||
|
charWidth = fm.charWidth(c);
|
||||||
|
}
|
||||||
|
width += charWidth;
|
||||||
|
}
|
||||||
|
offset += length;
|
||||||
|
tokens = tokens.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the discourse popup menu. Another features can be added: format
|
||||||
|
* selected text with a determinated tag (I'm thinking about [url]selected
|
||||||
|
* text[/url])
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
class DiscourseTextAreaPopup extends JPopupMenu {
|
||||||
|
JMenuItem copyItem;
|
||||||
|
|
||||||
|
public DiscourseTextAreaPopup() {
|
||||||
|
JMenuItem item;
|
||||||
|
|
||||||
|
copyItem = new JMenuItem("Copy");
|
||||||
|
copyItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
textarea.copy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add(copyItem);
|
||||||
|
|
||||||
|
item = new JMenuItem("Select All");
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
textarea.selectAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no text is selected, disable copy menu item
|
||||||
|
public void show(Component component, int x, int y) {
|
||||||
|
if (textarea.isSelectionActive()) {
|
||||||
|
copyItem.setEnabled(true);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
copyItem.setEnabled(false);
|
||||||
|
}
|
||||||
|
super.show(component, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// A false listener (use the mouse)
|
||||||
|
public class DiscourseListener {
|
||||||
|
|
||||||
|
public DiscourseListener(JEditTextArea thisTextarea) {
|
||||||
|
// I'm a... I know this gives peoblems, but all this code
|
||||||
|
// is a funny hacking experiment
|
||||||
|
thisTextarea.editorListener = parent.editorListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean keyPressed(KeyEvent event) {
|
||||||
|
System.out.println("Is your mouse lone some tonight...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -99,6 +99,8 @@ public class ExportFolder {
|
|||||||
// skip .DS_Store files, etc
|
// skip .DS_Store files, etc
|
||||||
if (!folder.isDirectory()) return; // false;
|
if (!folder.isDirectory()) return; // false;
|
||||||
|
|
||||||
|
System.out.println(folder.getAbsolutePath());
|
||||||
|
|
||||||
String list[] = folder.list();
|
String list[] = folder.list();
|
||||||
// if a bad folder or something like that, this might come back null
|
// if a bad folder or something like that, this might come back null
|
||||||
if (list == null) return; // false;
|
if (list == null) return; // false;
|
||||||
|
@ -151,6 +151,7 @@
|
|||||||
<string>$JAVAROOT/mrj.jar</string>
|
<string>$JAVAROOT/mrj.jar</string>
|
||||||
<string>$JAVAROOT/registry.jar</string>
|
<string>$JAVAROOT/registry.jar</string>
|
||||||
<string>$JAVAROOT/RXTXcomm.jar</string>
|
<string>$JAVAROOT/RXTXcomm.jar</string>
|
||||||
|
<string>$JAVAROOT/quaqua.jar</string>
|
||||||
</array>
|
</array>
|
||||||
<key>JVMVersion</key>
|
<key>JVMVersion</key>
|
||||||
<string>1.4+</string>
|
<string>1.4+</string>
|
||||||
@ -170,6 +171,22 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */ = {isa = PBXBuildFile; fileRef = 332D4DB509CF147F00BF81F6 /* Sizer.java */; };
|
332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */ = {isa = PBXBuildFile; fileRef = 332D4DB509CF147F00BF81F6 /* Sizer.java */; };
|
||||||
|
335A28F50C8CCB0A00D8A7F4 /* quaqua.jar in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335A28F30C8CCAF700D8A7F4 /* quaqua.jar */; };
|
||||||
|
335A28FE0C8CCB4000D8A7F4 /* libquaqua.jnilib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335A28F20C8CCAF700D8A7F4 /* libquaqua.jnilib */; };
|
||||||
|
335A29140C8CCC0900D8A7F4 /* PApplet.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29070C8CCC0900D8A7F4 /* PApplet.java */; };
|
||||||
|
335A29150C8CCC0900D8A7F4 /* PConstants.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29080C8CCC0900D8A7F4 /* PConstants.java */; };
|
||||||
|
335A29160C8CCC0900D8A7F4 /* PFont.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29090C8CCC0900D8A7F4 /* PFont.java */; };
|
||||||
|
335A29170C8CCC0900D8A7F4 /* PGraphics.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290A0C8CCC0900D8A7F4 /* PGraphics.java */; };
|
||||||
|
335A29180C8CCC0900D8A7F4 /* PGraphics2D.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290B0C8CCC0900D8A7F4 /* PGraphics2D.java */; };
|
||||||
|
335A29190C8CCC0900D8A7F4 /* PGraphics3D.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290C0C8CCC0900D8A7F4 /* PGraphics3D.java */; };
|
||||||
|
335A291A0C8CCC0900D8A7F4 /* PGraphicsJava2D.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290D0C8CCC0900D8A7F4 /* PGraphicsJava2D.java */; };
|
||||||
|
335A291B0C8CCC0900D8A7F4 /* PImage.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290E0C8CCC0900D8A7F4 /* PImage.java */; };
|
||||||
|
335A291C0C8CCC0900D8A7F4 /* PLine.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A290F0C8CCC0900D8A7F4 /* PLine.java */; };
|
||||||
|
335A291D0C8CCC0900D8A7F4 /* PMatrix.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29100C8CCC0900D8A7F4 /* PMatrix.java */; };
|
||||||
|
335A291E0C8CCC0900D8A7F4 /* PPolygon.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29110C8CCC0900D8A7F4 /* PPolygon.java */; };
|
||||||
|
335A291F0C8CCC0900D8A7F4 /* PShape.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29120C8CCC0900D8A7F4 /* PShape.java */; };
|
||||||
|
335A29200C8CCC0900D8A7F4 /* PTriangle.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29130C8CCC0900D8A7F4 /* PTriangle.java */; };
|
||||||
|
335A29240C8CCC5E00D8A7F4 /* DiscourseFormat.java in Sources */ = {isa = PBXBuildFile; fileRef = 335A29230C8CCC5E00D8A7F4 /* DiscourseFormat.java */; };
|
||||||
335D3B010C4EE1B80065B27E /* ATmegaBOOT_168.c in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFD0C4EE19D0065B27E /* ATmegaBOOT_168.c */; };
|
335D3B010C4EE1B80065B27E /* ATmegaBOOT_168.c in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFD0C4EE19D0065B27E /* ATmegaBOOT_168.c */; };
|
||||||
335D3B020C4EE1B80065B27E /* ATmegaBOOT_168_diecimila.hex in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFE0C4EE19D0065B27E /* ATmegaBOOT_168_diecimila.hex */; };
|
335D3B020C4EE1B80065B27E /* ATmegaBOOT_168_diecimila.hex in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFE0C4EE19D0065B27E /* ATmegaBOOT_168_diecimila.hex */; };
|
||||||
335D3B030C4EE1B80065B27E /* ATmegaBOOT_168_ng.hex in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFF0C4EE19D0065B27E /* ATmegaBOOT_168_ng.hex */; };
|
335D3B030C4EE1B80065B27E /* ATmegaBOOT_168_ng.hex in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335D3AFF0C4EE19D0065B27E /* ATmegaBOOT_168_ng.hex */; };
|
||||||
@ -363,6 +380,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 15;
|
dstSubfolderSpec = 15;
|
||||||
files = (
|
files = (
|
||||||
|
335A28F50C8CCB0A00D8A7F4 /* quaqua.jar in CopyFiles */,
|
||||||
33CF03CC09662DC000F2C9A9 /* mrj.jar in CopyFiles */,
|
33CF03CC09662DC000F2C9A9 /* mrj.jar in CopyFiles */,
|
||||||
33CF03CD09662DC000F2C9A9 /* RXTXcomm.jar in CopyFiles */,
|
33CF03CD09662DC000F2C9A9 /* RXTXcomm.jar in CopyFiles */,
|
||||||
33CF03CE09662DC000F2C9A9 /* antlr.jar in CopyFiles */,
|
33CF03CE09662DC000F2C9A9 /* antlr.jar in CopyFiles */,
|
||||||
@ -424,6 +442,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 16;
|
dstSubfolderSpec = 16;
|
||||||
files = (
|
files = (
|
||||||
|
335A28FE0C8CCB4000D8A7F4 /* libquaqua.jnilib in CopyFiles */,
|
||||||
339514FA097AEB8000193C89 /* license.txt in CopyFiles */,
|
339514FA097AEB8000193C89 /* license.txt in CopyFiles */,
|
||||||
339514FB097AEB8000193C89 /* readme.txt in CopyFiles */,
|
339514FB097AEB8000193C89 /* readme.txt in CopyFiles */,
|
||||||
);
|
);
|
||||||
@ -433,6 +452,22 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
332D4DB509CF147F00BF81F6 /* Sizer.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = Sizer.java; sourceTree = "<group>"; };
|
332D4DB509CF147F00BF81F6 /* Sizer.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = Sizer.java; sourceTree = "<group>"; };
|
||||||
|
335A28F20C8CCAF700D8A7F4 /* libquaqua.jnilib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libquaqua.jnilib; sourceTree = "<group>"; };
|
||||||
|
335A28F30C8CCAF700D8A7F4 /* quaqua.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = quaqua.jar; sourceTree = "<group>"; };
|
||||||
|
335A29070C8CCC0900D8A7F4 /* PApplet.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PApplet.java; sourceTree = "<group>"; };
|
||||||
|
335A29080C8CCC0900D8A7F4 /* PConstants.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PConstants.java; sourceTree = "<group>"; };
|
||||||
|
335A29090C8CCC0900D8A7F4 /* PFont.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PFont.java; sourceTree = "<group>"; };
|
||||||
|
335A290A0C8CCC0900D8A7F4 /* PGraphics.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PGraphics.java; sourceTree = "<group>"; };
|
||||||
|
335A290B0C8CCC0900D8A7F4 /* PGraphics2D.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PGraphics2D.java; sourceTree = "<group>"; };
|
||||||
|
335A290C0C8CCC0900D8A7F4 /* PGraphics3D.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PGraphics3D.java; sourceTree = "<group>"; };
|
||||||
|
335A290D0C8CCC0900D8A7F4 /* PGraphicsJava2D.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PGraphicsJava2D.java; sourceTree = "<group>"; };
|
||||||
|
335A290E0C8CCC0900D8A7F4 /* PImage.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PImage.java; sourceTree = "<group>"; };
|
||||||
|
335A290F0C8CCC0900D8A7F4 /* PLine.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PLine.java; sourceTree = "<group>"; };
|
||||||
|
335A29100C8CCC0900D8A7F4 /* PMatrix.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PMatrix.java; sourceTree = "<group>"; };
|
||||||
|
335A29110C8CCC0900D8A7F4 /* PPolygon.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PPolygon.java; sourceTree = "<group>"; };
|
||||||
|
335A29120C8CCC0900D8A7F4 /* PShape.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PShape.java; sourceTree = "<group>"; };
|
||||||
|
335A29130C8CCC0900D8A7F4 /* PTriangle.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = PTriangle.java; sourceTree = "<group>"; };
|
||||||
|
335A29230C8CCC5E00D8A7F4 /* DiscourseFormat.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = DiscourseFormat.java; sourceTree = "<group>"; };
|
||||||
335D3AFD0C4EE19D0065B27E /* ATmegaBOOT_168.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ATmegaBOOT_168.c; sourceTree = "<group>"; };
|
335D3AFD0C4EE19D0065B27E /* ATmegaBOOT_168.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ATmegaBOOT_168.c; sourceTree = "<group>"; };
|
||||||
335D3AFE0C4EE19D0065B27E /* ATmegaBOOT_168_diecimila.hex */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ATmegaBOOT_168_diecimila.hex; sourceTree = "<group>"; };
|
335D3AFE0C4EE19D0065B27E /* ATmegaBOOT_168_diecimila.hex */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ATmegaBOOT_168_diecimila.hex; sourceTree = "<group>"; };
|
||||||
335D3AFF0C4EE19D0065B27E /* ATmegaBOOT_168_ng.hex */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ATmegaBOOT_168_ng.hex; sourceTree = "<group>"; };
|
335D3AFF0C4EE19D0065B27E /* ATmegaBOOT_168_ng.hex */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ATmegaBOOT_168_ng.hex; sourceTree = "<group>"; };
|
||||||
@ -576,6 +611,27 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
335A29060C8CCC0800D8A7F4 /* core */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
335A29070C8CCC0900D8A7F4 /* PApplet.java */,
|
||||||
|
335A29080C8CCC0900D8A7F4 /* PConstants.java */,
|
||||||
|
335A29090C8CCC0900D8A7F4 /* PFont.java */,
|
||||||
|
335A290A0C8CCC0900D8A7F4 /* PGraphics.java */,
|
||||||
|
335A290B0C8CCC0900D8A7F4 /* PGraphics2D.java */,
|
||||||
|
335A290C0C8CCC0900D8A7F4 /* PGraphics3D.java */,
|
||||||
|
335A290D0C8CCC0900D8A7F4 /* PGraphicsJava2D.java */,
|
||||||
|
335A290E0C8CCC0900D8A7F4 /* PImage.java */,
|
||||||
|
335A290F0C8CCC0900D8A7F4 /* PLine.java */,
|
||||||
|
335A29100C8CCC0900D8A7F4 /* PMatrix.java */,
|
||||||
|
335A29110C8CCC0900D8A7F4 /* PPolygon.java */,
|
||||||
|
335A29120C8CCC0900D8A7F4 /* PShape.java */,
|
||||||
|
335A29130C8CCC0900D8A7F4 /* PTriangle.java */,
|
||||||
|
);
|
||||||
|
name = core;
|
||||||
|
path = ../../core;
|
||||||
|
sourceTree = SOURCE_ROOT;
|
||||||
|
};
|
||||||
335D3AFC0C4EE19D0065B27E /* bootloader168 */ = {
|
335D3AFC0C4EE19D0065B27E /* bootloader168 */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -660,6 +716,7 @@
|
|||||||
33FFFD3D0965B1E40016AC38 = {
|
33FFFD3D0965B1E40016AC38 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
335A29060C8CCC0800D8A7F4 /* core */,
|
||||||
33CF03B009662CA800F2C9A9 /* arduino.icns */,
|
33CF03B009662CA800F2C9A9 /* arduino.icns */,
|
||||||
33FF07D50965C3560016AC38 /* targets */,
|
33FF07D50965C3560016AC38 /* targets */,
|
||||||
33FFFE220965BD100016AC38 /* app */,
|
33FFFE220965BD100016AC38 /* app */,
|
||||||
@ -789,6 +846,7 @@
|
|||||||
33FFFE710965BD110016AC38 /* tools */ = {
|
33FFFE710965BD110016AC38 /* tools */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
335A29230C8CCC5E00D8A7F4 /* DiscourseFormat.java */,
|
||||||
33BEDDD309D6E8D800430D5B /* Archiver.java */,
|
33BEDDD309D6E8D800430D5B /* Archiver.java */,
|
||||||
33BEDDD409D6E8D800430D5B /* ExportFolder.java */,
|
33BEDDD409D6E8D800430D5B /* ExportFolder.java */,
|
||||||
33FFFE720965BD110016AC38 /* AutoFormat.java */,
|
33FFFE720965BD110016AC38 /* AutoFormat.java */,
|
||||||
@ -843,6 +901,8 @@
|
|||||||
33FFFEAC0965BD110016AC38 /* dist */ = {
|
33FFFEAC0965BD110016AC38 /* dist */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
335A28F20C8CCAF700D8A7F4 /* libquaqua.jnilib */,
|
||||||
|
335A28F30C8CCAF700D8A7F4 /* quaqua.jar */,
|
||||||
33FFFEAE0965BD110016AC38 /* bootloader */,
|
33FFFEAE0965BD110016AC38 /* bootloader */,
|
||||||
33FFFEB20965BD110016AC38 /* drivers */,
|
33FFFEB20965BD110016AC38 /* drivers */,
|
||||||
33FFFEB50965BD110016AC38 /* DS_Store */,
|
33FFFEB50965BD110016AC38 /* DS_Store */,
|
||||||
@ -1065,6 +1125,20 @@
|
|||||||
33BEE0CE09D7446100430D5B /* Library.java in Sources */,
|
33BEE0CE09D7446100430D5B /* Library.java in Sources */,
|
||||||
33F9446D0C2B2F6F0093EB9C /* UispUploader.java in Sources */,
|
33F9446D0C2B2F6F0093EB9C /* UispUploader.java in Sources */,
|
||||||
33F944E10C2B33560093EB9C /* AvrdudeUploader.java in Sources */,
|
33F944E10C2B33560093EB9C /* AvrdudeUploader.java in Sources */,
|
||||||
|
335A29140C8CCC0900D8A7F4 /* PApplet.java in Sources */,
|
||||||
|
335A29150C8CCC0900D8A7F4 /* PConstants.java in Sources */,
|
||||||
|
335A29160C8CCC0900D8A7F4 /* PFont.java in Sources */,
|
||||||
|
335A29170C8CCC0900D8A7F4 /* PGraphics.java in Sources */,
|
||||||
|
335A29180C8CCC0900D8A7F4 /* PGraphics2D.java in Sources */,
|
||||||
|
335A29190C8CCC0900D8A7F4 /* PGraphics3D.java in Sources */,
|
||||||
|
335A291A0C8CCC0900D8A7F4 /* PGraphicsJava2D.java in Sources */,
|
||||||
|
335A291B0C8CCC0900D8A7F4 /* PImage.java in Sources */,
|
||||||
|
335A291C0C8CCC0900D8A7F4 /* PLine.java in Sources */,
|
||||||
|
335A291D0C8CCC0900D8A7F4 /* PMatrix.java in Sources */,
|
||||||
|
335A291E0C8CCC0900D8A7F4 /* PPolygon.java in Sources */,
|
||||||
|
335A291F0C8CCC0900D8A7F4 /* PShape.java in Sources */,
|
||||||
|
335A29200C8CCC0900D8A7F4 /* PTriangle.java in Sources */,
|
||||||
|
335A29240C8CCC5E00D8A7F4 /* DiscourseFormat.java in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
BIN
build/macosx/dist/libquaqua.jnilib
vendored
Executable file
BIN
build/macosx/dist/libquaqua.jnilib
vendored
Executable file
Binary file not shown.
BIN
build/macosx/dist/quaqua.jar
vendored
Executable file
BIN
build/macosx/dist/quaqua.jar
vendored
Executable file
Binary file not shown.
@ -30,8 +30,8 @@ void loop()
|
|||||||
digitalWrite(pins[i], LOW); // and turning it off.
|
digitalWrite(pins[i], LOW); // and turning it off.
|
||||||
}
|
}
|
||||||
for (i = num_pins - 1; i >= 0; i--) {
|
for (i = num_pins - 1; i >= 0; i--) {
|
||||||
digitalWrite(i, HIGH);
|
digitalWrite(pins[i], HIGH);
|
||||||
delay(timer);
|
delay(timer);
|
||||||
digitalWrite(i, LOW);
|
digitalWrite(pins[i], LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
build/windows/dist/avr_tools.zip
vendored
BIN
build/windows/dist/avr_tools.zip
vendored
Binary file not shown.
@ -145,8 +145,8 @@ CLASSPATH="..\\build\\windows\\work\\lib\\RXTXcomm.jar;..\\build\\windows\\work\
|
|||||||
# show the user an error, rather than crapping out with some strange
|
# show the user an error, rather than crapping out with some strange
|
||||||
# "class not found" crap
|
# "class not found" crap
|
||||||
# need to do this twice because otherwise dependencies aren't resolved right.
|
# need to do this twice because otherwise dependencies aren't resolved right.
|
||||||
../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes preproc/*.java syntax/*.java tools/*.java *.java
|
../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes ../core/*.java preproc/*.java syntax/*.java tools/*.java *.java
|
||||||
../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes preproc/*.java syntax/*.java tools/*.java *.java
|
../build/windows/work/jikes -target 1.3 +D -classpath "$CLASSPATH;..\\build\\windows\\work\\classes" -d ..\\build\\windows\\work\\classes ../core/*.java preproc/*.java syntax/*.java tools/*.java *.java
|
||||||
|
|
||||||
cd ../build/windows/work/classes
|
cd ../build/windows/work/classes
|
||||||
rm -f ../lib/pde.jar
|
rm -f ../lib/pde.jar
|
||||||
|
8334
core/PApplet.java
Normal file
8334
core/PApplet.java
Normal file
File diff suppressed because it is too large
Load Diff
322
core/PConstants.java
Normal file
322
core/PConstants.java
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
|
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||||
|
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.core;
|
||||||
|
|
||||||
|
import java.awt.Cursor;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Numbers shared throughout processing.core.
|
||||||
|
* <P>
|
||||||
|
* An attempt is made to keep the constants as short/non-verbose
|
||||||
|
* as possible. For instance, the constant is TIFF instead of
|
||||||
|
* FILE_TYPE_TIFF. We'll do this as long as we can get away with it.
|
||||||
|
*/
|
||||||
|
public interface PConstants {
|
||||||
|
|
||||||
|
// renderers known to processing.core
|
||||||
|
|
||||||
|
static final String P2D = "processing.core.PGraphics2D";
|
||||||
|
static final String P3D = "processing.core.PGraphics3D";
|
||||||
|
static final String JAVA2D = "processing.core.PGraphicsJava2D";
|
||||||
|
static final String OPENGL = "processing.opengl.PGraphicsOpenGL";
|
||||||
|
static final String PDF = "processing.pdf.PGraphicsPDF";
|
||||||
|
static final String DXF = "processing.dxf.RawDXF";
|
||||||
|
//static final String SVG = "processing.dxf.PGraphicsSVG";
|
||||||
|
|
||||||
|
|
||||||
|
// platform IDs for PApplet.platform
|
||||||
|
|
||||||
|
static final int WINDOWS = 1;
|
||||||
|
static final int MACOS9 = 2;
|
||||||
|
static final int MACOSX = 3;
|
||||||
|
static final int LINUX = 4;
|
||||||
|
static final int OTHER = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// for better parity between c++ version (at no speed cost)
|
||||||
|
|
||||||
|
static final float EPSILON = 0.0001f;
|
||||||
|
// was around for auto-port to mobile version
|
||||||
|
//static final float ONE = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
|
// useful goodness
|
||||||
|
|
||||||
|
static final float PI = (float) Math.PI;
|
||||||
|
static final float HALF_PI = PI / 2.0f;
|
||||||
|
static final float THIRD_PI = PI / 3.0f;
|
||||||
|
static final float QUARTER_PI = PI / 4.0f;
|
||||||
|
static final float TWO_PI = PI * 2.0f;
|
||||||
|
|
||||||
|
static final float DEG_TO_RAD = PI/180.0f;
|
||||||
|
static final float RAD_TO_DEG = 180.0f/PI;
|
||||||
|
|
||||||
|
|
||||||
|
// angle modes
|
||||||
|
|
||||||
|
//static final int RADIANS = 0;
|
||||||
|
//static final int DEGREES = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// used by split, all the standard whitespace chars
|
||||||
|
// (also includes unicode nbsp, that little bostage)
|
||||||
|
|
||||||
|
static final String WHITESPACE = " \t\n\r\f\u00A0";
|
||||||
|
|
||||||
|
|
||||||
|
// for colors and/or images
|
||||||
|
|
||||||
|
static final int RGB = 1; // image & color
|
||||||
|
static final int ARGB = 2; // image
|
||||||
|
static final int HSB = 3; // color
|
||||||
|
static final int ALPHA = 4; // image
|
||||||
|
|
||||||
|
|
||||||
|
// image file types
|
||||||
|
|
||||||
|
static final int TIFF = 0;
|
||||||
|
static final int TARGA = 1;
|
||||||
|
static final int JPEG = 2;
|
||||||
|
static final int GIF = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// filter/convert types
|
||||||
|
|
||||||
|
static final int BLUR = 11;
|
||||||
|
static final int GRAY = 12;
|
||||||
|
static final int INVERT = 13;
|
||||||
|
static final int OPAQUE = 14;
|
||||||
|
static final int POSTERIZE = 15;
|
||||||
|
static final int THRESHOLD = 16;
|
||||||
|
static final int ERODE = 17;
|
||||||
|
static final int DILATE = 18;
|
||||||
|
|
||||||
|
|
||||||
|
// blend mode keyword definitions
|
||||||
|
// @see processing.core.PImage#blendColor(int,int,int)
|
||||||
|
|
||||||
|
public final static int REPLACE = 0;
|
||||||
|
public final static int BLEND = 1 << 0;
|
||||||
|
public final static int ADD = 1 << 1;
|
||||||
|
public final static int SUBTRACT = 1 << 2;
|
||||||
|
public final static int LIGHTEST = 1 << 3;
|
||||||
|
public final static int DARKEST = 1 << 4;
|
||||||
|
public final static int DIFFERENCE = 1 << 5;
|
||||||
|
public final static int EXCLUSION = 1 << 6;
|
||||||
|
public final static int MULTIPLY = 1 << 7;
|
||||||
|
public final static int SCREEN = 1 << 8;
|
||||||
|
public final static int OVERLAY = 1 << 9;
|
||||||
|
public final static int HARD_LIGHT = 1 << 10;
|
||||||
|
public final static int SOFT_LIGHT = 1 << 11;
|
||||||
|
public final static int DODGE = 1 << 12;
|
||||||
|
public final static int BURN = 1 << 13;
|
||||||
|
|
||||||
|
// colour component bitmasks
|
||||||
|
|
||||||
|
public static final int ALPHA_MASK = 0xff000000;
|
||||||
|
public static final int RED_MASK = 0x00ff0000;
|
||||||
|
public static final int GREEN_MASK = 0x0000ff00;
|
||||||
|
public static final int BLUE_MASK = 0x000000ff;
|
||||||
|
|
||||||
|
|
||||||
|
// for messages
|
||||||
|
|
||||||
|
static final int CHATTER = 0;
|
||||||
|
static final int COMPLAINT = 1;
|
||||||
|
static final int PROBLEM = 2;
|
||||||
|
|
||||||
|
|
||||||
|
// types of projection matrices
|
||||||
|
|
||||||
|
static final int CUSTOM = 0; // user-specified fanciness
|
||||||
|
static final int ORTHOGRAPHIC = 2; // 2D isometric projection
|
||||||
|
static final int PERSPECTIVE = 3; // perspective matrix
|
||||||
|
|
||||||
|
|
||||||
|
// rendering settings
|
||||||
|
|
||||||
|
static final float PIXEL_CENTER = 0.5f; // for polygon aa
|
||||||
|
|
||||||
|
|
||||||
|
// shapes
|
||||||
|
|
||||||
|
// the low four bits set the variety,
|
||||||
|
// higher bits set the specific shape type
|
||||||
|
|
||||||
|
static final int POINTS = (1 << 4) | 0;
|
||||||
|
|
||||||
|
static final int LINES = (1 << 5) | 0;
|
||||||
|
//static final int LINE_STRIP = (1 << 5) | 1;
|
||||||
|
//static final int LINE_LOOP = (1 << 5) | 2;
|
||||||
|
|
||||||
|
static final int TRIANGLES = (1 << 6) | 0;
|
||||||
|
static final int TRIANGLE_STRIP = (1 << 6) | 1;
|
||||||
|
static final int TRIANGLE_FAN = (1 << 6) | 2;
|
||||||
|
|
||||||
|
static final int QUADS = (1 << 7) | 0;
|
||||||
|
static final int QUAD_STRIP = (1 << 7) | 1;
|
||||||
|
|
||||||
|
static final int POLYGON = (1 << 8) | 0;
|
||||||
|
//static final int CONCAVE_POLYGON = (1 << 8) | 1;
|
||||||
|
//static final int CONVEX_POLYGON = (1 << 8) | 2;
|
||||||
|
|
||||||
|
static final int OPEN = 1;
|
||||||
|
static final int CLOSE = 2;
|
||||||
|
|
||||||
|
|
||||||
|
// shape drawing modes
|
||||||
|
|
||||||
|
/** Draw mode convention to use (x, y) to (width, height) */
|
||||||
|
static final int CORNER = 0;
|
||||||
|
/** Draw mode convention to use (x1, y1) to (x2, y2) coordinates */
|
||||||
|
static final int CORNERS = 1;
|
||||||
|
/** @deprecated Use RADIUS instead (as of 0125) */
|
||||||
|
static final int CENTER_RADIUS = 2;
|
||||||
|
/** Draw mode from the center, and using the radius */
|
||||||
|
static final int RADIUS = 2;
|
||||||
|
/** Draw from the center, using second pair of values as the diameter.
|
||||||
|
Formerly called CENTER_DIAMETER in alpha releases */
|
||||||
|
static final int CENTER = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// vertically alignment modes for text
|
||||||
|
|
||||||
|
/** Default vertical alignment for text placement */
|
||||||
|
static final int BASELINE = 0;
|
||||||
|
/** Align text to the top */
|
||||||
|
static final int TOP = 101;
|
||||||
|
/** Align text from the bottom, using the baseline. */
|
||||||
|
static final int BOTTOM = 102;
|
||||||
|
|
||||||
|
|
||||||
|
// uv texture orientation modes
|
||||||
|
|
||||||
|
static final int NORMALIZED = 1; //_SPACE = 0; // 0..1
|
||||||
|
static final int IMAGE = 2;
|
||||||
|
|
||||||
|
|
||||||
|
// text placement modes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* textMode(MODEL) is the default, meaning that characters
|
||||||
|
* will be affected by transformations like any other shapes.
|
||||||
|
* <p/>
|
||||||
|
* Changed value in 0093 to not interfere with LEFT, CENTER, and RIGHT.
|
||||||
|
*/
|
||||||
|
static final int MODEL = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* textMode(SHAPE) draws text using the the glyph outlines of
|
||||||
|
* individual characters rather than as textures. If the outlines are
|
||||||
|
* not available, then textMode(SHAPE) will be ignored and textMode(MODEL)
|
||||||
|
* will be used instead. For this reason, be sure to call textMode()
|
||||||
|
* <EM>after</EM> calling textFont().
|
||||||
|
* <p/>
|
||||||
|
* Currently, textMode(SHAPE) is only supported by OPENGL mode.
|
||||||
|
* It also requires Java 1.2 or higher (OPENGL requires 1.4 anyway)
|
||||||
|
*/
|
||||||
|
static final int SHAPE = 5;
|
||||||
|
|
||||||
|
|
||||||
|
// text alignment modes
|
||||||
|
// are inherited from LEFT, CENTER, RIGHT
|
||||||
|
|
||||||
|
|
||||||
|
// stroke modes
|
||||||
|
|
||||||
|
static final int SQUARE = 1 << 0; // called 'butt' in the svg spec
|
||||||
|
static final int ROUND = 1 << 1;
|
||||||
|
static final int PROJECT = 1 << 2; // called 'square' in the svg spec
|
||||||
|
static final int MITER = 1 << 3;
|
||||||
|
static final int BEVEL = 1 << 5;
|
||||||
|
|
||||||
|
|
||||||
|
// lighting
|
||||||
|
|
||||||
|
static final int AMBIENT = 0;
|
||||||
|
static final int DIRECTIONAL = 1;
|
||||||
|
static final int POINT = 2;
|
||||||
|
static final int SPOT = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// key constants
|
||||||
|
|
||||||
|
// only including the most-used of these guys
|
||||||
|
// if people need more esoteric keys, they can learn about
|
||||||
|
// the esoteric java KeyEvent api and of virtual keys
|
||||||
|
|
||||||
|
// both key and keyCode will equal these values
|
||||||
|
// for 0125, these were changed to 'char' values, because they
|
||||||
|
// can be upgraded to ints automatically by Java, but having them
|
||||||
|
// as ints prevented split(blah, TAB) from working
|
||||||
|
static final char BACKSPACE = 8;
|
||||||
|
static final char TAB = 9;
|
||||||
|
static final char ENTER = 10;
|
||||||
|
static final char RETURN = 13;
|
||||||
|
static final char ESC = 27;
|
||||||
|
static final char DELETE = 127;
|
||||||
|
|
||||||
|
// i.e. if ((key == CODED) && (keyCode == UP))
|
||||||
|
static final int CODED = 0xffff;
|
||||||
|
|
||||||
|
// key will be CODED and keyCode will be this value
|
||||||
|
static final int UP = KeyEvent.VK_UP;
|
||||||
|
static final int DOWN = KeyEvent.VK_DOWN;
|
||||||
|
static final int LEFT = KeyEvent.VK_LEFT;
|
||||||
|
static final int RIGHT = KeyEvent.VK_RIGHT;
|
||||||
|
|
||||||
|
// key will be CODED and keyCode will be this value
|
||||||
|
static final int ALT = KeyEvent.VK_ALT;
|
||||||
|
static final int CONTROL = KeyEvent.VK_CONTROL;
|
||||||
|
static final int SHIFT = KeyEvent.VK_SHIFT;
|
||||||
|
|
||||||
|
|
||||||
|
// cursor types
|
||||||
|
|
||||||
|
static final int ARROW = Cursor.DEFAULT_CURSOR;
|
||||||
|
static final int CROSS = Cursor.CROSSHAIR_CURSOR;
|
||||||
|
static final int HAND = Cursor.HAND_CURSOR;
|
||||||
|
static final int MOVE = Cursor.MOVE_CURSOR;
|
||||||
|
static final int TEXT = Cursor.TEXT_CURSOR;
|
||||||
|
static final int WAIT = Cursor.WAIT_CURSOR;
|
||||||
|
|
||||||
|
|
||||||
|
// hints
|
||||||
|
|
||||||
|
//static final int SCALE_STROKE_WIDTH = 0;
|
||||||
|
//static final int LIGHTING_AFFECTS_STROKE = 1;
|
||||||
|
static final int ENABLE_NATIVE_FONTS = 2;
|
||||||
|
static final int DISABLE_TEXT_SMOOTH = 3;
|
||||||
|
//static final int DISABLE_SMOOTH_HACK = 4;
|
||||||
|
static final int DISABLE_DEPTH_TEST = 5;
|
||||||
|
static final int NO_FLYING_POO = 6;
|
||||||
|
static final int ENABLE_DEPTH_SORT = 7;
|
||||||
|
static final int DISABLE_ERROR_REPORT = 8;
|
||||||
|
static final int ENABLE_ACCURATE_TEXTURES = 9;
|
||||||
|
|
||||||
|
static final int HINT_COUNT = 10;
|
||||||
|
}
|
1019
core/PFont.java
Normal file
1019
core/PFont.java
Normal file
File diff suppressed because it is too large
Load Diff
4308
core/PGraphics.java
Normal file
4308
core/PGraphics.java
Normal file
File diff suppressed because it is too large
Load Diff
1672
core/PGraphics2D.java
Normal file
1672
core/PGraphics2D.java
Normal file
File diff suppressed because it is too large
Load Diff
3943
core/PGraphics3D.java
Normal file
3943
core/PGraphics3D.java
Normal file
File diff suppressed because it is too large
Load Diff
1381
core/PGraphicsJava2D.java
Normal file
1381
core/PGraphicsJava2D.java
Normal file
File diff suppressed because it is too large
Load Diff
2598
core/PImage.java
Normal file
2598
core/PImage.java
Normal file
File diff suppressed because it is too large
Load Diff
1295
core/PLine.java
Normal file
1295
core/PLine.java
Normal file
File diff suppressed because it is too large
Load Diff
640
core/PMatrix.java
Normal file
640
core/PMatrix.java
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Processing project - http://Proce55ing.net
|
||||||
|
|
||||||
|
Copyright (c) 2005-06 Ben Fry and Casey Reas
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.core;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4x4 matrix implementation.
|
||||||
|
*/
|
||||||
|
public final class PMatrix implements PConstants {
|
||||||
|
|
||||||
|
public float m00, m01, m02, m03;
|
||||||
|
public float m10, m11, m12, m13;
|
||||||
|
public float m20, m21, m22, m23;
|
||||||
|
public float m30, m31, m32, m33;
|
||||||
|
|
||||||
|
final static int DEFAULT_STACK_DEPTH = 0;
|
||||||
|
int maxStackDepth;
|
||||||
|
int stackPointer = 0;
|
||||||
|
float stack[][];
|
||||||
|
|
||||||
|
|
||||||
|
// locally allocated version to avoid creating new memory
|
||||||
|
static protected PMatrix inverseCopy;
|
||||||
|
|
||||||
|
|
||||||
|
public PMatrix() {
|
||||||
|
set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
maxStackDepth = DEFAULT_STACK_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PMatrix(int stackDepth) {
|
||||||
|
set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
stack = new float[stackDepth][16];
|
||||||
|
maxStackDepth = stackDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PMatrix(float m00, float m01, float m02, float m03,
|
||||||
|
float m10, float m11, float m12, float m13,
|
||||||
|
float m20, float m21, float m22, float m23,
|
||||||
|
float m30, float m31, float m32, float m33) {
|
||||||
|
set(m00, m01, m02, m03,
|
||||||
|
m10, m11, m12, m13,
|
||||||
|
m20, m21, m22, m23,
|
||||||
|
m30, m31, m32, m33);
|
||||||
|
maxStackDepth = DEFAULT_STACK_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Make a copy of a matrix. We copy the stack depth,
|
||||||
|
// but we don't make a copy of the stack or the stack pointer.
|
||||||
|
public PMatrix(PMatrix src) {
|
||||||
|
set(src);
|
||||||
|
maxStackDepth = src.maxStackDepth;
|
||||||
|
stack = new float[maxStackDepth][16];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
set(1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clearStack() {
|
||||||
|
stackPointer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean push() {
|
||||||
|
if (stackPointer == maxStackDepth) return false;
|
||||||
|
|
||||||
|
stack[stackPointer][0] = m00;
|
||||||
|
stack[stackPointer][1] = m01;
|
||||||
|
stack[stackPointer][2] = m02;
|
||||||
|
stack[stackPointer][3] = m03;
|
||||||
|
|
||||||
|
stack[stackPointer][4] = m10;
|
||||||
|
stack[stackPointer][5] = m11;
|
||||||
|
stack[stackPointer][6] = m12;
|
||||||
|
stack[stackPointer][7] = m13;
|
||||||
|
|
||||||
|
stack[stackPointer][8] = m20;
|
||||||
|
stack[stackPointer][9] = m21;
|
||||||
|
stack[stackPointer][10] = m22;
|
||||||
|
stack[stackPointer][11] = m23;
|
||||||
|
|
||||||
|
stack[stackPointer][12] = m30;
|
||||||
|
stack[stackPointer][13] = m31;
|
||||||
|
stack[stackPointer][14] = m32;
|
||||||
|
stack[stackPointer][15] = m33;
|
||||||
|
|
||||||
|
stackPointer++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean pop() {
|
||||||
|
if (stackPointer == 0) return false;
|
||||||
|
stackPointer--;
|
||||||
|
|
||||||
|
m00 = stack[stackPointer][0];
|
||||||
|
m01 = stack[stackPointer][1];
|
||||||
|
m02 = stack[stackPointer][2];
|
||||||
|
m03 = stack[stackPointer][3];
|
||||||
|
|
||||||
|
m10 = stack[stackPointer][4];
|
||||||
|
m11 = stack[stackPointer][5];
|
||||||
|
m12 = stack[stackPointer][6];
|
||||||
|
m13 = stack[stackPointer][7];
|
||||||
|
|
||||||
|
m20 = stack[stackPointer][8];
|
||||||
|
m21 = stack[stackPointer][9];
|
||||||
|
m22 = stack[stackPointer][10];
|
||||||
|
m23 = stack[stackPointer][11];
|
||||||
|
|
||||||
|
m30 = stack[stackPointer][12];
|
||||||
|
m31 = stack[stackPointer][13];
|
||||||
|
m32 = stack[stackPointer][14];
|
||||||
|
m33 = stack[stackPointer][15];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void set(PMatrix src) {
|
||||||
|
set(src.m00, src.m01, src.m02, src.m03,
|
||||||
|
src.m10, src.m11, src.m12, src.m13,
|
||||||
|
src.m20, src.m21, src.m22, src.m23,
|
||||||
|
src.m30, src.m31, src.m32, src.m33);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void set(float m00, float m01, float m02, float m03,
|
||||||
|
float m10, float m11, float m12, float m13,
|
||||||
|
float m20, float m21, float m22, float m23,
|
||||||
|
float m30, float m31, float m32, float m33) {
|
||||||
|
this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03;
|
||||||
|
this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13;
|
||||||
|
this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23;
|
||||||
|
this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void translate(float tx, float ty) {
|
||||||
|
translate(tx, ty, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invTranslate(float tx, float ty) {
|
||||||
|
invTranslate(tx, ty, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void translate(float tx, float ty, float tz) {
|
||||||
|
m03 += tx*m00 + ty*m01 + tz*m02;
|
||||||
|
m13 += tx*m10 + ty*m11 + tz*m12;
|
||||||
|
m23 += tx*m20 + ty*m21 + tz*m22;
|
||||||
|
m33 += tx*m30 + ty*m31 + tz*m32;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invTranslate(float tx, float ty, float tz) {
|
||||||
|
preApply(1, 0, 0, -tx,
|
||||||
|
0, 1, 0, -ty,
|
||||||
|
0, 0, 1, -tz,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// OPT could save several multiplies for the 0s and 1s by just
|
||||||
|
// putting the multMatrix code here and removing uneccessary terms
|
||||||
|
|
||||||
|
public void rotateX(float angle) {
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
apply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invRotateX(float angle) {
|
||||||
|
float c = cos(-angle);
|
||||||
|
float s = sin(-angle);
|
||||||
|
preApply(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void rotateY(float angle) {
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
apply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invRotateY(float angle) {
|
||||||
|
float c = cos(-angle);
|
||||||
|
float s = sin(-angle);
|
||||||
|
preApply(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just calls rotateZ because two dimensional rotation
|
||||||
|
* is the same as rotating along the z-axis.
|
||||||
|
*/
|
||||||
|
public void rotate(float angle) {
|
||||||
|
rotateZ(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invRotate(float angle) {
|
||||||
|
invRotateZ(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void rotateZ(float angle) {
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
apply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invRotateZ(float angle) {
|
||||||
|
float c = cos(-angle);
|
||||||
|
float s = sin(-angle);
|
||||||
|
preApply(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void rotate(float angle, float v0, float v1, float v2) {
|
||||||
|
// should be in radians (i think), instead of degrees (gl uses degrees)
|
||||||
|
// based on 15-463 code, but similar to opengl ref p.443
|
||||||
|
|
||||||
|
// TODO should make sure this vector is normalized
|
||||||
|
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
float t = 1.0f - c;
|
||||||
|
|
||||||
|
apply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
|
||||||
|
(t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0,
|
||||||
|
(t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invRotate(float angle, float v0, float v1, float v2) {
|
||||||
|
// TODO should make sure this vector is normalized
|
||||||
|
|
||||||
|
float c = cos(-angle);
|
||||||
|
float s = sin(-angle);
|
||||||
|
float t = 1.0f - c;
|
||||||
|
|
||||||
|
preApply((t*v0*v0) + c, (t*v0*v1) - (s*v2), (t*v0*v2) + (s*v1), 0,
|
||||||
|
(t*v0*v1) + (s*v2), (t*v1*v1) + c, (t*v1*v2) - (s*v0), 0,
|
||||||
|
(t*v0*v2) - (s*v1), (t*v1*v2) + (s*v0), (t*v2*v2) + c, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void scale(float s) {
|
||||||
|
apply(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invScale(float s) {
|
||||||
|
preApply(1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1/s, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void scale(float sx, float sy) {
|
||||||
|
apply(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invScale(float sx, float sy) {
|
||||||
|
preApply(1/sx, 0, 0, 0, 0, 1/sy, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// OPTIMIZE: same as above
|
||||||
|
public void scale(float x, float y, float z) {
|
||||||
|
apply(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void invScale(float x, float y, float z) {
|
||||||
|
preApply(1/x, 0, 0, 0, 0, 1/y, 0, 0, 0, 0, 1/z, 0, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void transform(float n00, float n01, float n02, float n03,
|
||||||
|
float n10, float n11, float n12, float n13,
|
||||||
|
float n20, float n21, float n22, float n23,
|
||||||
|
float n30, float n31, float n32, float n33) {
|
||||||
|
apply(n00, n01, n02, n03,
|
||||||
|
n10, n11, n12, n13,
|
||||||
|
n20, n21, n22, n23,
|
||||||
|
n30, n31, n32, n33);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public void preApply(PMatrix lhs) {
|
||||||
|
preApply(lhs.m00, lhs.m01, lhs.m02, lhs.m03,
|
||||||
|
lhs.m10, lhs.m11, lhs.m12, lhs.m13,
|
||||||
|
lhs.m20, lhs.m21, lhs.m22, lhs.m23,
|
||||||
|
lhs.m30, lhs.m31, lhs.m32, lhs.m33);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// for inverse operations, like multiplying the matrix on the left
|
||||||
|
public void preApply(float n00, float n01, float n02, float n03,
|
||||||
|
float n10, float n11, float n12, float n13,
|
||||||
|
float n20, float n21, float n22, float n23,
|
||||||
|
float n30, float n31, float n32, float n33) {
|
||||||
|
|
||||||
|
float r00 = n00*m00 + n01*m10 + n02*m20 + n03*m30;
|
||||||
|
float r01 = n00*m01 + n01*m11 + n02*m21 + n03*m31;
|
||||||
|
float r02 = n00*m02 + n01*m12 + n02*m22 + n03*m32;
|
||||||
|
float r03 = n00*m03 + n01*m13 + n02*m23 + n03*m33;
|
||||||
|
|
||||||
|
float r10 = n10*m00 + n11*m10 + n12*m20 + n13*m30;
|
||||||
|
float r11 = n10*m01 + n11*m11 + n12*m21 + n13*m31;
|
||||||
|
float r12 = n10*m02 + n11*m12 + n12*m22 + n13*m32;
|
||||||
|
float r13 = n10*m03 + n11*m13 + n12*m23 + n13*m33;
|
||||||
|
|
||||||
|
float r20 = n20*m00 + n21*m10 + n22*m20 + n23*m30;
|
||||||
|
float r21 = n20*m01 + n21*m11 + n22*m21 + n23*m31;
|
||||||
|
float r22 = n20*m02 + n21*m12 + n22*m22 + n23*m32;
|
||||||
|
float r23 = n20*m03 + n21*m13 + n22*m23 + n23*m33;
|
||||||
|
|
||||||
|
float r30 = n30*m00 + n31*m10 + n32*m20 + n33*m30;
|
||||||
|
float r31 = n30*m01 + n31*m11 + n32*m21 + n33*m31;
|
||||||
|
float r32 = n30*m02 + n31*m12 + n32*m22 + n33*m32;
|
||||||
|
float r33 = n30*m03 + n31*m13 + n32*m23 + n33*m33;
|
||||||
|
|
||||||
|
m00 = r00; m01 = r01; m02 = r02; m03 = r03;
|
||||||
|
m10 = r10; m11 = r11; m12 = r12; m13 = r13;
|
||||||
|
m20 = r20; m21 = r21; m22 = r22; m23 = r23;
|
||||||
|
m30 = r30; m31 = r31; m32 = r32; m33 = r33;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean invApply(PMatrix rhs) {
|
||||||
|
PMatrix copy = new PMatrix(rhs);
|
||||||
|
PMatrix inverse = copy.invert();
|
||||||
|
if (inverse == null) return false;
|
||||||
|
preApply(inverse);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean invApply(float n00, float n01, float n02, float n03,
|
||||||
|
float n10, float n11, float n12, float n13,
|
||||||
|
float n20, float n21, float n22, float n23,
|
||||||
|
float n30, float n31, float n32, float n33) {
|
||||||
|
if (inverseCopy == null) {
|
||||||
|
inverseCopy = new PMatrix();
|
||||||
|
}
|
||||||
|
inverseCopy.set(n00, n01, n02, n03,
|
||||||
|
n10, n11, n12, n13,
|
||||||
|
n20, n21, n22, n23,
|
||||||
|
n30, n31, n32, n33);
|
||||||
|
PMatrix inverse = inverseCopy.invert();
|
||||||
|
if (inverse == null) return false;
|
||||||
|
preApply(inverse);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void apply(PMatrix rhs) {
|
||||||
|
apply(rhs.m00, rhs.m01, rhs.m02, rhs.m03,
|
||||||
|
rhs.m10, rhs.m11, rhs.m12, rhs.m13,
|
||||||
|
rhs.m20, rhs.m21, rhs.m22, rhs.m23,
|
||||||
|
rhs.m30, rhs.m31, rhs.m32, rhs.m33);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void apply(float n00, float n01, float n02, float n03,
|
||||||
|
float n10, float n11, float n12, float n13,
|
||||||
|
float n20, float n21, float n22, float n23,
|
||||||
|
float n30, float n31, float n32, float n33) {
|
||||||
|
|
||||||
|
float r00 = m00*n00 + m01*n10 + m02*n20 + m03*n30;
|
||||||
|
float r01 = m00*n01 + m01*n11 + m02*n21 + m03*n31;
|
||||||
|
float r02 = m00*n02 + m01*n12 + m02*n22 + m03*n32;
|
||||||
|
float r03 = m00*n03 + m01*n13 + m02*n23 + m03*n33;
|
||||||
|
|
||||||
|
float r10 = m10*n00 + m11*n10 + m12*n20 + m13*n30;
|
||||||
|
float r11 = m10*n01 + m11*n11 + m12*n21 + m13*n31;
|
||||||
|
float r12 = m10*n02 + m11*n12 + m12*n22 + m13*n32;
|
||||||
|
float r13 = m10*n03 + m11*n13 + m12*n23 + m13*n33;
|
||||||
|
|
||||||
|
float r20 = m20*n00 + m21*n10 + m22*n20 + m23*n30;
|
||||||
|
float r21 = m20*n01 + m21*n11 + m22*n21 + m23*n31;
|
||||||
|
float r22 = m20*n02 + m21*n12 + m22*n22 + m23*n32;
|
||||||
|
float r23 = m20*n03 + m21*n13 + m22*n23 + m23*n33;
|
||||||
|
|
||||||
|
float r30 = m30*n00 + m31*n10 + m32*n20 + m33*n30;
|
||||||
|
float r31 = m30*n01 + m31*n11 + m32*n21 + m33*n31;
|
||||||
|
float r32 = m30*n02 + m31*n12 + m32*n22 + m33*n32;
|
||||||
|
float r33 = m30*n03 + m31*n13 + m32*n23 + m33*n33;
|
||||||
|
|
||||||
|
m00 = r00; m01 = r01; m02 = r02; m03 = r03;
|
||||||
|
m10 = r10; m11 = r11; m12 = r12; m13 = r13;
|
||||||
|
m20 = r20; m21 = r21; m22 = r22; m23 = r23;
|
||||||
|
m30 = r30; m31 = r31; m32 = r32; m33 = r33;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void mult3(float vec[], float out[]) {
|
||||||
|
// must use these temp vars because vec may be the same as out
|
||||||
|
float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03;
|
||||||
|
float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13;
|
||||||
|
float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23;
|
||||||
|
|
||||||
|
out[0] = tmpx;
|
||||||
|
out[1] = tmpy;
|
||||||
|
out[2] = tmpz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void mult(float vec[], float out[]) {
|
||||||
|
// must use these temp vars because vec may be the same as out
|
||||||
|
float tmpx = m00*vec[0] + m01*vec[1] + m02*vec[2] + m03*vec[3];
|
||||||
|
float tmpy = m10*vec[0] + m11*vec[1] + m12*vec[2] + m13*vec[3];
|
||||||
|
float tmpz = m20*vec[0] + m21*vec[1] + m22*vec[2] + m23*vec[3];
|
||||||
|
float tmpw = m30*vec[0] + m31*vec[1] + m32*vec[2] + m33*vec[3];
|
||||||
|
|
||||||
|
out[0] = tmpx;
|
||||||
|
out[1] = tmpy;
|
||||||
|
out[2] = tmpz;
|
||||||
|
out[3] = tmpw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the determinant of the matrix
|
||||||
|
*/
|
||||||
|
public float determinant() {
|
||||||
|
float f =
|
||||||
|
m00
|
||||||
|
* ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32)
|
||||||
|
- m13 * m22 * m31
|
||||||
|
- m11 * m23 * m32
|
||||||
|
- m12 * m21 * m33);
|
||||||
|
f -= m01
|
||||||
|
* ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32)
|
||||||
|
- m13 * m22 * m30
|
||||||
|
- m10 * m23 * m32
|
||||||
|
- m12 * m20 * m33);
|
||||||
|
f += m02
|
||||||
|
* ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31)
|
||||||
|
- m13 * m21 * m30
|
||||||
|
- m10 * m23 * m31
|
||||||
|
- m11 * m20 * m33);
|
||||||
|
f -= m03
|
||||||
|
* ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31)
|
||||||
|
- m12 * m21 * m30
|
||||||
|
- m10 * m22 * m31
|
||||||
|
- m11 * m20 * m32);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the determinant of a 3x3 matrix
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
private float determinant3x3(float t00, float t01, float t02,
|
||||||
|
float t10, float t11, float t12,
|
||||||
|
float t20, float t21, float t22) {
|
||||||
|
return (t00 * (t11 * t22 - t12 * t21) +
|
||||||
|
t01 * (t12 * t20 - t10 * t22) +
|
||||||
|
t02 * (t10 * t21 - t11 * t20));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PMatrix transpose() {
|
||||||
|
float temp;
|
||||||
|
temp = m01; m01 = m10; m10 = temp;
|
||||||
|
temp = m02; m02 = m20; m20 = temp;
|
||||||
|
temp = m03; m03 = m30; m30 = temp;
|
||||||
|
temp = m12; m12 = m21; m21 = temp;
|
||||||
|
temp = m13; m13 = m31; m31 = temp;
|
||||||
|
temp = m23; m23 = m32; m32 = temp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invert this matrix
|
||||||
|
* @return this if successful, null otherwise
|
||||||
|
*/
|
||||||
|
public PMatrix invert() {
|
||||||
|
|
||||||
|
float determinant = determinant();
|
||||||
|
|
||||||
|
if (determinant != 0) {
|
||||||
|
// m00 m01 m02 m03
|
||||||
|
// m10 m11 m12 m13
|
||||||
|
// m20 m21 m22 m23
|
||||||
|
// m30 m31 m32 m33
|
||||||
|
float determinant_inv = 1f / determinant;
|
||||||
|
|
||||||
|
// first row
|
||||||
|
float t00 = determinant3x3(m11, m12, m13, m21, m22, m23, m31, m32, m33);
|
||||||
|
float t01 = -determinant3x3(m10, m12, m13, m20, m22, m23, m30, m32, m33);
|
||||||
|
float t02 = determinant3x3(m10, m11, m13, m20, m21, m23, m30, m31, m33);
|
||||||
|
float t03 = -determinant3x3(m10, m11, m12, m20, m21, m22, m30, m31, m32);
|
||||||
|
|
||||||
|
// second row
|
||||||
|
float t10 = -determinant3x3(m01, m02, m03, m21, m22, m23, m31, m32, m33);
|
||||||
|
float t11 = determinant3x3(m00, m02, m03, m20, m22, m23, m30, m32, m33);
|
||||||
|
float t12 = -determinant3x3(m00, m01, m03, m20, m21, m23, m30, m31, m33);
|
||||||
|
float t13 = determinant3x3(m00, m01, m02, m20, m21, m22, m30, m31, m32);
|
||||||
|
|
||||||
|
// third row
|
||||||
|
float t20 = determinant3x3(m01, m02, m03, m11, m12, m13, m31, m32, m33);
|
||||||
|
float t21 = -determinant3x3(m00, m02, m03, m10, m12, m13, m30, m32, m33);
|
||||||
|
float t22 = determinant3x3(m00, m01, m03, m10, m11, m13, m30, m31, m33);
|
||||||
|
float t23 = -determinant3x3(m00, m01, m02, m10, m11, m12, m30, m31, m32);
|
||||||
|
|
||||||
|
// fourth row
|
||||||
|
float t30 = -determinant3x3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
|
||||||
|
float t31 = determinant3x3(m00, m02, m03, m10, m12, m13, m20, m22, m23);
|
||||||
|
float t32 = -determinant3x3(m00, m01, m03, m10, m11, m13, m20, m21, m23);
|
||||||
|
float t33 = determinant3x3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
|
||||||
|
|
||||||
|
// transpose and divide by the determinant
|
||||||
|
m00 = t00*determinant_inv;
|
||||||
|
m11 = t11*determinant_inv;
|
||||||
|
m22 = t22*determinant_inv;
|
||||||
|
m33 = t33*determinant_inv;
|
||||||
|
m01 = t10*determinant_inv;
|
||||||
|
m10 = t01*determinant_inv;
|
||||||
|
m20 = t02*determinant_inv;
|
||||||
|
m02 = t20*determinant_inv;
|
||||||
|
m12 = t21*determinant_inv;
|
||||||
|
m21 = t12*determinant_inv;
|
||||||
|
m03 = t30*determinant_inv;
|
||||||
|
m30 = t03*determinant_inv;
|
||||||
|
m13 = t31*determinant_inv;
|
||||||
|
m31 = t13*determinant_inv;
|
||||||
|
m32 = t23*determinant_inv;
|
||||||
|
m23 = t32*determinant_inv;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
public void print() {
|
||||||
|
int big = (int) Math.abs(max(max(max(max(abs(m00), abs(m01)),
|
||||||
|
max(abs(m02), abs(m03))),
|
||||||
|
max(max(abs(m10), abs(m11)),
|
||||||
|
max(abs(m12), abs(m13)))),
|
||||||
|
max(max(max(abs(m20), abs(m21)),
|
||||||
|
max(abs(m22), abs(m23))),
|
||||||
|
max(max(abs(m30), abs(m31)),
|
||||||
|
max(abs(m32), abs(m33))))));
|
||||||
|
|
||||||
|
// avoid infinite loop
|
||||||
|
if (Float.isNaN(big) || Float.isInfinite(big)) {
|
||||||
|
big = 1000000; // set to something arbitrary
|
||||||
|
}
|
||||||
|
|
||||||
|
int d = 1;
|
||||||
|
while ((big /= 10) != 0) d++; // cheap log()
|
||||||
|
|
||||||
|
System.out.println(PApplet.nfs(m00, d, 4) + " " +
|
||||||
|
PApplet.nfs(m01, d, 4) + " " +
|
||||||
|
PApplet.nfs(m02, d, 4) + " " +
|
||||||
|
PApplet.nfs(m03, d, 4));
|
||||||
|
|
||||||
|
System.out.println(PApplet.nfs(m10, d, 4) + " " +
|
||||||
|
PApplet.nfs(m11, d, 4) + " " +
|
||||||
|
PApplet.nfs(m12, d, 4) + " " +
|
||||||
|
PApplet.nfs(m13, d, 4));
|
||||||
|
|
||||||
|
System.out.println(PApplet.nfs(m20, d, 4) + " " +
|
||||||
|
PApplet.nfs(m21, d, 4) + " " +
|
||||||
|
PApplet.nfs(m22, d, 4) + " " +
|
||||||
|
PApplet.nfs(m23, d, 4));
|
||||||
|
|
||||||
|
System.out.println(PApplet.nfs(m30, d, 4) + " " +
|
||||||
|
PApplet.nfs(m31, d, 4) + " " +
|
||||||
|
PApplet.nfs(m32, d, 4) + " " +
|
||||||
|
PApplet.nfs(m33, d, 4));
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
private final float max(float a, float b) {
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final float abs(float a) {
|
||||||
|
return (a < 0) ? -a : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final float sin(float angle) {
|
||||||
|
return (float)Math.sin(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final float cos(float angle) {
|
||||||
|
return (float)Math.cos(angle);
|
||||||
|
}
|
||||||
|
}
|
772
core/PPolygon.java
Normal file
772
core/PPolygon.java
Normal file
@ -0,0 +1,772 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
|
Copyright (c) 2004-06 Ben Fry and Casey Reas
|
||||||
|
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.core;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zbuffer polygon rendering object for PGraphics.
|
||||||
|
* <P>
|
||||||
|
* Likely to be removed before 1.0 as it's no longer particularly used.
|
||||||
|
*/
|
||||||
|
public class PPolygon implements PConstants {
|
||||||
|
|
||||||
|
// identical to the constants from PGraphics
|
||||||
|
|
||||||
|
static final int X = 0; // transformed xyzw
|
||||||
|
static final int Y = 1; // formerly SX SY SZ
|
||||||
|
static final int Z = 2;
|
||||||
|
|
||||||
|
static final int R = 3; // actual rgb, after lighting
|
||||||
|
static final int G = 4; // fill stored here, transform in place
|
||||||
|
static final int B = 5;
|
||||||
|
static final int A = 6;
|
||||||
|
|
||||||
|
static final int U = 7; // texture
|
||||||
|
static final int V = 8;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
static final int DEFAULT_SIZE = 64; // this is needed for spheres
|
||||||
|
float vertices[][] = new float[DEFAULT_SIZE][PGraphics.VERTEX_FIELD_COUNT];
|
||||||
|
int vertexCount;
|
||||||
|
|
||||||
|
// really this is "debug" but..
|
||||||
|
static final boolean FRY = false;
|
||||||
|
|
||||||
|
// after some fiddling, this seems to produce the best results
|
||||||
|
//static final int ZBUFFER_MIN_COVERAGE = 204;
|
||||||
|
|
||||||
|
float r[] = new float[DEFAULT_SIZE]; // storage used by incrementalize
|
||||||
|
float dr[] = new float[DEFAULT_SIZE];
|
||||||
|
float l[] = new float[DEFAULT_SIZE]; // more storage for incrementalize
|
||||||
|
float dl[] = new float[DEFAULT_SIZE];
|
||||||
|
float sp[] = new float[DEFAULT_SIZE]; // temporary storage for scanline
|
||||||
|
float sdp[] = new float[DEFAULT_SIZE];
|
||||||
|
|
||||||
|
// color and xyz are always interpolated
|
||||||
|
boolean interpX;
|
||||||
|
boolean interpZ;
|
||||||
|
boolean interpUV; // is this necessary? could just check timage != null
|
||||||
|
boolean interpARGB;
|
||||||
|
|
||||||
|
int rgba;
|
||||||
|
int r2, g2, b2, a2, a2orig;
|
||||||
|
|
||||||
|
boolean noDepthTest;
|
||||||
|
|
||||||
|
PGraphics parent;
|
||||||
|
int pixels[];
|
||||||
|
|
||||||
|
// the parent's width/height,
|
||||||
|
// or if smooth is enabled, parent's w/h scaled
|
||||||
|
// up by the smooth dimension
|
||||||
|
int width, height;
|
||||||
|
int width1, height1;
|
||||||
|
|
||||||
|
PImage timage;
|
||||||
|
int tpixels[];
|
||||||
|
int theight, twidth;
|
||||||
|
int theight1, twidth1;
|
||||||
|
int tformat;
|
||||||
|
|
||||||
|
// temp fix to behave like SMOOTH_IMAGES
|
||||||
|
boolean texture_smooth;
|
||||||
|
|
||||||
|
// for anti-aliasing
|
||||||
|
static final int SUBXRES = 8;
|
||||||
|
static final int SUBXRES1 = 7;
|
||||||
|
static final int SUBYRES = 8;
|
||||||
|
static final int SUBYRES1 = 7;
|
||||||
|
static final int MAX_COVERAGE = SUBXRES * SUBYRES;
|
||||||
|
|
||||||
|
boolean smooth;
|
||||||
|
int firstModY;
|
||||||
|
int lastModY;
|
||||||
|
int lastY;
|
||||||
|
int aaleft[] = new int[SUBYRES];
|
||||||
|
int aaright[] = new int[SUBYRES];
|
||||||
|
int aaleftmin, aarightmin;
|
||||||
|
int aaleftmax, aarightmax;
|
||||||
|
int aaleftfull, aarightfull;
|
||||||
|
|
||||||
|
final private int MODYRES(int y) {
|
||||||
|
return (y & SUBYRES1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PPolygon(PGraphics iparent) {
|
||||||
|
parent = iparent;
|
||||||
|
reset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void reset(int count) {
|
||||||
|
vertexCount = count;
|
||||||
|
interpX = true;
|
||||||
|
interpZ = true;
|
||||||
|
interpUV = false;
|
||||||
|
interpARGB = true;
|
||||||
|
timage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public float[] nextVertex() {
|
||||||
|
if (vertexCount == vertices.length) {
|
||||||
|
//parent.message(CHATTER, "re-allocating for " +
|
||||||
|
// (vertexCount*2) + " vertices");
|
||||||
|
float temp[][] = new float[vertexCount<<1][PGraphics.VERTEX_FIELD_COUNT];
|
||||||
|
System.arraycopy(vertices, 0, temp, 0, vertexCount);
|
||||||
|
vertices = temp;
|
||||||
|
|
||||||
|
r = new float[vertices.length];
|
||||||
|
dr = new float[vertices.length];
|
||||||
|
l = new float[vertices.length];
|
||||||
|
dl = new float[vertices.length];
|
||||||
|
sp = new float[vertices.length];
|
||||||
|
sdp = new float[vertices.length];
|
||||||
|
}
|
||||||
|
return vertices[vertexCount++]; // returns v[0], sets vc to 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if this vertex is redundant. If so, will also
|
||||||
|
* decrement the vertex count.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
public boolean redundantVertex(float x, float y, float z) {
|
||||||
|
// because vertexCount will be 2 when setting vertex[1]
|
||||||
|
if (vertexCount < 2) return false;
|
||||||
|
|
||||||
|
// vertexCount-1 is the current vertex that would be used
|
||||||
|
// vertexCount-2 would be the previous feller
|
||||||
|
if ((Math.abs(vertices[vertexCount-2][MX] - x) < EPSILON) &&
|
||||||
|
(Math.abs(vertices[vertexCount-2][MY] - y) < EPSILON) &&
|
||||||
|
(Math.abs(vertices[vertexCount-2][MZ] - z) < EPSILON)) {
|
||||||
|
vertexCount--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public void texture(PImage image) {
|
||||||
|
this.timage = image;
|
||||||
|
this.tpixels = image.pixels;
|
||||||
|
this.twidth = image.width;
|
||||||
|
this.theight = image.height;
|
||||||
|
this.tformat = image.format;
|
||||||
|
|
||||||
|
twidth1 = twidth - 1;
|
||||||
|
theight1 = theight - 1;
|
||||||
|
interpUV = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if (vertexCount < 3) return;
|
||||||
|
|
||||||
|
// these may have changed due to a resize()
|
||||||
|
// so they should be refreshed here
|
||||||
|
pixels = parent.pixels;
|
||||||
|
//zbuffer = parent.zbuffer;
|
||||||
|
|
||||||
|
noDepthTest = parent.hints[DISABLE_DEPTH_TEST];
|
||||||
|
smooth = parent.smooth;
|
||||||
|
|
||||||
|
// by default, text turns on smooth for the textures
|
||||||
|
// themselves. but this should be shut off if the hint
|
||||||
|
// for DISABLE_TEXT_SMOOTH is set.
|
||||||
|
texture_smooth = (//parent.drawing_text &&
|
||||||
|
!parent.hints[DISABLE_TEXT_SMOOTH]);
|
||||||
|
|
||||||
|
width = smooth ? parent.width*SUBXRES : parent.width;
|
||||||
|
height = smooth ? parent.height*SUBYRES : parent.height;
|
||||||
|
|
||||||
|
width1 = width - 1;
|
||||||
|
height1 = height - 1;
|
||||||
|
|
||||||
|
if (!interpARGB) {
|
||||||
|
r2 = (int) (vertices[0][R] * 255);
|
||||||
|
g2 = (int) (vertices[0][G] * 255);
|
||||||
|
b2 = (int) (vertices[0][B] * 255);
|
||||||
|
a2 = (int) (vertices[0][A] * 255);
|
||||||
|
a2orig = a2; // save an extra copy
|
||||||
|
rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
r[i] = 0; dr[i] = 0; l[i] = 0; dl[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hack to not make polygons fly into the screen
|
||||||
|
if (parent.hints[NO_FLYING_POO]) {
|
||||||
|
float nwidth2 = -width * 2;
|
||||||
|
float nheight2 = -height * 2;
|
||||||
|
float width2 = width * 2;
|
||||||
|
float height2 = height * 2;
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
if ((vertices[i][X] < nwidth2) ||
|
||||||
|
(vertices[i][X] > width2) ||
|
||||||
|
(vertices[i][Y] < nheight2) ||
|
||||||
|
(vertices[i][Y] > height2)) {
|
||||||
|
return; // this is a bad poly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
vertices[i][X] *= SUBXRES;
|
||||||
|
vertices[i][Y] *= SUBYRES;
|
||||||
|
}
|
||||||
|
firstModY = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find top vertex (y is zero at top, higher downwards)
|
||||||
|
int topi = 0;
|
||||||
|
float ymin = vertices[0][Y];
|
||||||
|
float ymax = vertices[0][Y]; // fry 031001
|
||||||
|
for (int i = 1; i < vertexCount; i++) {
|
||||||
|
if (vertices[i][Y] < ymin) {
|
||||||
|
ymin = vertices[i][Y];
|
||||||
|
topi = i;
|
||||||
|
}
|
||||||
|
if (vertices[i][Y] > ymax) ymax = vertices[i][Y];
|
||||||
|
}
|
||||||
|
|
||||||
|
// the last row is an exceptional case, because there won't
|
||||||
|
// necessarily be 8 rows of subpixel lines that will force
|
||||||
|
// the final line to render. so instead, the algo keeps track
|
||||||
|
// of the lastY (in subpixel resolution) that will be rendered
|
||||||
|
// and that will force a scanline to happen the same as
|
||||||
|
// every eighth in the other situations
|
||||||
|
//lastY = -1; // fry 031001
|
||||||
|
lastY = (int) (ymax - 0.5f); // global to class bc used by other fxns
|
||||||
|
|
||||||
|
int lefti = topi; // li, index of left vertex
|
||||||
|
int righti = topi; // ri, index of right vertex
|
||||||
|
int y = (int) (ymin + 0.5f); // current scan line
|
||||||
|
int lefty = y - 1; // lower end of left edge
|
||||||
|
int righty = y - 1; // lower end of right edge
|
||||||
|
|
||||||
|
interpX = true;
|
||||||
|
|
||||||
|
int remaining = vertexCount;
|
||||||
|
|
||||||
|
// scan in y, activating new edges on left & right
|
||||||
|
// as scan line passes over new vertices
|
||||||
|
while (remaining > 0) {
|
||||||
|
// advance left edge?
|
||||||
|
while ((lefty <= y) && (remaining > 0)) {
|
||||||
|
remaining--;
|
||||||
|
// step ccw down left side
|
||||||
|
int i = (lefti != 0) ? (lefti-1) : (vertexCount-1);
|
||||||
|
incrementalize_y(vertices[lefti], vertices[i], l, dl, y);
|
||||||
|
lefty = (int) (vertices[i][Y] + 0.5f);
|
||||||
|
lefti = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance right edge?
|
||||||
|
while ((righty <= y) && (remaining > 0)) {
|
||||||
|
remaining--;
|
||||||
|
// step cw down right edge
|
||||||
|
int i = (righti != vertexCount-1) ? (righti + 1) : 0;
|
||||||
|
incrementalize_y(vertices[righti], vertices[i], r, dr, y);
|
||||||
|
righty = (int) (vertices[i][Y] + 0.5f);
|
||||||
|
righti = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do scanlines till end of l or r edge
|
||||||
|
while (y < lefty && y < righty) {
|
||||||
|
// this doesn't work because it's not always set here
|
||||||
|
//if (remaining == 0) {
|
||||||
|
//lastY = (lefty < righty) ? lefty-1 : righty-1;
|
||||||
|
//System.out.println("lastY is " + lastY);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if ((y >= 0) && (y < height)) {
|
||||||
|
//try { // hopefully this bug is fixed
|
||||||
|
if (l[X] <= r[X]) scanline(y, l, r);
|
||||||
|
else scanline(y, r, l);
|
||||||
|
//} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
// this increment probably needs to be different
|
||||||
|
// UV and RGB shouldn't be incremented until line is emitted
|
||||||
|
increment(l, dl);
|
||||||
|
increment(r, dr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (smooth) {
|
||||||
|
//System.out.println("y/lasty/lastmody = " + y + " " + lastY + " " + lastModY);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void unexpand() {
|
||||||
|
if (smooth) {
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
vertices[i][X] /= SUBXRES;
|
||||||
|
vertices[i][Y] /= SUBYRES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void scanline(int y, float l[], float r[]) {
|
||||||
|
//System.out.println("scanline " + y);
|
||||||
|
for (int i = 0; i < vertexCount; i++) { // should be moved later
|
||||||
|
sp[i] = 0; sdp[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this rounding doesn't seem to be relevant with smooth
|
||||||
|
int lx = (int) (l[X] + 0.49999f); // ceil(l[X]-.5);
|
||||||
|
if (lx < 0) lx = 0;
|
||||||
|
int rx = (int) (r[X] - 0.5f);
|
||||||
|
if (rx > width1) rx = width1;
|
||||||
|
|
||||||
|
if (lx > rx) return;
|
||||||
|
|
||||||
|
if (smooth) {
|
||||||
|
int mody = MODYRES(y);
|
||||||
|
|
||||||
|
aaleft[mody] = lx;
|
||||||
|
aaright[mody] = rx;
|
||||||
|
|
||||||
|
if (firstModY == -1) {
|
||||||
|
firstModY = mody;
|
||||||
|
aaleftmin = lx; aaleftmax = lx;
|
||||||
|
aarightmin = rx; aarightmax = rx;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (aaleftmin > aaleft[mody]) aaleftmin = aaleft[mody];
|
||||||
|
if (aaleftmax < aaleft[mody]) aaleftmax = aaleft[mody];
|
||||||
|
if (aarightmin > aaright[mody]) aarightmin = aaright[mody];
|
||||||
|
if (aarightmax < aaright[mody]) aarightmax = aaright[mody];
|
||||||
|
}
|
||||||
|
|
||||||
|
lastModY = mody; // moved up here (before the return) 031001
|
||||||
|
// not the eighth (or lastY) line, so not scanning this time
|
||||||
|
if ((mody != SUBYRES1) && (y != lastY)) return;
|
||||||
|
//lastModY = mody; // eeK! this was missing
|
||||||
|
//return;
|
||||||
|
|
||||||
|
//if (y == lastY) {
|
||||||
|
//System.out.println("y is lasty");
|
||||||
|
//}
|
||||||
|
//lastModY = mody;
|
||||||
|
aaleftfull = aaleftmax/SUBXRES + 1;
|
||||||
|
aarightfull = aarightmin/SUBXRES - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the setup, based on lx
|
||||||
|
incrementalize_x(l, r, sp, sdp, lx);
|
||||||
|
|
||||||
|
// scan in x, generating pixels
|
||||||
|
// using parent.width to get actual pixel index
|
||||||
|
// rather than scaled by smooth factor
|
||||||
|
int offset = smooth ? parent.width * (y / SUBYRES) : parent.width*y;
|
||||||
|
|
||||||
|
int truelx = 0, truerx = 0;
|
||||||
|
if (smooth) {
|
||||||
|
truelx = lx / SUBXRES;
|
||||||
|
truerx = (rx + SUBXRES1) / SUBXRES;
|
||||||
|
|
||||||
|
lx = aaleftmin / SUBXRES;
|
||||||
|
rx = (aarightmax + SUBXRES1) / SUBXRES;
|
||||||
|
if (lx < 0) lx = 0;
|
||||||
|
if (rx > parent.width1) rx = parent.width1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interpX = false;
|
||||||
|
int tr, tg, tb, ta;
|
||||||
|
|
||||||
|
for (int x = lx; x <= rx; x++) {
|
||||||
|
// added == because things on same plane weren't replacing each other
|
||||||
|
// makes for strangeness in 3D, but totally necessary for 2D
|
||||||
|
//if (noDepthTest || (sp[Z] <= zbuffer[offset+x])) {
|
||||||
|
if (true) {
|
||||||
|
|
||||||
|
// map texture based on U, V coords in sp[U] and sp[V]
|
||||||
|
if (interpUV) {
|
||||||
|
int tu = (int)sp[U];
|
||||||
|
int tv = (int)sp[V];
|
||||||
|
|
||||||
|
if (tu > twidth1) tu = twidth1;
|
||||||
|
if (tv > theight1) tv = theight1;
|
||||||
|
if (tu < 0) tu = 0;
|
||||||
|
if (tv < 0) tv = 0;
|
||||||
|
|
||||||
|
int txy = tv*twidth + tu;
|
||||||
|
|
||||||
|
if (smooth || texture_smooth) {
|
||||||
|
//if (FRY) System.out.println("sp u v = " + sp[U] + " " + sp[V]);
|
||||||
|
//System.out.println("sp u v = " + sp[U] + " " + sp[V]);
|
||||||
|
// tuf1/tvf1 is the amount of coverage for the adjacent
|
||||||
|
// pixel, which is the decimal percentage.
|
||||||
|
int tuf1 = (int) (255f * (sp[U] - (float)tu));
|
||||||
|
int tvf1 = (int) (255f * (sp[V] - (float)tv));
|
||||||
|
|
||||||
|
// the closer sp[U or V] is to the decimal being zero
|
||||||
|
// the more coverage it should get of the original pixel
|
||||||
|
int tuf = 255 - tuf1;
|
||||||
|
int tvf = 255 - tvf1;
|
||||||
|
|
||||||
|
// this code sucks! filled with bugs and slow as hell!
|
||||||
|
int pixel00 = tpixels[txy];
|
||||||
|
int pixel01 = (tv < theight1) ?
|
||||||
|
tpixels[txy + twidth] : tpixels[txy];
|
||||||
|
int pixel10 = (tu < twidth1) ?
|
||||||
|
tpixels[txy + 1] : tpixels[txy];
|
||||||
|
int pixel11 = ((tv < theight1) && (tu < twidth1)) ?
|
||||||
|
tpixels[txy + twidth + 1] : tpixels[txy];
|
||||||
|
|
||||||
|
int p00, p01, p10, p11;
|
||||||
|
int px0, px1; //, pxy;
|
||||||
|
|
||||||
|
if (tformat == ALPHA) {
|
||||||
|
px0 = (pixel00*tuf + pixel10*tuf1) >> 8;
|
||||||
|
px1 = (pixel01*tuf + pixel11*tuf1) >> 8;
|
||||||
|
ta = (((px0*tvf + px1*tvf1) >> 8) *
|
||||||
|
(interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
|
||||||
|
|
||||||
|
} else if (tformat == ARGB) {
|
||||||
|
p00 = (pixel00 >> 24) & 0xff;
|
||||||
|
p01 = (pixel01 >> 24) & 0xff;
|
||||||
|
p10 = (pixel10 >> 24) & 0xff;
|
||||||
|
p11 = (pixel11 >> 24) & 0xff;
|
||||||
|
|
||||||
|
px0 = (p00*tuf + p10*tuf1) >> 8;
|
||||||
|
px1 = (p01*tuf + p11*tuf1) >> 8;
|
||||||
|
ta = (((px0*tvf + px1*tvf1) >> 8) *
|
||||||
|
(interpARGB ? ((int) (sp[A]*255)) : a2orig)) >> 8;
|
||||||
|
|
||||||
|
} else { // RGB image, no alpha
|
||||||
|
ta = interpARGB ? ((int) (sp[A]*255)) : a2orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tformat == RGB) || (tformat == ARGB)) {
|
||||||
|
p00 = (pixel00 >> 16) & 0xff; // red
|
||||||
|
p01 = (pixel01 >> 16) & 0xff;
|
||||||
|
p10 = (pixel10 >> 16) & 0xff;
|
||||||
|
p11 = (pixel11 >> 16) & 0xff;
|
||||||
|
|
||||||
|
px0 = (p00*tuf + p10*tuf1) >> 8;
|
||||||
|
px1 = (p01*tuf + p11*tuf1) >> 8;
|
||||||
|
tr = (((px0*tvf + px1*tvf1) >> 8) *
|
||||||
|
(interpARGB ? ((int) sp[R]*255) : r2)) >> 8;
|
||||||
|
|
||||||
|
|
||||||
|
p00 = (pixel00 >> 8) & 0xff; // green
|
||||||
|
p01 = (pixel01 >> 8) & 0xff;
|
||||||
|
p10 = (pixel10 >> 8) & 0xff;
|
||||||
|
p11 = (pixel11 >> 8) & 0xff;
|
||||||
|
|
||||||
|
px0 = (p00*tuf + p10*tuf1) >> 8;
|
||||||
|
px1 = (p01*tuf + p11*tuf1) >> 8;
|
||||||
|
tg = (((px0*tvf + px1*tvf1) >> 8) *
|
||||||
|
(interpARGB ? ((int) sp[G]*255) : g2)) >> 8;
|
||||||
|
|
||||||
|
|
||||||
|
p00 = pixel00 & 0xff; // blue
|
||||||
|
p01 = pixel01 & 0xff;
|
||||||
|
p10 = pixel10 & 0xff;
|
||||||
|
p11 = pixel11 & 0xff;
|
||||||
|
|
||||||
|
px0 = (p00*tuf + p10*tuf1) >> 8;
|
||||||
|
px1 = (p01*tuf + p11*tuf1) >> 8;
|
||||||
|
tb = (((px0*tvf + px1*tvf1) >> 8) *
|
||||||
|
(interpARGB ? ((int) sp[B]*255) : b2)) >> 8;
|
||||||
|
|
||||||
|
} else { // alpha image, only use current fill color
|
||||||
|
if (interpARGB) {
|
||||||
|
tr = (int) (sp[R] * 255);
|
||||||
|
tg = (int) (sp[G] * 255);
|
||||||
|
tb = (int) (sp[B] * 255);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tr = r2;
|
||||||
|
tg = g2;
|
||||||
|
tb = b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get coverage for pixel if smooth
|
||||||
|
// checks smooth again here because of
|
||||||
|
// hints[SMOOTH_IMAGES] used up above
|
||||||
|
int weight = smooth ? coverage(x) : 255;
|
||||||
|
if (weight != 255) ta = ta*weight >> 8;
|
||||||
|
|
||||||
|
} else { // no smooth, just get the pixels
|
||||||
|
int tpixel = tpixels[txy];
|
||||||
|
|
||||||
|
// TODO i doubt splitting these guys really gets us
|
||||||
|
// all that much speed.. is it worth it?
|
||||||
|
if (tformat == ALPHA) {
|
||||||
|
ta = tpixel;
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
tr = (int) sp[R]*255;
|
||||||
|
tg = (int) sp[G]*255;
|
||||||
|
tb = (int) sp[B]*255;
|
||||||
|
if (sp[A] != 1) {
|
||||||
|
ta = (((int) sp[A]*255) * ta) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tr = r2;
|
||||||
|
tg = g2;
|
||||||
|
tb = b2;
|
||||||
|
ta = (a2orig * ta) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // RGB or ARGB
|
||||||
|
ta = (tformat == RGB) ? 255 : (tpixel >> 24) & 0xff;
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
tr = (((int) sp[R]*255) * ((tpixel >> 16) & 0xff)) >> 8;
|
||||||
|
tg = (((int) sp[G]*255) * ((tpixel >> 8) & 0xff)) >> 8;
|
||||||
|
tb = (((int) sp[B]*255) * ((tpixel) & 0xff)) >> 8;
|
||||||
|
ta = (((int) sp[A]*255) * ta) >> 8;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tr = (r2 * ((tpixel >> 16) & 0xff)) >> 8;
|
||||||
|
tg = (g2 * ((tpixel >> 8) & 0xff)) >> 8;
|
||||||
|
tb = (b2 * ((tpixel) & 0xff)) >> 8;
|
||||||
|
ta = (a2orig * ta) >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ta == 254) || (ta == 255)) { // if (ta & 0xf8) would be good
|
||||||
|
// no need to blend
|
||||||
|
pixels[offset+x] = 0xff000000 | (tr << 16) | (tg << 8) | tb;
|
||||||
|
//zbuffer[offset+x] = sp[Z];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// blend with pixel on screen
|
||||||
|
int a1 = 255-ta;
|
||||||
|
int r1 = (pixels[offset+x] >> 16) & 0xff;
|
||||||
|
int g1 = (pixels[offset+x] >> 8) & 0xff;
|
||||||
|
int b1 = (pixels[offset+x]) & 0xff;
|
||||||
|
|
||||||
|
pixels[offset+x] = 0xff000000 |
|
||||||
|
(((tr*ta + r1*a1) >> 8) << 16) |
|
||||||
|
((tg*ta + g1*a1) & 0xff00) |
|
||||||
|
((tb*ta + b1*a1) >> 8);
|
||||||
|
//if (ta > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // no image applied
|
||||||
|
int weight = smooth ? coverage(x) : 255;
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
r2 = (int) (sp[R] * 255);
|
||||||
|
g2 = (int) (sp[G] * 255);
|
||||||
|
b2 = (int) (sp[B] * 255);
|
||||||
|
if (sp[A] != 1) weight = (weight * ((int) (sp[A] * 255))) >> 8;
|
||||||
|
if (weight == 255) {
|
||||||
|
rgba = 0xff000000 | (r2 << 16) | (g2 << 8) | b2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (a2orig != 255) weight = (weight * a2orig) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weight == 255) {
|
||||||
|
// no blend, no aa, just the rgba
|
||||||
|
pixels[offset+x] = rgba;
|
||||||
|
//zbuffer[offset+x] = sp[Z];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int r1 = (pixels[offset+x] >> 16) & 0xff;
|
||||||
|
int g1 = (pixels[offset+x] >> 8) & 0xff;
|
||||||
|
int b1 = (pixels[offset+x]) & 0xff;
|
||||||
|
a2 = weight;
|
||||||
|
|
||||||
|
int a1 = 255 - a2;
|
||||||
|
pixels[offset+x] = (0xff000000 |
|
||||||
|
((r1*a1 + r2*a2) >> 8) << 16 |
|
||||||
|
// use & instead of >> and << below
|
||||||
|
((g1*a1 + g2*a2) >> 8) << 8 |
|
||||||
|
((b1*a1 + b2*a2) >> 8));
|
||||||
|
|
||||||
|
//if (a2 > ZBUFFER_MIN_COVERAGE) zbuffer[offset+x] = sp[Z];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if smooth enabled, don't increment values
|
||||||
|
// for the pixel in the stretch out version
|
||||||
|
// of the scanline used to get smooth edges.
|
||||||
|
if (!smooth || ((x >= truelx) && (x <= truerx))) {
|
||||||
|
increment(sp, sdp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstModY = -1;
|
||||||
|
interpX = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// x is in screen, not huge 8x coordinates
|
||||||
|
private int coverage(int x) {
|
||||||
|
if ((x >= aaleftfull) && (x <= aarightfull) &&
|
||||||
|
// important since not all SUBYRES lines may have been covered
|
||||||
|
(firstModY == 0) && (lastModY == SUBYRES1)) {
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pixelLeft = x*SUBXRES; // huh?
|
||||||
|
int pixelRight = pixelLeft + 8;
|
||||||
|
|
||||||
|
int amt = 0;
|
||||||
|
for (int i = firstModY; i <= lastModY; i++) {
|
||||||
|
if ((aaleft[i] > pixelRight) || (aaright[i] < pixelLeft)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// does this need a +1 ?
|
||||||
|
amt += ((aaright[i] < pixelRight ? aaright[i] : pixelRight) -
|
||||||
|
(aaleft[i] > pixelLeft ? aaleft[i] : pixelLeft));
|
||||||
|
}
|
||||||
|
amt <<= 2;
|
||||||
|
return (amt == 256) ? 255 : amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void incrementalize_y(float p1[], float p2[],
|
||||||
|
float p[], float dp[], int y) {
|
||||||
|
float delta = p2[Y] - p1[Y];
|
||||||
|
if (delta == 0) delta = 1;
|
||||||
|
float fraction = y + 0.5f - p1[Y];
|
||||||
|
|
||||||
|
if (interpX) {
|
||||||
|
dp[X] = (p2[X] - p1[X]) / delta;
|
||||||
|
p[X] = p1[X] + dp[X] * fraction;
|
||||||
|
}
|
||||||
|
if (interpZ) {
|
||||||
|
dp[Z] = (p2[Z] - p1[Z]) / delta;
|
||||||
|
p[Z] = p1[Z] + dp[Z] * fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
dp[R] = (p2[R] - p1[R]) / delta;
|
||||||
|
dp[G] = (p2[G] - p1[G]) / delta;
|
||||||
|
dp[B] = (p2[B] - p1[B]) / delta;
|
||||||
|
dp[A] = (p2[A] - p1[A]) / delta;
|
||||||
|
p[R] = p1[R] + dp[R] * fraction;
|
||||||
|
p[G] = p1[G] + dp[G] * fraction;
|
||||||
|
p[B] = p1[B] + dp[B] * fraction;
|
||||||
|
p[A] = p1[A] + dp[A] * fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpUV) {
|
||||||
|
dp[U] = (p2[U] - p1[U]) / delta;
|
||||||
|
dp[V] = (p2[V] - p1[V]) / delta;
|
||||||
|
|
||||||
|
//if (smooth) {
|
||||||
|
//p[U] = p1[U]; //+ dp[U] * fraction;
|
||||||
|
//p[V] = p1[V]; //+ dp[V] * fraction;
|
||||||
|
|
||||||
|
//} else {
|
||||||
|
p[U] = p1[U] + dp[U] * fraction;
|
||||||
|
p[V] = p1[V] + dp[V] * fraction;
|
||||||
|
//}
|
||||||
|
if (FRY) System.out.println("inc y p[U] p[V] = " + p[U] + " " + p[V]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void incrementalize_x(float p1[], float p2[],
|
||||||
|
float p[], float dp[], int x) {
|
||||||
|
float delta = p2[X] - p1[X];
|
||||||
|
if (delta == 0) delta = 1;
|
||||||
|
float fraction = x + 0.5f - p1[X];
|
||||||
|
if (smooth) {
|
||||||
|
delta /= SUBXRES;
|
||||||
|
fraction /= SUBXRES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpX) {
|
||||||
|
dp[X] = (p2[X] - p1[X]) / delta;
|
||||||
|
p[X] = p1[X] + dp[X] * fraction;
|
||||||
|
}
|
||||||
|
if (interpZ) {
|
||||||
|
dp[Z] = (p2[Z] - p1[Z]) / delta;
|
||||||
|
p[Z] = p1[Z] + dp[Z] * fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
dp[R] = (p2[R] - p1[R]) / delta;
|
||||||
|
dp[G] = (p2[G] - p1[G]) / delta;
|
||||||
|
dp[B] = (p2[B] - p1[B]) / delta;
|
||||||
|
dp[A] = (p2[A] - p1[A]) / delta;
|
||||||
|
p[R] = p1[R] + dp[R] * fraction;
|
||||||
|
p[G] = p1[G] + dp[G] * fraction;
|
||||||
|
p[B] = p1[B] + dp[B] * fraction;
|
||||||
|
p[A] = p1[A] + dp[A] * fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpUV) {
|
||||||
|
if (FRY) System.out.println("delta, frac = " + delta + ", " + fraction);
|
||||||
|
dp[U] = (p2[U] - p1[U]) / delta;
|
||||||
|
dp[V] = (p2[V] - p1[V]) / delta;
|
||||||
|
|
||||||
|
//if (smooth) {
|
||||||
|
//p[U] = p1[U];
|
||||||
|
// offset for the damage that will be done by the
|
||||||
|
// 8 consecutive calls to scanline
|
||||||
|
// agh.. this won't work b/c not always 8 calls before render
|
||||||
|
// maybe lastModY - firstModY + 1 instead?
|
||||||
|
if (FRY) System.out.println("before inc x p[V] = " + p[V] + " " + p1[V] + " " + p2[V]);
|
||||||
|
//p[V] = p1[V] - SUBXRES1 * fraction;
|
||||||
|
|
||||||
|
//} else {
|
||||||
|
p[U] = p1[U] + dp[U] * fraction;
|
||||||
|
p[V] = p1[V] + dp[V] * fraction;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void increment(float p[], float dp[]) {
|
||||||
|
if (interpX) p[X] += dp[X];
|
||||||
|
if (interpZ) p[Z] += dp[Z];
|
||||||
|
|
||||||
|
if (interpARGB) {
|
||||||
|
p[R] += dp[R];
|
||||||
|
p[G] += dp[G];
|
||||||
|
p[B] += dp[B];
|
||||||
|
p[A] += dp[A];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpUV) {
|
||||||
|
if (FRY) System.out.println("increment() " + p[V] + " " + dp[V]);
|
||||||
|
p[U] += dp[U];
|
||||||
|
p[V] += dp[V];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
289
core/PShape.java
Normal file
289
core/PShape.java
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Part of the Processing project - http://processing.org
|
||||||
|
|
||||||
|
Copyright (c) 2006 Ben Fry and Casey Reas
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package processing.core;
|
||||||
|
|
||||||
|
|
||||||
|
// take a look at the obj loader to see how this fits with things
|
||||||
|
|
||||||
|
// PShape.line() PShape.ellipse()?
|
||||||
|
// PShape s = beginShape()
|
||||||
|
// line()
|
||||||
|
// endShape(s)
|
||||||
|
|
||||||
|
public class PShape {
|
||||||
|
|
||||||
|
int kind;
|
||||||
|
PMatrix matrix;
|
||||||
|
|
||||||
|
int[] opcode;
|
||||||
|
int opcodeCount;
|
||||||
|
// need to reorder vertex fields to make a VERTEX_SHORT_COUNT
|
||||||
|
// that puts all the non-rendering fields into later indices
|
||||||
|
float[][] data; // second param is the VERTEX_FIELD_COUNT
|
||||||
|
// should this be called vertices (consistent with PGraphics internals)
|
||||||
|
// or does that hurt flexibility?
|
||||||
|
|
||||||
|
int childCount;
|
||||||
|
PShape[] children;
|
||||||
|
|
||||||
|
// POINTS, LINES, xLINE_STRIP, xLINE_LOOP
|
||||||
|
// TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
|
||||||
|
// QUADS, QUAD_STRIP
|
||||||
|
// xPOLYGON
|
||||||
|
static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP
|
||||||
|
static final int GROUP = 2;
|
||||||
|
|
||||||
|
// how to handle rectmode/ellipsemode?
|
||||||
|
// are they bitshifted into the constant?
|
||||||
|
// CORNER, CORNERS, CENTER, (CENTER_RADIUS?)
|
||||||
|
static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2
|
||||||
|
static final int ELLIPSE = 4;
|
||||||
|
|
||||||
|
static final int VERTEX = 7;
|
||||||
|
static final int CURVE = 5;
|
||||||
|
static final int BEZIER = 6;
|
||||||
|
|
||||||
|
|
||||||
|
// fill and stroke functions will need a pointer to the parent
|
||||||
|
// PGraphics object.. may need some kind of createShape() fxn
|
||||||
|
// or maybe the values are stored until draw() is called?
|
||||||
|
|
||||||
|
// attaching images is very tricky.. it's a different type of data
|
||||||
|
|
||||||
|
// material parameters will be thrown out,
|
||||||
|
// except those currently supported (kinds of lights)
|
||||||
|
|
||||||
|
// setAxis -> .x and .y to move x and y coords of origin
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
|
||||||
|
// pivot point for transformations
|
||||||
|
public float px;
|
||||||
|
public float py;
|
||||||
|
|
||||||
|
|
||||||
|
public PShape() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PShape(float x, float y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the following (the shape() command adds the g)
|
||||||
|
* PShape s = loadShapes("blah.svg");
|
||||||
|
* shape(s);
|
||||||
|
*/
|
||||||
|
public void draw(PGraphics g) {
|
||||||
|
boolean flat = g instanceof PGraphics3D;
|
||||||
|
|
||||||
|
if (matrix != null) {
|
||||||
|
g.pushMatrix();
|
||||||
|
if (flat) {
|
||||||
|
g.applyMatrix(matrix.m00, matrix.m01, matrix.m02,
|
||||||
|
matrix.m10, matrix.m11, matrix.m12);
|
||||||
|
} else {
|
||||||
|
g.applyMatrix(matrix.m00, matrix.m01, matrix.m02, matrix.m03,
|
||||||
|
matrix.m10, matrix.m11, matrix.m12, matrix.m13,
|
||||||
|
matrix.m20, matrix.m21, matrix.m22, matrix.m23,
|
||||||
|
matrix.m30, matrix.m31, matrix.m32, matrix.m33);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if g subclasses PGraphics2, ignore all lighting stuff and z coords
|
||||||
|
// otherwise if PGraphics3, need to call diffuse() etc
|
||||||
|
|
||||||
|
// unfortunately, also a problem with no way to encode stroke/fill
|
||||||
|
// being enabled/disabled.. this quickly gets into just having opcodes
|
||||||
|
// for the entire api, to deal with things like textures and images
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case PATH:
|
||||||
|
for (int i = 0; i < opcodeCount; i++) {
|
||||||
|
switch (opcode[i]) {
|
||||||
|
case VERTEX:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GROUP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RECT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matrix != null) {
|
||||||
|
g.popMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
|
// can't be 'add' because that suggests additive geometry
|
||||||
|
public void addChild(PShape who) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PShape createGroup() {
|
||||||
|
PShape group = new PShape();
|
||||||
|
group.kind = GROUP;
|
||||||
|
addChild(group);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
|
// translate, rotate, scale, apply (no push/pop)
|
||||||
|
// these each call matrix.translate, etc
|
||||||
|
// if matrix is null when one is called,
|
||||||
|
// it is created and set to identity
|
||||||
|
|
||||||
|
|
||||||
|
public void translate(float tx, float ty) {
|
||||||
|
translate(tx, ty, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void translate(float tx, float ty, float tz) {
|
||||||
|
checkMatrix();
|
||||||
|
matrix.translate(tx, ty, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
public void rotateX(float angle) {
|
||||||
|
rotate(angle, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateY(float angle) {
|
||||||
|
rotate(angle, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateZ(float angle) {
|
||||||
|
rotate(angle, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate(float angle) {
|
||||||
|
rotateZ(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate(float angle, float v0, float v1, float v2) {
|
||||||
|
checkMatrix();
|
||||||
|
matrix.rotate(angle, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
public void scale(float s) {
|
||||||
|
scale(s, s, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale(float sx, float sy) {
|
||||||
|
scale(sx, sy, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale(float x, float y, float z) {
|
||||||
|
checkMatrix();
|
||||||
|
matrix.scale(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
public void applyMatrix(float n00, float n01, float n02,
|
||||||
|
float n10, float n11, float n12) {
|
||||||
|
checkMatrix();
|
||||||
|
matrix.apply(n00, n01, n02, 0,
|
||||||
|
n10, n11, n12, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyMatrix(float n00, float n01, float n02, float n03,
|
||||||
|
float n10, float n11, float n12, float n13,
|
||||||
|
float n20, float n21, float n22, float n23,
|
||||||
|
float n30, float n31, float n32, float n33) {
|
||||||
|
checkMatrix();
|
||||||
|
matrix.apply(n00, n01, n02, n03,
|
||||||
|
n10, n11, n12, n13,
|
||||||
|
n20, n21, n22, n23,
|
||||||
|
n30, n31, n32, n33);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
protected void checkMatrix() {
|
||||||
|
if (matrix == null) {
|
||||||
|
matrix = new PMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Center the shape based on its bounding box. Can't assume
|
||||||
|
* that the bounding box is 0, 0, width, height. Common case will be
|
||||||
|
* opening a letter size document in Illustrator, and drawing something
|
||||||
|
* in the middle, then reading it in as an svg file.
|
||||||
|
* This will also need to flip the y axis (scale(1, -1)) in cases
|
||||||
|
* like Adobe Illustrator where the coordinates start at the bottom.
|
||||||
|
*/
|
||||||
|
public void center() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the pivot point for all transformations.
|
||||||
|
*/
|
||||||
|
public void pivot(float x, float y) {
|
||||||
|
px = x;
|
||||||
|
py = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
3827
core/PTriangle.java
Normal file
3827
core/PTriangle.java
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user