mirror of
https://github.com/esp8266/Arduino.git
synced 2025-08-07 00:04:36 +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.ice.jni.registry.*;
|
||||
|
||||
import processing.core.*;
|
||||
|
||||
|
||||
/**
|
||||
@@ -52,21 +53,8 @@ import com.ice.jni.registry.*;
|
||||
* files and images, etc) that comes from that.
|
||||
*/
|
||||
public class Base {
|
||||
static final int VERSION = 3;
|
||||
static final int VERSION = 10;
|
||||
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,
|
||||
@@ -76,79 +64,18 @@ public class Base {
|
||||
|
||||
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[]) {
|
||||
|
||||
// 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");
|
||||
// Base.showError("Need to install Java 1.4",
|
||||
// "This version of Arduino requires \n" +
|
||||
// "Java 1.4 or later to run properly.\n" +
|
||||
// "Please visit java.com to upgrade.", null);
|
||||
// }
|
||||
Base.showError("Need to install Java 1.4",
|
||||
"This version of Processing requires \n" +
|
||||
"Java 1.4 or later to run properly.\n" +
|
||||
"Please visit java.com to upgrade.", null);
|
||||
}
|
||||
|
||||
|
||||
// grab any opened file from the command line
|
||||
@@ -183,14 +110,34 @@ public class Base {
|
||||
// set the look and feel before opening the window
|
||||
|
||||
try {
|
||||
if (Base.isLinux()) {
|
||||
// linux is by default (motif?) even uglier than metal
|
||||
// actually, i'm using native menus, so they're ugly and
|
||||
// motif-looking. ick. need to fix this.
|
||||
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
|
||||
if (Base.isMacOS()) {
|
||||
// Use the Quaqua L & F on OS X to make JFileChooser less awful
|
||||
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
|
||||
// undo quaqua trying to fix the margins, since we've already
|
||||
// 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 {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -228,7 +175,7 @@ public class Base {
|
||||
* specifically a Mac OS X machine because it doesn't un on OS 9 anymore.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
static public boolean isWindows() {
|
||||
return platform == WINDOWS;
|
||||
return PApplet.platform == PConstants.WINDOWS;
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +191,7 @@ public class Base {
|
||||
* true if running on linux.
|
||||
*/
|
||||
static public boolean isLinux() {
|
||||
return platform == LINUX;
|
||||
return PApplet.platform == PConstants.LINUX;
|
||||
}
|
||||
|
||||
|
||||
@@ -472,8 +419,9 @@ public class Base {
|
||||
sketchbookFolder = new File(documentsFolder, "Arduino");
|
||||
|
||||
} catch (Exception e) {
|
||||
showError("sketch folder problem",
|
||||
"Could not locate default sketch folder location.", e);
|
||||
//showError("Could not find folder",
|
||||
// "Could not locate the Documents folder.", e);
|
||||
sketchbookFolder = promptSketchbookLocation();
|
||||
}
|
||||
|
||||
} else if (isWindows()) {
|
||||
@@ -502,11 +450,15 @@ public class Base {
|
||||
sketchbookFolder = new File(personalPath, "Arduino");
|
||||
|
||||
} catch (Exception e) {
|
||||
showError("Problem getting documents folder",
|
||||
"Error getting the Arduino sketchbook folder.", e);
|
||||
//showError("Problem getting folder",
|
||||
// "Could not locate the Documents folder.", e);
|
||||
sketchbookFolder = promptSketchbookLocation();
|
||||
}
|
||||
|
||||
} else {
|
||||
sketchbookFolder = promptSketchbookLocation();
|
||||
|
||||
/*
|
||||
// on linux (or elsewhere?) prompt the user for the location
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setDialogTitle("Select the folder where " +
|
||||
@@ -523,6 +475,7 @@ public class Base {
|
||||
} else {
|
||||
System.exit(0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// jnireg seems to be reading the chars as bytes
|
||||
// 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) {
|
||||
String currentDir = System.getProperty("user.dir");
|
||||
openURL(currentDir + File.separator +
|
||||
"reference" + File.separator +
|
||||
referenceFile + ".html");
|
||||
openURL(Base.getContents("reference" + File.separator + referenceFile));
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
* 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) {
|
||||
//System.out.println("opening url " + url);
|
||||
@@ -707,11 +746,19 @@ public class Base {
|
||||
} else if (Base.isLinux()) {
|
||||
// how's mozilla sound to ya, laddie?
|
||||
//Runtime.getRuntime().exec(new String[] { "mozilla", url });
|
||||
String browser = Preferences.get("browser");
|
||||
Runtime.getRuntime().exec(new String[] { browser, url });
|
||||
|
||||
//String browser = Preferences.get("browser");
|
||||
//Runtime.getRuntime().exec(new String[] { browser, url });
|
||||
String launcher = Preferences.get("launcher.linux");
|
||||
if (launcher != null) {
|
||||
Runtime.getRuntime().exec(new String[] { launcher, url });
|
||||
}
|
||||
} 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) {
|
||||
@@ -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
|
||||
* a folder in the machine's native file browser.
|
||||
@@ -742,6 +819,11 @@ public class Base {
|
||||
} else if (Base.isMacOS()) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
@@ -780,7 +862,7 @@ public class Base {
|
||||
* for errors that allow P5 to continue running.
|
||||
*/
|
||||
static public void showError(String title, String message,
|
||||
Exception e) {
|
||||
Throwable e) {
|
||||
if (title == null) title = "Error";
|
||||
JOptionPane.showMessageDialog(new Frame(), message, title,
|
||||
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) {
|
||||
Image image = null;
|
||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||
|
||||
//if ((Base.platform == Base.MACOSX) ||
|
||||
//(Base.platform == Base.MACOS9)) {
|
||||
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);
|
||||
image = tk.getImage(getLibContents(name));
|
||||
MediaTracker tracker = new MediaTracker(who);
|
||||
tracker.addImage(image, 0);
|
||||
try {
|
||||
tracker.waitForAll();
|
||||
@@ -819,17 +907,7 @@ public class Base {
|
||||
|
||||
|
||||
static public InputStream getStream(String filename) throws IOException {
|
||||
//if (Base.platform == Base.MACOSX) {
|
||||
// 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();
|
||||
return new FileInputStream(getLibContents(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -965,7 +1043,7 @@ public class Base {
|
||||
if (!Preferences.getBoolean("compiler.save_build_files")) {
|
||||
if (!dead.delete()) {
|
||||
// temporarily disabled
|
||||
//System.err.println("couldn't delete " + dead);
|
||||
System.err.println("Could not delete " + dead);
|
||||
}
|
||||
}
|
||||
} 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.tools.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.*;
|
||||
import java.awt.dnd.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.print.*;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
@@ -45,7 +47,9 @@ import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.undo.*;
|
||||
|
||||
import com.apple.mrj.*;
|
||||
import com.oroinc.text.regex.*;
|
||||
//import de.hunsicker.jalopy.*;
|
||||
|
||||
import com.apple.mrj.*;
|
||||
import gnu.io.*;
|
||||
@@ -78,6 +82,9 @@ public class Editor extends JFrame
|
||||
boolean handleNewShift;
|
||||
boolean handleNewLibrary;
|
||||
|
||||
PageFormat pageFormat;
|
||||
PrinterJob printerJob;
|
||||
|
||||
EditorButtons buttons;
|
||||
EditorHeader header;
|
||||
EditorStatus status;
|
||||
@@ -133,14 +140,12 @@ public class Editor extends JFrame
|
||||
// used internally, and only briefly
|
||||
CompoundEdit compoundEdit;
|
||||
|
||||
//static public UndoManager undo = new UndoManager(); // editor needs this guy
|
||||
|
||||
//
|
||||
|
||||
//SketchHistory history; // TODO re-enable history
|
||||
Sketchbook sketchbook;
|
||||
//Preferences preferences;
|
||||
//FindReplace find;
|
||||
FindReplace find;
|
||||
|
||||
//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
|
||||
addWindowListener(new WindowAdapter() {
|
||||
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();
|
||||
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
|
||||
//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());
|
||||
contentPain.add(pain, BorderLayout.CENTER);
|
||||
|
||||
Box box = Box.createVerticalBox();
|
||||
Box upper = Box.createVerticalBox();
|
||||
@@ -251,6 +266,17 @@ public class Editor extends JFrame
|
||||
listener = new EditorListener(this, textarea);
|
||||
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() {
|
||||
|
||||
public void dragEnter(DropTargetDragEvent event) {
|
||||
@@ -278,14 +304,17 @@ public class Editor extends JFrame
|
||||
|
||||
Transferable transferable = event.getTransferable();
|
||||
DataFlavor flavors[] = transferable.getTransferDataFlavors();
|
||||
*/
|
||||
int successful = 0;
|
||||
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
try {
|
||||
//System.out.println(flavors[i]);
|
||||
//System.out.println(transferable.getTransferData(flavors[i]));
|
||||
java.util.List list =
|
||||
(java.util.List) transferable.getTransferData(flavors[i]);
|
||||
Object stuff = 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++) {
|
||||
Object item = list.get(j);
|
||||
if (item instanceof File) {
|
||||
@@ -298,7 +327,7 @@ public class Editor extends JFrame
|
||||
File parent = file.getParentFile();
|
||||
if (name.equals(parent.getName())) {
|
||||
handleOpenFile(file);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +339,7 @@ public class Editor extends JFrame
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +352,7 @@ public class Editor extends JFrame
|
||||
} else {
|
||||
message(successful + " files added to the sketch.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -488,7 +519,9 @@ public class Editor extends JFrame
|
||||
listener.applyPreferences();
|
||||
|
||||
// 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();
|
||||
|
||||
item = newJMenuItem("Page Setup", 'P', true);
|
||||
item.setEnabled(false);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handlePageSetup();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
item = newJMenuItem("Print", 'P');
|
||||
item.setEnabled(false);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handlePrint();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
// macosx already has its own preferences and quit menu
|
||||
@@ -600,7 +641,7 @@ public class Editor extends JFrame
|
||||
item = newJMenuItem("Quit", 'Q');
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handleQuit();
|
||||
handleQuitInternal();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@@ -639,17 +680,9 @@ public class Editor extends JFrame
|
||||
|
||||
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());
|
||||
|
||||
if (Base.isWindows() || Base.isMacOS()) {
|
||||
//if (Base.isWindows() || Base.isMacOS()) {
|
||||
// no way to do an 'open in file browser' on other platforms
|
||||
// since there isn't any sort of standard
|
||||
item = newJMenuItem("Show Sketch Folder", 'K', false);
|
||||
@@ -660,8 +693,20 @@ public class Editor extends JFrame
|
||||
}
|
||||
});
|
||||
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
|
||||
//history.attachMenu(menu);
|
||||
return menu;
|
||||
@@ -681,20 +726,39 @@ public class Editor extends JFrame
|
||||
item.addActionListener(new ActionListener() {
|
||||
synchronized public void actionPerformed(ActionEvent e) {
|
||||
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);
|
||||
|
||||
/*item = new JMenuItem("Create Font...");
|
||||
item = new JMenuItem("Copy for Discourse");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//new CreateFont().show(sketch.dataFolder);
|
||||
new CreateFont(Editor.this).show();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
new DiscourseFormat(Editor.this).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
*/
|
||||
|
||||
item = new JMenuItem("Archive Sketch");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -706,13 +770,17 @@ public class Editor extends JFrame
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
/*
|
||||
item = new JMenuItem("Export Folder...");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
new ExportFolder(Editor.this).show();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
*/
|
||||
menu.addSeparator();
|
||||
|
||||
mcuMenu = new JMenu("Microcontroller (MCU)");
|
||||
@@ -946,21 +1014,18 @@ public class Editor extends JFrame
|
||||
menu.add(item);
|
||||
}
|
||||
|
||||
item = new JMenuItem("Troubleshooting");
|
||||
item = new JMenuItem("Environment");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
||||
"reference" + File.separator +
|
||||
"Guide_Troubleshooting.html");
|
||||
Base.showEnvironment();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
item = new JMenuItem("Environment");
|
||||
item = new JMenuItem("Troubleshooting");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
||||
"reference" + File.separator + "Guide_Environment.html");
|
||||
Base.showTroubleshooting();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@@ -968,8 +1033,17 @@ public class Editor extends JFrame
|
||||
item = new JMenuItem("Reference");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
||||
"reference" + File.separator + "index.html");
|
||||
Base.showReference();
|
||||
}
|
||||
});
|
||||
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);
|
||||
@@ -977,33 +1051,11 @@ public class Editor extends JFrame
|
||||
item = new JMenuItem("Frequently Asked Questions");
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Base.openURL(System.getProperty("user.dir") + File.separator +
|
||||
"reference" + File.separator + "FAQ.html");
|
||||
Base.showFAQ();
|
||||
}
|
||||
});
|
||||
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.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -1083,22 +1135,27 @@ public class Editor extends JFrame
|
||||
item = newJMenuItem("Find...", 'F');
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new FindReplace(Editor.this).show();
|
||||
//find.show();
|
||||
if (find == null) {
|
||||
find = new FindReplace(Editor.this);
|
||||
}
|
||||
//new FindReplace(Editor.this).show();
|
||||
find.show();
|
||||
//find.setVisible(true);
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
// TODO find next should only be enabled after a
|
||||
// search has actually taken place
|
||||
item = newJMenuItem("Find Next", 'G');
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// TODO find next should only be enabled after a
|
||||
// search has actually taken place
|
||||
if (find != null) {
|
||||
//find.find(true);
|
||||
FindReplace find = new FindReplace(Editor.this); //.show();
|
||||
//FindReplace find = new FindReplace(Editor.this); //.show();
|
||||
find.find(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
@@ -1116,9 +1173,9 @@ public class Editor extends JFrame
|
||||
|
||||
/**
|
||||
* A software engineer, somewhere, needs to have his abstraction
|
||||
* taken away. In some countries they jail people for writing the
|
||||
* sort of crappy api that would require a four line helper function
|
||||
* to set the command key for a menu item.
|
||||
* taken away. In some countries they jail or beat people for writing
|
||||
* the sort of API that would require a five line helper function
|
||||
* just to set the command key for a menu item.
|
||||
*/
|
||||
static public JMenuItem newJMenuItem(String title,
|
||||
int what, boolean shift) {
|
||||
@@ -1191,7 +1248,6 @@ public class Editor extends JFrame
|
||||
|
||||
protected void updateRedoState() {
|
||||
if (undo.canRedo()) {
|
||||
//this.setEnabled(true);
|
||||
redoItem.setEnabled(true);
|
||||
redoItem.setText(undo.getRedoPresentationName());
|
||||
putValue(Action.NAME, undo.getRedoPresentationName());
|
||||
@@ -1339,10 +1395,12 @@ public class Editor extends JFrame
|
||||
redoAction.updateRedoState();
|
||||
}
|
||||
|
||||
|
||||
public void beginCompoundEdit() {
|
||||
compoundEdit = new CompoundEdit();
|
||||
}
|
||||
|
||||
|
||||
public void endCompoundEdit() {
|
||||
compoundEdit.end();
|
||||
undo.addEdit(compoundEdit);
|
||||
@@ -1352,6 +1410,8 @@ public class Editor extends JFrame
|
||||
}
|
||||
|
||||
|
||||
// ...................................................................
|
||||
|
||||
|
||||
public void handleRun(final boolean present) {
|
||||
doClose();
|
||||
@@ -1576,42 +1636,71 @@ public class Editor extends JFrame
|
||||
String prompt = "Save changes to " + sketch.name + "? ";
|
||||
|
||||
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.
|
||||
status.prompt(prompt);
|
||||
|
||||
} else {
|
||||
// if the user selected quit, then this has to be done with
|
||||
// a JOptionPane instead of internally in the editor.
|
||||
// TODO this is actually just a bug to be fixed.
|
||||
|
||||
// macosx java kills the app even though cancel might get hit
|
||||
// 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 (!Base.isMacOS() || PApplet.javaVersion < 1.5f) {
|
||||
int result =
|
||||
JOptionPane.showConfirmDialog(this, prompt, "Quit",
|
||||
JOptionPane.YES_NO_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
handleSave(true);
|
||||
checkModified2();
|
||||
|
||||
} else if (result == JOptionPane.NO_OPTION) {
|
||||
checkModified2(); // though this may just quit
|
||||
checkModified2();
|
||||
}
|
||||
// cancel is ignored altogether
|
||||
|
||||
} else if (result == JOptionPane.CANCEL_OPTION) {
|
||||
// ignored
|
||||
} else {
|
||||
// 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.
|
||||
* 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();
|
||||
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 (Base.calcFolderSize(sketch.folder) == 0) {
|
||||
Base.removeDir(sketch.folder);
|
||||
sketchbook.rebuildMenus();
|
||||
//sketchbook.rebuildMenus();
|
||||
sketchbook.rebuildMenusAsync();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) { } // oh well
|
||||
@@ -1893,7 +1989,11 @@ public class Editor extends JFrame
|
||||
message(EMPTY);
|
||||
}
|
||||
// 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) {
|
||||
// show the error as a message in the window
|
||||
@@ -1918,7 +2018,10 @@ public class Editor extends JFrame
|
||||
try {
|
||||
if (sketch.saveAs()) {
|
||||
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 {
|
||||
message("Save Cancelled.");
|
||||
}
|
||||
@@ -2007,6 +2110,7 @@ public class Editor extends JFrame
|
||||
null,
|
||||
options,
|
||||
options[0]);
|
||||
|
||||
if (result == JOptionPane.OK_OPTION) {
|
||||
handleSave(true);
|
||||
|
||||
@@ -2021,13 +2125,57 @@ public class Editor extends JFrame
|
||||
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
|
||||
* to disk just in case they want to quit. Final exit() happens
|
||||
* in Editor since it has the callback from EditorStatus.
|
||||
*/
|
||||
public void handleQuit() {
|
||||
public void handleQuitInternal() {
|
||||
// doStop() isn't sufficient with external vm & quit
|
||||
// instead use doClose() which will kill the external vm
|
||||
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.
|
||||
*/
|
||||
@@ -2050,6 +2219,26 @@ public class Editor extends JFrame
|
||||
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) {
|
||||
if(debugging)
|
||||
doStop();
|
||||
@@ -2083,6 +2272,7 @@ public class Editor extends JFrame
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
public void highlightLine(int lnum) {
|
||||
if (lnum < 0) {
|
||||
textarea.select(0, 0);
|
||||
@@ -2169,7 +2359,7 @@ public class Editor extends JFrame
|
||||
|
||||
|
||||
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.line >= 0) highlightLine(e.line);
|
||||
|
||||
@@ -2205,7 +2395,7 @@ public class Editor extends JFrame
|
||||
* Returns the edit popup menu.
|
||||
*/
|
||||
class TextAreaPopup extends JPopupMenu {
|
||||
String currentDir = System.getProperty("user.dir");
|
||||
//String currentDir = System.getProperty("user.dir");
|
||||
String referenceFile = null;
|
||||
|
||||
JMenuItem cutItem, copyItem;
|
||||
@@ -2251,13 +2441,14 @@ public class Editor extends JFrame
|
||||
|
||||
this.addSeparator();
|
||||
|
||||
// referenceItem = new JMenuItem("Find in Reference");
|
||||
// referenceItem.addActionListener(new ActionListener() {
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// Base.showReference(referenceFile);
|
||||
// }
|
||||
// });
|
||||
// this.add(referenceItem);
|
||||
referenceItem = new JMenuItem("Find in Reference");
|
||||
referenceItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//Base.showReference(referenceFile + ".html");
|
||||
handleReference(); //textarea.getSelectedText());
|
||||
}
|
||||
});
|
||||
this.add(referenceItem);
|
||||
}
|
||||
|
||||
// if no text is selected, disable copy and cut menu items
|
||||
@@ -2266,14 +2457,14 @@ public class Editor extends JFrame
|
||||
cutItem.setEnabled(true);
|
||||
copyItem.setEnabled(true);
|
||||
|
||||
//referenceFile = PdeKeywords.getReference(textarea.getSelectedText());
|
||||
//if (referenceFile != null) {
|
||||
//referenceItem.setEnabled(true);
|
||||
//}
|
||||
String sel = textarea.getSelectedText().trim();
|
||||
referenceFile = PdeKeywords.getReference(sel);
|
||||
referenceItem.setEnabled(referenceFile != null);
|
||||
|
||||
} else {
|
||||
cutItem.setEnabled(false);
|
||||
copyItem.setEnabled(false);
|
||||
//referenceItem.setEnabled(false);
|
||||
referenceItem.setEnabled(false);
|
||||
}
|
||||
super.show(component, x, y);
|
||||
}
|
||||
|
@@ -241,6 +241,7 @@ public class EditorHeader extends JComponent {
|
||||
|
||||
|
||||
public void rebuildMenu() {
|
||||
//System.out.println("rebuilding");
|
||||
if (menu != null) {
|
||||
menu.removeAll();
|
||||
|
||||
@@ -248,6 +249,9 @@ public class EditorHeader extends JComponent {
|
||||
menu = new JMenu();
|
||||
popup = menu.getPopupMenu();
|
||||
add(popup);
|
||||
popup.setLightWeightPopupEnabled(true);
|
||||
|
||||
/*
|
||||
popup.addPopupMenuListener(new PopupMenuListener() {
|
||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||
// on redraw, the isVisible() will get checked.
|
||||
@@ -259,6 +263,7 @@ public class EditorHeader extends JComponent {
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
|
||||
});
|
||||
*/
|
||||
}
|
||||
JMenuItem item;
|
||||
|
||||
@@ -352,6 +357,43 @@ public class EditorHeader extends JComponent {
|
||||
}
|
||||
|
||||
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) {
|
||||
menu.addSeparator();
|
||||
|
@@ -60,6 +60,10 @@ public class EditorListener {
|
||||
int selectionStart, selectionEnd;
|
||||
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) {
|
||||
this.editor = editor;
|
||||
@@ -105,6 +109,16 @@ public class EditorListener {
|
||||
//System.out.println(c + " " + code + " " + event);
|
||||
//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) {
|
||||
//event.consume(); // does nothing
|
||||
return false;
|
||||
@@ -195,8 +209,8 @@ public class EditorListener {
|
||||
|
||||
switch ((int) c) {
|
||||
|
||||
case 9: // expand tabs
|
||||
if (tabsExpand) {
|
||||
case 9:
|
||||
if (tabsExpand) { // expand tabs
|
||||
textarea.setSelectedText(tabString);
|
||||
event.consume();
|
||||
return true;
|
||||
@@ -286,12 +300,40 @@ public class EditorListener {
|
||||
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 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
|
||||
// the caret position, so that the number of spaces aren't
|
||||
// just being duplicated again
|
||||
// the caret position and count the number of spaces,
|
||||
// so that the number of spaces aren't duplicated again
|
||||
int index = origIndex + 1;
|
||||
int extraCount = 0;
|
||||
while ((index < contents.length) &&
|
||||
@@ -300,23 +342,58 @@ public class EditorListener {
|
||||
extraCount++;
|
||||
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
|
||||
// can cause trouble. for simplicity's sake, just ignore this case.
|
||||
//if (spaceCount < 0) spaceCount = origCount;
|
||||
// can cause trouble. for 0099, was ignoring the case, but this is
|
||||
// annoying, so in 0122 we're trying to fix that.
|
||||
/*
|
||||
if (spaceCount - extraCount > 0) {
|
||||
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
|
||||
if (origIndex != -1) {
|
||||
if (contents[origIndex] == '{') {
|
||||
spaceCount += tabSize;
|
||||
}
|
||||
}
|
||||
// now, check to see if the current line contains a } and if so,
|
||||
// outdent again by indent
|
||||
//if (braceCount > 0) {
|
||||
//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);
|
||||
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
|
||||
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.
|
||||
*/
|
||||
|
@@ -57,6 +57,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
|
||||
JButton replaceButton;
|
||||
JButton replaceAllButton;
|
||||
JButton replaceFindButton;
|
||||
JButton findButton;
|
||||
|
||||
JCheckBox ignoreCaseBox;
|
||||
@@ -132,12 +133,14 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
|
||||
// ordering is different on mac versus pc
|
||||
if (Base.isMacOS()) {
|
||||
buttons.add(replaceButton = new JButton("Replace"));
|
||||
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"));
|
||||
|
||||
} else {
|
||||
buttons.add(findButton = new JButton("Find"));
|
||||
buttons.add(replaceFindButton = new JButton("Replace & Find"));
|
||||
buttons.add(replaceButton = new JButton("Replace"));
|
||||
buttons.add(replaceAllButton = new JButton("Replace All"));
|
||||
}
|
||||
@@ -169,10 +172,12 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
|
||||
replaceButton.addActionListener(this);
|
||||
replaceAllButton.addActionListener(this);
|
||||
replaceFindButton.addActionListener(this);
|
||||
findButton.addActionListener(this);
|
||||
|
||||
// you mustn't replace what you haven't found, my son
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
|
||||
// so that typing will go straight to this field
|
||||
//findField.requestFocus();
|
||||
@@ -189,44 +194,28 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
setBounds((screen.width - wide) / 2,
|
||||
(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);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
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
|
||||
// though this still doesn't seem to work
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowActivated(WindowEvent e) {
|
||||
//System.out.println("activating");
|
||||
//boolean ok = findField.requestFocusInWindow();
|
||||
boolean ok = findField.requestFocusInWindow();
|
||||
//System.out.println("got " + ok);
|
||||
//findField.selectAll();
|
||||
findField.selectAll();
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +245,10 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
if (source == findButton) {
|
||||
find(true);
|
||||
|
||||
} else if (source == replaceFindButton) {
|
||||
replace();
|
||||
find(true);
|
||||
|
||||
} else if (source == replaceButton) {
|
||||
replace();
|
||||
|
||||
@@ -276,6 +269,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
found = false;
|
||||
|
||||
String search = findField.getText();
|
||||
//System.out.println("finding for " + search + " " + findString);
|
||||
// this will catch "find next" being called when no search yet
|
||||
if (search.length() == 0) return;
|
||||
|
||||
@@ -299,12 +293,14 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
if (nextIndex == -1) {
|
||||
found = false;
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
//Toolkit.getDefaultToolkit().beep();
|
||||
return;
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
replaceButton.setEnabled(true);
|
||||
replaceFindButton.setEnabled(true);
|
||||
editor.textarea.select(nextIndex, nextIndex + search.length());
|
||||
}
|
||||
|
||||
@@ -322,6 +318,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
if (sel.equals(replaceField.getText())) {
|
||||
found = false;
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -332,6 +329,7 @@ public class FindReplace extends JFrame implements ActionListener {
|
||||
|
||||
// don't allow a double replace
|
||||
replaceButton.setEnabled(false);
|
||||
replaceFindButton.setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -31,6 +31,8 @@ import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
import processing.core.*;
|
||||
|
||||
/*
|
||||
* Provides information about and builds a library
|
||||
*/
|
||||
@@ -552,7 +554,7 @@ public class Library implements MessageConsumer{
|
||||
continue;
|
||||
}
|
||||
|
||||
String pieces[] = Base.split(line, '\t');
|
||||
String pieces[] = PApplet.split(line, '\t');
|
||||
|
||||
if (pieces.length >= 2) {
|
||||
String keyword = pieces[0].trim();
|
||||
|
@@ -41,7 +41,12 @@ import javax.swing.filechooser.*;
|
||||
import javax.swing.text.*;
|
||||
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
|
||||
* properties files are iso8859-1, which is highly likely to
|
||||
* 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 {
|
||||
|
||||
@@ -88,9 +97,12 @@ public class Preferences {
|
||||
* inside a static block.
|
||||
*/
|
||||
static public int BUTTON_HEIGHT = 24;
|
||||
/*
|
||||
// remove this for 0121, because quaqua takes care of it
|
||||
static {
|
||||
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
|
||||
}
|
||||
*/
|
||||
|
||||
// value for the size bars, buttons, etc
|
||||
|
||||
@@ -107,15 +119,18 @@ public class Preferences {
|
||||
|
||||
// gui elements
|
||||
|
||||
JDialog dialog;
|
||||
//JDialog dialog;
|
||||
JFrame dialog;
|
||||
int wide, high;
|
||||
|
||||
JTextField sketchbookLocationField;
|
||||
JCheckBox exportSeparateBox;
|
||||
JCheckBox sketchPromptBox;
|
||||
JCheckBox sketchCleanBox;
|
||||
JCheckBox externalEditorBox;
|
||||
JCheckBox memoryOverrideBox;
|
||||
JTextField memoryField;
|
||||
JCheckBox checkUpdatesBox;
|
||||
|
||||
JTextField fontSizeField;
|
||||
|
||||
|
||||
@@ -145,7 +160,7 @@ public class Preferences {
|
||||
// check for platform-specific properties in the defaults
|
||||
|
||||
String platformExtension = "." +
|
||||
platforms[Base.platform];
|
||||
platforms[processing.core.PApplet.platform];
|
||||
int extensionLength = platformExtension.length();
|
||||
|
||||
Enumeration e = table.keys(); //properties.propertyNames();
|
||||
@@ -195,7 +210,8 @@ public class Preferences {
|
||||
|
||||
// setup dialog for the prefs
|
||||
|
||||
dialog = new JDialog(editor, "Preferences", true);
|
||||
//dialog = new JDialog(editor, "Preferences", true);
|
||||
dialog = new JFrame("Preferences");
|
||||
dialog.setResizable(false);
|
||||
|
||||
Container pain = dialog.getContentPane();
|
||||
@@ -249,6 +265,7 @@ public class Preferences {
|
||||
button = new JButton(PROMPT_BROWSE);
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
/*
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
|
||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
@@ -258,6 +275,13 @@ public class Preferences {
|
||||
File file = fc.getSelectedFile();
|
||||
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);
|
||||
@@ -286,6 +310,8 @@ public class Preferences {
|
||||
box.add(label);
|
||||
fontSizeField = new JTextField(4);
|
||||
box.add(fontSizeField);
|
||||
label = new JLabel(" (requires restart of Arduino)");
|
||||
box.add(label);
|
||||
pain.add(box);
|
||||
d = box.getPreferredSize();
|
||||
box.setBounds(left, top, d.width, d.height);
|
||||
@@ -468,9 +494,9 @@ public class Preferences {
|
||||
String newSizeText = fontSizeField.getText();
|
||||
try {
|
||||
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);
|
||||
set("editor.font", Base.join(pieces, ','));
|
||||
set("editor.font", PApplet.join(pieces, ','));
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("ignoring invalid font size " + newSizeText);
|
||||
|
@@ -23,7 +23,7 @@
|
||||
|
||||
package processing.app;
|
||||
|
||||
//import processing.core.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
@@ -40,7 +40,7 @@ import com.oroinc.text.regex.*;
|
||||
*/
|
||||
public class Runner implements MessageConsumer {
|
||||
|
||||
//PApplet applet;
|
||||
PApplet applet;
|
||||
RunnerException exception;
|
||||
Window window;
|
||||
PrintStream leechErr;
|
||||
@@ -497,6 +497,7 @@ java.lang.NullPointerException
|
||||
}
|
||||
|
||||
if (codeIndex != -1) {
|
||||
//System.out.println("got line num " + lineNumber);
|
||||
// in case this was a tab that got embedded into the main .java
|
||||
lineNumber -= sketch.code[codeIndex].preprocOffset;
|
||||
|
||||
|
257
app/Sketch.java
257
app/Sketch.java
@@ -24,7 +24,7 @@
|
||||
package processing.app;
|
||||
|
||||
import processing.app.preproc.*;
|
||||
//import processing.core.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
@@ -73,6 +73,7 @@ public class Sketch {
|
||||
static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
|
||||
|
||||
public SketchCode current;
|
||||
int currentIndex;
|
||||
int codeCount;
|
||||
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;
|
||||
while (index < codeCount) {
|
||||
if ((code[index] == null) ||
|
||||
@@ -330,7 +335,7 @@ public class Sketch {
|
||||
// ask for new name of file (internal to window)
|
||||
// TODO maybe just popup a text area?
|
||||
renamingCode = true;
|
||||
String prompt = (current == code[0]) ?
|
||||
String prompt = (currentIndex == 0) ?
|
||||
"New name for sketch:" : "New name for file:";
|
||||
String oldName = current.name + flavorExtensionsShown[current.flavor];
|
||||
editor.status.edit(prompt, oldName);
|
||||
@@ -436,7 +441,7 @@ public class Sketch {
|
||||
}
|
||||
|
||||
if (renamingCode) {
|
||||
if (current == code[0]) {
|
||||
if (currentIndex == 0) {
|
||||
// get the new folder name/location
|
||||
File newFolder = new File(folder.getParentFile(), newName);
|
||||
if (newFolder.exists()) {
|
||||
@@ -494,43 +499,17 @@ public class Sketch {
|
||||
// having saved everything and renamed the folder and the main .pde,
|
||||
// use the editor to re-open the sketch to re-init state
|
||||
// (unfortunately this will kill positions for carets etc)
|
||||
editor.handleOpenUnchecked(mainFilename);
|
||||
|
||||
/*
|
||||
// backtrack and don't rename the sketch folder
|
||||
success = newFolder.renameTo(folder);
|
||||
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;
|
||||
editor.handleOpenUnchecked(mainFilename,
|
||||
currentIndex,
|
||||
editor.textarea.getSelectionStart(),
|
||||
editor.textarea.getSelectionEnd(),
|
||||
editor.textarea.getScrollPosition());
|
||||
|
||||
// get the changes into the sketchbook menu
|
||||
// (re-enabled in 0115 to fix bug #332)
|
||||
editor.sketchbook.rebuildMenus();
|
||||
|
||||
// reload the sketch
|
||||
load();
|
||||
*/
|
||||
|
||||
} else {
|
||||
} else { // else if something besides code[0]
|
||||
if (!current.file.renameTo(newFile)) {
|
||||
Base.showWarning("Error",
|
||||
"Could not rename \"" + current.file.getName() +
|
||||
@@ -593,7 +572,7 @@ public class Sketch {
|
||||
|
||||
// confirm deletion with user, yes/no
|
||||
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 \"" + current.name +
|
||||
flavorExtensionsShown[current.flavor] + "\"?";
|
||||
@@ -606,7 +585,7 @@ public class Sketch {
|
||||
options,
|
||||
options[0]);
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
if (current == code[0]) {
|
||||
if (currentIndex == 0) {
|
||||
// need to unset all the modified flags, otherwise tries
|
||||
// to do a save on the handleNew()
|
||||
|
||||
@@ -672,7 +651,7 @@ public class Sketch {
|
||||
|
||||
// don't allow hide of the main code
|
||||
// TODO maybe gray out the menu on setCurrent(0)
|
||||
if (current == code[0]) {
|
||||
if (currentIndex == 0) {
|
||||
Base.showMessage("Can't do that",
|
||||
"You cannot hide the main " +
|
||||
".pde file from a sketch\n");
|
||||
@@ -933,57 +912,14 @@ public class Sketch {
|
||||
File newFile = new File(newFolder, newName + ".pde");
|
||||
code[0].saveAs(newFile);
|
||||
|
||||
editor.handleOpenUnchecked(newFile.getPath());
|
||||
editor.handleOpenUnchecked(newFile.getPath(),
|
||||
currentIndex,
|
||||
editor.textarea.getSelectionStart(),
|
||||
editor.textarea.getSelectionEnd(),
|
||||
editor.textarea.getScrollPosition());
|
||||
|
||||
/*
|
||||
// copy the entire contents of the sketch folder
|
||||
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();
|
||||
*/
|
||||
// Name changed, rebuild the sketch menus
|
||||
editor.sketchbook.rebuildMenusAsync();
|
||||
|
||||
// let Editor know that the save was successful
|
||||
return true;
|
||||
@@ -1168,8 +1104,8 @@ public class Sketch {
|
||||
* </OL>
|
||||
*/
|
||||
public void setCurrent(int which) {
|
||||
if (current == code[which]) {
|
||||
//System.out.println("already current, ignoring");
|
||||
// if current is null, then this is the first setCurrent(0)
|
||||
if ((currentIndex == which) && (current != null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1182,6 +1118,7 @@ public class Sketch {
|
||||
}
|
||||
|
||||
current = code[which];
|
||||
currentIndex = which;
|
||||
editor.setCode(current);
|
||||
//editor.setDocument(current.document,
|
||||
// current.selectionStart, current.selectionStop,
|
||||
@@ -1286,6 +1223,9 @@ public class Sketch {
|
||||
//handleOpen(sketch);
|
||||
//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
|
||||
load();
|
||||
}
|
||||
@@ -1746,7 +1686,12 @@ public class Sketch {
|
||||
// make sure the user didn't hide the sketch folder
|
||||
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();
|
||||
|
||||
@@ -1773,6 +1718,7 @@ public class Sketch {
|
||||
|
||||
/* int wide = PApplet.DEFAULT_WIDTH;
|
||||
int high = PApplet.DEFAULT_HEIGHT;
|
||||
String renderer = "";
|
||||
|
||||
PatternMatcher matcher = new Perl5Matcher();
|
||||
PatternCompiler compiler = new Perl5Compiler();
|
||||
@@ -1785,20 +1731,26 @@ public class Sketch {
|
||||
// modified for 83 to match size(XXX, ddd so that it'll
|
||||
// properly handle size(200, 200) and size(200, 200, P3D)
|
||||
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);
|
||||
|
||||
// adds a space at the beginning, in case size() is the very
|
||||
// first thing in the program (very common), since the regexp
|
||||
// needs to check for things in front of it.
|
||||
PatternMatcherInput input =
|
||||
new PatternMatcherInput(" " + code[0].program);
|
||||
new PatternMatcherInput(" " + scrubComments(code[0].program));
|
||||
if (matcher.contains(input, pattern)) {
|
||||
MatchResult result = matcher.getMatch();
|
||||
|
||||
try {
|
||||
wide = Integer.parseInt(result.group(1).toString());
|
||||
high = Integer.parseInt(result.group(2).toString());
|
||||
|
||||
renderer = result.group(3).toString(); //.trim();
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
// found a reference to size, but it didn't
|
||||
// seem to contain numbers
|
||||
@@ -1865,45 +1817,6 @@ public class Sketch {
|
||||
if (is == null) {
|
||||
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
|
||||
String LOADING_IMAGE = "loading.gif";
|
||||
@@ -1929,13 +1842,13 @@ public class Sketch {
|
||||
new FileOutputStream(new File(appletFolder, name + ".jar"));
|
||||
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
|
||||
ZipEntry entry;
|
||||
archives.append(name + ".jar");
|
||||
|
||||
// add the manifest file
|
||||
addManifest(zos);
|
||||
|
||||
// add the contents of the code folder to the jar
|
||||
// unpacks all jar files
|
||||
//File codeFolder = new File(folder, "code");
|
||||
// unpacks all jar files, unless multi jar files selected in prefs
|
||||
if (codeFolder.exists()) {
|
||||
String includes = Compiler.contentsToClassPath(codeFolder);
|
||||
packClassPathIntoZipFile(includes, zos);
|
||||
@@ -1980,7 +1893,18 @@ public class Sketch {
|
||||
|
||||
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
|
||||
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);
|
||||
}
|
||||
|
||||
} else { // just copy the file over.. prolly a .dll or something
|
||||
Base.copyFile(exportFile,
|
||||
@@ -1991,6 +1915,7 @@ public class Sketch {
|
||||
*/
|
||||
/* String bagelJar = "lib/core.jar";
|
||||
packClassPathIntoZipFile(bagelJar, zos);
|
||||
}
|
||||
|
||||
// files to include from data directory
|
||||
// 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.
|
||||
* <PRE>
|
||||
@@ -2135,7 +2107,6 @@ public class Sketch {
|
||||
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
if (pieces[i].length() == 0) continue;
|
||||
//System.out.println("checking piece " + pieces[i]);
|
||||
|
||||
// is it a jar file or directory?
|
||||
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
||||
@@ -2299,4 +2270,16 @@ public class Sketch {
|
||||
public String getMainFilePath() {
|
||||
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");
|
||||
File sketchbookFolder = Base.getDefaultSketchbookFolder();
|
||||
//System.out.println("default is " + sketchbookFolder);
|
||||
Preferences.set("sketchbook.path",
|
||||
sketchbookFolder.getAbsolutePath());
|
||||
|
||||
@@ -170,11 +171,8 @@ public class Sketchbook {
|
||||
if (noPrompt) prompt = false;
|
||||
|
||||
if (prompt) {
|
||||
//if (!startup) {
|
||||
// prompt for the filename and location for the new sketch
|
||||
|
||||
FileDialog fd = new FileDialog(editor, //new Frame(),
|
||||
//"Create new sketch named",
|
||||
FileDialog fd = new FileDialog(editor,
|
||||
"Create sketch folder named:",
|
||||
FileDialog.SAVE);
|
||||
fd.setDirectory(getSketchbookPath());
|
||||
@@ -228,7 +226,7 @@ public class Sketchbook {
|
||||
}
|
||||
|
||||
// make a note of a newly added sketch in the sketchbook menu
|
||||
rebuildMenus();
|
||||
rebuildMenusAsync();
|
||||
|
||||
// now open it up
|
||||
//handleOpen(newbieName, newbieFile, newbieDir);
|
||||
@@ -257,10 +255,25 @@ public class Sketchbook {
|
||||
|
||||
|
||||
/**
|
||||
* Java classes are pretty limited about what you can use
|
||||
* for their naming. This helper function replaces everything
|
||||
* but A-Z, a-z, and 0-9 with underscores. Also disallows
|
||||
* starting the sketch name with a digit.
|
||||
* Return true if the name is valid for a Processing sketch.
|
||||
*/
|
||||
static public boolean isSanitary(String name) {
|
||||
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) {
|
||||
char c[] = origName.toCharArray();
|
||||
@@ -280,7 +293,12 @@ public class Sketchbook {
|
||||
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) {
|
||||
buffer.setLength(63);
|
||||
}
|
||||
@@ -290,12 +308,12 @@ public class Sketchbook {
|
||||
|
||||
public String handleOpen() {
|
||||
// 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(),
|
||||
"Open a Processing sketch...",
|
||||
FileDialog.LOAD);
|
||||
//fd.setDirectory(Preferences.get("sketchbook.path"));
|
||||
fd.setDirectory(getSketchbookPath());
|
||||
//fd.setDirectory(getSketchbookPath());
|
||||
|
||||
// only show .pde files as eligible bachelors
|
||||
// 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
|
||||
* contents of the sketchbook.
|
||||
@@ -333,6 +368,7 @@ public class Sketchbook {
|
||||
* the menu will disappear from its original location.
|
||||
*/
|
||||
public void rebuildMenus() {
|
||||
//EditorConsole.systemOut.println("rebuilding menus");
|
||||
try {
|
||||
// rebuild file/open and the toolbar popup menus
|
||||
buildMenu(openMenu);
|
||||
@@ -359,6 +395,7 @@ public class Sketchbook {
|
||||
"sketchbook menu. Things might get a little\n" +
|
||||
"kooky around here.", e);
|
||||
}
|
||||
//EditorConsole.systemOut.println("done rebuilding menus");
|
||||
}
|
||||
|
||||
|
||||
@@ -444,25 +481,8 @@ public class Sketchbook {
|
||||
if (list == null) return false;
|
||||
|
||||
// alphabetize list, since it's not always alpha order
|
||||
// use cheapie bubble-style sort which should be fine
|
||||
// since not a tone of files, and things will mostly be sorted
|
||||
// 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());
|
||||
// replaced hella slow bubble sort with this feller for 0093
|
||||
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
ActionListener listener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -477,18 +497,23 @@ public class Sketchbook {
|
||||
list[i].equals("CVS")) continue;
|
||||
|
||||
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");
|
||||
// if a .pde file of the same prefix as the folder exists..
|
||||
if (entry.exists()) {
|
||||
String sanityCheck = sanitizedName(list[i]);
|
||||
if (!sanityCheck.equals(list[i])) {
|
||||
//String sanityCheck = sanitizedName(list[i]);
|
||||
//if (!sanityCheck.equals(list[i])) {
|
||||
if (!Sketchbook.isSanitary(list[i])) {
|
||||
if (!builtOnce) {
|
||||
String mess =
|
||||
String complaining =
|
||||
"The sketch \"" + list[i] + "\" cannot be used.\n" +
|
||||
"Sketch names must contain only basic letters and numbers.\n" +
|
||||
"(ascii only and no spaces, and it cannot start with a number)";
|
||||
Base.showMessage("Ignoring bad sketch name", mess);
|
||||
"Sketch names must contain only basic letters and numbers\n" +
|
||||
"(ASCII-only with no spaces, " +
|
||||
"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;
|
||||
}
|
||||
@@ -499,7 +524,8 @@ public class Sketchbook {
|
||||
menu.add(item);
|
||||
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]);
|
||||
// needs to be separate var
|
||||
// otherwise would set ifound to false
|
||||
@@ -523,22 +549,8 @@ public class Sketchbook {
|
||||
if (list == null) return false;
|
||||
|
||||
// alphabetize list, since it's not always alpha order
|
||||
// use cheapie bubble-style sort which should be fine
|
||||
// since not a tone of files, and things will mostly be sorted
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// replaced hella slow bubble sort with this feller for 0093
|
||||
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
ActionListener listener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -591,6 +603,8 @@ public class Sketchbook {
|
||||
String packages[] =
|
||||
Compiler.packageListFromClassPath(libraryClassPath);
|
||||
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);
|
||||
}
|
||||
*/
|
||||
@@ -600,11 +614,10 @@ public class Sketchbook {
|
||||
menu.add(item);
|
||||
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]);
|
||||
// needs to be separate var
|
||||
// otherwise would set ifound to false
|
||||
boolean found = addLibraries(submenu, subfolder); //, false);
|
||||
// needs to be separate var, otherwise would set ifound to false
|
||||
boolean found = addLibraries(submenu, subfolder);
|
||||
if (found) {
|
||||
menu.add(submenu);
|
||||
ifound = true;
|
||||
|
@@ -30,7 +30,7 @@
|
||||
package processing.app.preproc;
|
||||
|
||||
import processing.app.*;
|
||||
//import processing.core.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@@ -99,6 +99,7 @@ public class PdePreprocessor {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
//public String write(String program, String buildPath, String name,
|
||||
@@ -109,10 +110,19 @@ public class PdePreprocessor {
|
||||
throws java.lang.Exception {
|
||||
// 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:
|
||||
if ((program.length() > 0) &&
|
||||
program.charAt(program.length()-1) != '\n') {
|
||||
// bug filed at http://dev.processing.org/bugs/show_bug.cgi?id=5
|
||||
//if ((program.length() > 0) &&
|
||||
//program.charAt(program.length()-1) != '\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")) {
|
||||
// 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()];
|
||||
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) {
|
||||
codeFolderImports = new String[codeFolderPackages.length];
|
||||
for (int i = 0; i < codeFolderPackages.length; i++) {
|
||||
|
@@ -136,9 +136,10 @@ public abstract class InputHandler extends KeyAdapter
|
||||
{
|
||||
String name = (String)en.nextElement();
|
||||
ActionListener _listener = getAction(name);
|
||||
if(_listener == listener)
|
||||
if(_listener == listener) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -180,7 +181,6 @@ public abstract class InputHandler extends KeyAdapter
|
||||
/**
|
||||
* Grabs the next key typed event and invokes the specified
|
||||
* action with the key as a the action command.
|
||||
* @param action The action
|
||||
*/
|
||||
public void grabNextKeyStroke(ActionListener listener)
|
||||
{
|
||||
@@ -743,19 +743,32 @@ public abstract class InputHandler extends KeyAdapter
|
||||
{
|
||||
JEditTextArea textArea = getTextArea(evt);
|
||||
int caret = textArea.getCaretPosition();
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
if(select)
|
||||
textArea.select(textArea.getMarkPosition(),
|
||||
caret + 1);
|
||||
else
|
||||
} else if (select) {
|
||||
textArea.select(textArea.getMarkPosition(), caret+1);
|
||||
|
||||
} else {
|
||||
int start = textArea.getSelectionStart();
|
||||
int end = textArea.getSelectionEnd();
|
||||
if (start != end) {
|
||||
textArea.select(end, end);
|
||||
} else {
|
||||
textArea.setCaretPosition(caret + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class next_line implements ActionListener
|
||||
{
|
||||
@@ -774,7 +787,13 @@ public abstract class InputHandler extends KeyAdapter
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -901,13 +920,19 @@ public abstract class InputHandler extends KeyAdapter
|
||||
return;
|
||||
}
|
||||
|
||||
if(select)
|
||||
textArea.select(textArea.getMarkPosition(),
|
||||
caret - 1);
|
||||
else
|
||||
if (select) {
|
||||
textArea.select(textArea.getMarkPosition(), caret-1);
|
||||
} else {
|
||||
int start = textArea.getSelectionStart();
|
||||
int end = textArea.getSelectionEnd();
|
||||
if (start != end) {
|
||||
textArea.select(start, start);
|
||||
} else {
|
||||
textArea.setCaretPosition(caret - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class prev_line implements ActionListener
|
||||
{
|
||||
@@ -926,7 +951,14 @@ public abstract class InputHandler extends KeyAdapter
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -888,22 +888,20 @@ public class JEditTextArea extends JComponent
|
||||
*/
|
||||
public void setText(String text)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
document.beginCompoundEdit();
|
||||
document.remove(0,document.getLength());
|
||||
document.insertString(0,text,null);
|
||||
}
|
||||
catch(BadLocationException bl)
|
||||
{
|
||||
|
||||
} catch (BadLocationException bl) {
|
||||
bl.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
} finally {
|
||||
document.endCompoundEdit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the specified substring of the document.
|
||||
* @param start The start offset
|
||||
@@ -1502,7 +1500,7 @@ public class JEditTextArea extends JComponent
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public final void setSelectionRectangular(boolean rectSelect)
|
||||
@@ -1644,6 +1642,7 @@ public class JEditTextArea extends JComponent
|
||||
|
||||
switch(evt.getID()) {
|
||||
case KeyEvent.KEY_TYPED:
|
||||
//if ((editorListener != null) && !editorListener.keyTyped(evt)) {
|
||||
inputHandler.keyTyped(evt);
|
||||
break;
|
||||
case KeyEvent.KEY_PRESSED:
|
||||
@@ -2145,21 +2144,52 @@ public class JEditTextArea extends JComponent
|
||||
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");
|
||||
if(noWordSep == null)
|
||||
noWordSep = "";
|
||||
|
||||
// If the user clicked on a non-letter char,
|
||||
// we select the surrounding non-letters
|
||||
boolean selectNoLetter = (!Character
|
||||
.isLetterOrDigit(ch)
|
||||
&& noWordSep.indexOf(ch) == -1);
|
||||
// Ok, it's not a bracket... select the word
|
||||
String lineText = getLineText(line);
|
||||
|
||||
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--) {
|
||||
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);
|
||||
if(selectNoLetter ^ (!Character
|
||||
.isLetterOrDigit(ch) &&
|
||||
noWordSep.indexOf(ch) == -1))
|
||||
{
|
||||
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
|
||||
noWordSep.indexOf(ch) == -1)) {
|
||||
wordEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
int lineStart = getLineStartOffset(line);
|
||||
select(lineStart + wordStart,lineStart + wordEnd);
|
||||
|
@@ -76,7 +76,7 @@ public class KeywordMap
|
||||
/**
|
||||
* Adds a key-value mapping.
|
||||
* @param keyword The key
|
||||
* @Param id The value
|
||||
* @param id The value
|
||||
*/
|
||||
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) {
|
||||
//int tab = line.indexOf('\t');
|
||||
// any line with no tab is ignored
|
||||
|
@@ -2,9 +2,9 @@
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -32,41 +32,65 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
|
||||
public PdeTextAreaDefaults() {
|
||||
|
||||
inputHandler = new DefaultInputHandler();
|
||||
inputHandler.addDefaultKeyBindings();
|
||||
//inputHandler.addDefaultKeyBindings(); // 0122
|
||||
|
||||
// use option on mac for things that are ctrl on windows/linux
|
||||
String mod = Base.isMacOS() ? "A" : "C";
|
||||
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
|
||||
// right now, ctrl-up/down is select up/down, but mod should be
|
||||
// used instead, because the mac expects it to be option(alt)
|
||||
|
||||
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
|
||||
inputHandler.addKeyBinding("C+BACK_SPACE", InputHandler.BACKSPACE_WORD);
|
||||
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
|
||||
inputHandler.addKeyBinding("C+DELETE", InputHandler.DELETE_WORD);
|
||||
|
||||
inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
|
||||
inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
|
||||
//inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
|
||||
// for 0122, shift-backspace is delete
|
||||
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.DELETE);
|
||||
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
|
||||
|
||||
// the following two were changing for 0122 for better mac/pc compatability
|
||||
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("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("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()) {
|
||||
inputHandler.addKeyBinding("M+LEFT", InputHandler.HOME);
|
||||
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_DOWN", InputHandler.NEXT_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(mod + "+RIGHT", InputHandler.NEXT_WORD);
|
||||
inputHandler.addKeyBinding(mod + "S+RIGHT", InputHandler.SELECT_NEXT_WORD);
|
||||
|
||||
inputHandler.addKeyBinding("UP", InputHandler.PREV_LINE);
|
||||
inputHandler.addKeyBinding(mod + "+UP", InputHandler.PREV_LINE); // p5
|
||||
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("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);
|
||||
|
||||
document = new SyntaxDocument();
|
||||
|
@@ -18,6 +18,7 @@ import javax.swing.text.*;
|
||||
import javax.swing.JComponent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.print.*;
|
||||
|
||||
/**
|
||||
* The text area repaint manager. It performs double buffering and paints
|
||||
@@ -25,8 +26,12 @@ import java.awt.*;
|
||||
* @author Slava Pestov
|
||||
* @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
|
||||
* 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.
|
||||
* @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)
|
||||
{
|
||||
if (!printing) {
|
||||
if (line >= textArea.getSelectionStartLine()
|
||||
&& line <= textArea.getSelectionEndLine())
|
||||
paintLineHighlight(gfx,line,y);
|
||||
@@ -613,6 +645,7 @@ public class TextAreaPainter extends JComponent implements TabExpander
|
||||
if (line == textArea.getCaretLine())
|
||||
paintCaret(gfx,line,y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintLineHighlight(Graphics gfx, int line, int y)
|
||||
{
|
||||
|
@@ -25,6 +25,7 @@ package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
|
||||
import java.awt.FileDialog;
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
@@ -35,7 +36,7 @@ public class Archiver {
|
||||
Editor editor;
|
||||
|
||||
// someday these will be settable
|
||||
boolean useDate = true; //false;
|
||||
boolean useDate;
|
||||
int digits = 3;
|
||||
|
||||
NumberFormat numberFormat;
|
||||
@@ -79,6 +80,9 @@ public class Archiver {
|
||||
String namely = null;
|
||||
int index = 0;
|
||||
do {
|
||||
// only use the date if the sketch name isn't the default name
|
||||
useDate = !name.startsWith("sketch_");
|
||||
|
||||
if (useDate) {
|
||||
String purty = dateFormat.format(new Date());
|
||||
String stamp = purty + ((char) ('a' + index));
|
||||
@@ -93,6 +97,20 @@ public class Archiver {
|
||||
index++;
|
||||
} 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 {
|
||||
//System.out.println(newbie);
|
||||
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
|
||||
@@ -110,6 +128,9 @@ public class Archiver {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
editor.message("Archive sketch canceled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
package processing.app.tools;
|
||||
|
||||
import processing.app.*;
|
||||
//import processing.core.*;
|
||||
import processing.core.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.StringTokenizer;
|
||||
@@ -915,26 +915,25 @@ public class AutoFormat {
|
||||
if (formattedText.equals(originalText)) {
|
||||
editor.message("No changes necessary for Auto Format.");
|
||||
|
||||
} else {
|
||||
// replace with new bootiful text
|
||||
// selectionEnd hopefully at least in the neighborhood
|
||||
editor.setText(formattedText, selectionEnd, selectionEnd);
|
||||
editor.sketch.setModified(true);
|
||||
|
||||
} else if (paren != 0) {
|
||||
// warn user if there are too many parens in either direction
|
||||
if (paren != 0) {
|
||||
editor.error("Warning: Too many " +
|
||||
editor.error("Auto Format Canceled: Too many " +
|
||||
((paren < 0) ? "right" : "left") +
|
||||
" parentheses.");
|
||||
|
||||
} 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") +
|
||||
" curly braces.");
|
||||
|
||||
} 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.");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception 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
|
||||
if (!folder.isDirectory()) return; // false;
|
||||
|
||||
System.out.println(folder.getAbsolutePath());
|
||||
|
||||
String list[] = folder.list();
|
||||
// if a bad folder or something like that, this might come back null
|
||||
if (list == null) return; // false;
|
||||
|
Reference in New Issue
Block a user