Resynced with Processing/Wiring IDE code: improved auto-format, better performance for EditorConsole, etc...

This commit is contained in:
David A. Mellis 2006-03-26 19:12:53 +00:00
parent 2de016c367
commit 3ea01968d7
22 changed files with 3213 additions and 1343 deletions

View File

@ -52,30 +52,63 @@ import com.ice.jni.registry.*;
* files and images, etc) that comes from that. * files and images, etc) that comes from that.
*/ */
public class Base { public class Base {
static final int VERSION = 1; static final int VERSION = 3;
static final String VERSION_NAME = "0004 Alpha"; static final String VERSION_NAME = "0004 Alpha";
static public int platform; // platform IDs for PApplet.platform
// platform IDs for platform
static final int WINDOWS = 1; static final int WINDOWS = 1;
static final int MACOS9 = 2; static final int MACOS9 = 2;
static final int MACOSX = 3; static final int MACOSX = 3;
static final int LINUX = 4; static final int LINUX = 4;
static final int OTHER = 0; static final int OTHER = 0;
// used by split, all the standard whitespace chars
// moved from PApplet // (uncludes unicode nbsp, that little bostage)
// in preperation of detaching the IDE from the
// Arduino core classes static final String WHITESPACE = " \t\n\r\f\u00A0";
/** /**
* Path of filename opened on the command line,
* or via the MRJ open document handler.
*/
static String openedAtStartup;
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. * Current platform in use.
* <P> * <P>
* Equivalent to System.getProperty("os.name"), just used internally. * Equivalent to System.getProperty("os.name"), just used internally.
*/ */
static public String platformName = System.getProperty("os.name"); static public String platformName =
System.getProperty("os.name");
static { static {
// figure out which operating system // figure out which operating system
@ -105,23 +138,6 @@ public class Base {
} }
} }
// 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,
* or via the MRJ open document handler.
*/
static String openedAtStartup;
Editor editor;
static public void main(String args[]) { static public void main(String args[]) {
// make sure that this is running on java 1.4 // make sure that this is running on java 1.4
@ -179,6 +195,9 @@ public class Base {
e.printStackTrace(); e.printStackTrace();
} }
// use native popups so they don't look so crappy on osx
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
// build the editor object // build the editor object
editor = new Editor(); editor = new Editor();
@ -214,7 +233,6 @@ public class Base {
* returns true if running on windows. * returns true if running on windows.
*/ */
static public boolean isWindows() { static public boolean isWindows() {
return platform == WINDOWS; return platform == WINDOWS;
} }
@ -223,7 +241,6 @@ public class Base {
* true if running on linux. * true if running on linux.
*/ */
static public boolean isLinux() { static public boolean isLinux() {
return platform == LINUX; return platform == LINUX;
} }
@ -363,26 +380,40 @@ public class Base {
} }
static public File getBuildFolder() { static File buildFolder;
String buildPath = Preferences.get("build.path");
if (buildPath != null) return new File(buildPath);
File folder = new File(getTempFolder(), "build"); static public File getBuildFolder() {
if (!folder.exists()) folder.mkdirs(); if (buildFolder == null) {
return folder; String buildPath = Preferences.get("build.path");
if (buildPath != null) {
buildFolder = new File(buildPath);
} else {
//File folder = new File(getTempFolder(), "build");
//if (!folder.exists()) folder.mkdirs();
buildFolder = createTempFolder("build");
buildFolder.deleteOnExit();
}
}
return buildFolder;
} }
/** /**
* Get the path to the platform's temporary folder, by creating * Get the path to the platform's temporary folder, by creating
* a temporary temporary file and getting its parent folder. * a temporary temporary file and getting its parent folder.
* <br/>
* Modified for revision 0094 to actually make the folder randomized
* to avoid conflicts in multi-user environments. (Bug 177)
*/ */
static public File getTempFolder() { static public File createTempFolder(String name) {
try { try {
File ignored = File.createTempFile("ignored", null); File folder = File.createTempFile(name, null);
String tempPath = ignored.getParent(); //String tempPath = ignored.getParent();
ignored.delete(); //return new File(tempPath);
return new File(tempPath); folder.delete();
folder.mkdirs();
return folder;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -548,6 +579,55 @@ public class Base {
// ................................................................. // .................................................................
// someone needs to be slapped
//static KeyStroke closeWindowKeyStroke;
/**
* Return true if the key event was a Ctrl-W or an ESC,
* both indicators to close the window.
* Use as part of a keyPressed() event handler for frames.
*/
/*
static public boolean isCloseWindowEvent(KeyEvent e) {
if (closeWindowKeyStroke == null) {
int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
closeWindowKeyStroke = KeyStroke.getKeyStroke('W', modifiers);
}
return ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
KeyStroke.getKeyStrokeForEvent(e).equals(closeWindowKeyStroke));
}
*/
/**
* Registers key events for a Ctrl-W and ESC with an ActionListener
* that will take care of disposing the window.
*/
static public void registerWindowCloseKeys(JRootPane root, //Window window,
ActionListener disposer) {
/*
JRootPane root = null;
if (window instanceof JFrame) {
root = ((JFrame)window).getRootPane();
} else if (window instanceof JDialog) {
root = ((JDialog)window).getRootPane();
}
*/
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
root.registerKeyboardAction(disposer, stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
stroke = KeyStroke.getKeyStroke('W', modifiers);
root.registerKeyboardAction(disposer, stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
}
// .................................................................
/** /**
* Given the reference filename from the keywords list, * Given the reference filename from the keywords list,
* builds a URL and passes it to openURL. * builds a URL and passes it to openURL.
@ -858,7 +938,9 @@ public class Base {
static public void removeDir(File dir) { static public void removeDir(File dir) {
if (dir.exists()) { if (dir.exists()) {
removeDescendants(dir); removeDescendants(dir);
dir.delete(); if (!dir.delete()) {
System.err.println("Could not delete " + dir);
}
} }
} }
@ -917,6 +999,46 @@ public class Base {
} }
/**
* Gets a list of all files within the specified folder,
* and returns a list of their relative paths.
* Ignores any files/folders prefixed with a dot.
*/
static public String[] listFiles(String path, boolean relative) {
return listFiles(new File(path), relative);
}
static public String[] listFiles(File folder, boolean relative) {
String path = folder.getAbsolutePath();
Vector vector = new Vector();
listFiles(relative ? (path + File.separator) : "", path, vector);
String outgoing[] = new String[vector.size()];
vector.copyInto(outgoing);
return outgoing;
}
static protected void listFiles(String basePath,
String path, Vector vector) {
File folder = new File(path);
String list[] = folder.list();
if (list == null) return;
for (int i = 0; i < list.length; i++) {
if (list[i].charAt(0) == '.') continue;
File file = new File(path, list[i]);
String newPath = file.getAbsolutePath();
if (newPath.startsWith(basePath)) {
newPath = newPath.substring(basePath.length());
}
vector.add(newPath);
if (file.isDirectory()) {
listFiles(basePath, newPath, vector);
}
}
}
/** /**
* Equivalent to the one in PApplet, but static (die() is removed) * Equivalent to the one in PApplet, but static (die() is removed)
*/ */
@ -954,7 +1076,7 @@ public class Base {
return null; return null;
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// STRINGS // STRINGS

View File

@ -76,7 +76,9 @@ public class Compiler implements MessageConsumer {
String userdir = System.getProperty("user.dir") + File.separator; String userdir = System.getProperty("user.dir") + File.separator;
String baseCommandCompiler[] = new String[] { LibraryManager libraryManager = new LibraryManager();
String preCommandCompiler[] = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : ((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" :
userdir + "tools/avr/bin/avr-gcc"), userdir + "tools/avr/bin/avr-gcc"),
"-c", // compile, don't link "-c", // compile, don't link
@ -86,11 +88,19 @@ public class Compiler implements MessageConsumer {
"-w", // surpress all warnings "-w", // surpress all warnings
"-mmcu=" + Preferences.get("build.mcu"), "-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"), "-DF_CPU=" + Preferences.get("build.f_cpu"),
" ",
" "
}; };
String baseCommandCompilerCPP[] = new String[] { // use lib directories as include paths
String[] libDirs = libraryManager.getFolderPaths();
// Last two arguments will specify the file being compiled and the output file.
String[] baseCommandCompiler = new String[preCommandCompiler.length + libDirs.length + 2];
System.arraycopy(preCommandCompiler, 0, baseCommandCompiler, 0, preCommandCompiler.length);
for (int i = 0; i < libDirs.length; ++i) {
baseCommandCompiler[preCommandCompiler.length + i] = "-I" + libDirs[i];
}
String preCommandCompilerCPP[] = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : ((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" :
userdir + "tools/avr/bin/avr-g++"), userdir + "tools/avr/bin/avr-g++"),
"-c", // compile, don't link "-c", // compile, don't link
@ -101,46 +111,33 @@ public class Compiler implements MessageConsumer {
"-fno-exceptions", "-fno-exceptions",
"-mmcu=" + Preferences.get("build.mcu"), "-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"), "-DF_CPU=" + Preferences.get("build.f_cpu"),
" ",
" "
}; };
String baseCommandLinker[] = new String[] { // use lib directories as include paths
// Last two arguments will specify the file being compiled and the output file.
String[] baseCommandCompilerCPP = new String[preCommandCompilerCPP.length + libDirs.length + 2];
System.arraycopy(preCommandCompilerCPP, 0, baseCommandCompilerCPP, 0, preCommandCompilerCPP.length);
for (int i = 0; i < libDirs.length; ++i) {
baseCommandCompilerCPP[preCommandCompilerCPP.length + i] = "-I" + libDirs[i];
}
String preCommandLinker[] = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : ((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" :
userdir + "tools/avr/bin/avr-gcc"), userdir + "tools/avr/bin/avr-gcc"),
" ", " ",
"-mmcu=" + Preferences.get("build.mcu"), "-mmcu=" + Preferences.get("build.mcu"),
"-o", "-o",
" ", " ",
// ((!Base.isMacOS()) ? "" : userdir) + "lib/uart.o",
// ((!Base.isMacOS()) ? "" : userdir) + "lib/buffer.o",
// ((!Base.isMacOS()) ? "" : userdir) + "lib/timer.o",
// ((!Base.isMacOS()) ? "" : userdir) + "lib/wiring.o",
// ((!Base.isMacOS()) ? "" : userdir) + "lib/pins_arduino.o",
//((!Base.isMacOS()) ? "lib/WApplet.o" :
//userdir + "lib/WApplet.o"),
//((!Base.isMacOS()) ? "lib/WSerial.o" :
//userdir + "lib/WSerial.o"),
//((!Base.isMacOS()) ? "lib/WTimer.o" :
//userdir + "lib/WTimer.o"),
//((!Base.isMacOS()) ? "lib/Servo.o" :
//userdir + "lib/Servo.o"),
////((!Base.isMacOS()) ? "lib/Wire.o" :
//// userdir + "lib/Wire.o"),
////((!Base.isMacOS()) ? "lib/WServo.o" :
//// userdir + "lib/WServo.o"),
//((!Base.isMacOS()) ? "lib/WDisplay.o" :
//userdir + "lib/WDisplay.o"),
//((!Base.isMacOS()) ? "lib/WEncoder.o" :
//userdir + "lib/WEncoder.o"),
//((!Base.isMacOS()) ? "lib/WInterrupts.o" :
//userdir + "lib/WInterrupts.o"),
//((!Base.isMacOS()) ? "lib/WCounter.o" :
//userdir + "lib/WCounter.o"),
//((!Base.isMacOS()) ? "tools/avr/avr/lib/libm.a" :
//userdir + "tools/avr/avr/lib/libm.a")
}; };
// use lib object files during include
String[] libObjectFiles = libraryManager.getObjectFiles();
String[] baseCommandLinker = new String[preCommandLinker.length + libObjectFiles.length];
System.arraycopy(preCommandLinker, 0, baseCommandLinker, 0, preCommandLinker.length);
for (int i = 0; i < libObjectFiles.length; ++i) {
baseCommandLinker[preCommandLinker.length + i] = libObjectFiles[i];
}
String baseCommandObjcopy[] = new String[] { String baseCommandObjcopy[] = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-objcopy" : ((!Base.isMacOS()) ? "tools/avr/bin/avr-objcopy" :
userdir + "tools/avr/bin/avr-objcopy"), userdir + "tools/avr/bin/avr-objcopy"),
@ -295,8 +292,8 @@ public class Compiler implements MessageConsumer {
Process process; Process process;
boolean compiling = true; boolean compiling = true;
for(int i = 0; i < fileCount; i++) { for(int i = 0; i < fileCount; i++) {
baseCommandCompiler[8] = sourceNames[i]; baseCommandCompiler[baseCommandCompiler.length - 2] = sourceNames[i];
baseCommandCompiler[9] = "-o"+ objectNames[i]; baseCommandCompiler[baseCommandCompiler.length - 1] = "-o"+ objectNames[i];
//System.arraycopy(baseCommandCompiler.length //System.arraycopy(baseCommandCompiler.length
//for(int j = 0; j < baseCommandCompiler.length; j++) { //for(int j = 0; j < baseCommandCompiler.length; j++) {
// System.out.println(baseCommandCompiler[j]); // System.out.println(baseCommandCompiler[j]);
@ -325,8 +322,8 @@ public class Compiler implements MessageConsumer {
} }
for(int i = 0; i < fileCountCPP; i++) { for(int i = 0; i < fileCountCPP; i++) {
baseCommandCompilerCPP[9] = sourceNamesCPP[i]; baseCommandCompilerCPP[baseCommandCompilerCPP.length - 2] = sourceNamesCPP[i];
baseCommandCompilerCPP[10] = "-o"+ objectNamesCPP[i]; baseCommandCompilerCPP[baseCommandCompilerCPP.length - 1] = "-o"+ objectNamesCPP[i];
//for(int j = 0; j < baseCommandCompilerCPP.length; j++) { //for(int j = 0; j < baseCommandCompilerCPP.length; j++) {
// System.out.println(baseCommandCompilerCPP[j]); // System.out.println(baseCommandCompilerCPP[j]);
//} //}

File diff suppressed because it is too large Load Diff

View File

@ -41,9 +41,11 @@ public class EditorButtons extends JComponent implements MouseInputListener {
}; };
static final int BUTTON_COUNT = title.length; static final int BUTTON_COUNT = title.length;
static final int BUTTON_WIDTH = 27; //Preferences.GRID_SIZE; /// height, width of the toolbar buttons
static final int BUTTON_HEIGHT = 32; //Preferences.GRID_SIZE; static final int BUTTON_WIDTH = 27;
static final int BUTTON_GAP = 15; //BUTTON_WIDTH / 2; static final int BUTTON_HEIGHT = 32;
/// amount of space between groups of buttons on the toolbar
static final int BUTTON_GAP = 15;
static final int RUN = 0; static final int RUN = 0;
static final int STOP = 1; static final int STOP = 1;
@ -59,7 +61,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
static final int ACTIVE = 2; static final int ACTIVE = 2;
Editor editor; Editor editor;
boolean disableRun; //boolean disableRun;
//Label status; //Label status;
Image offscreen; Image offscreen;
@ -72,7 +74,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
Image rollover[]; Image rollover[];
Image active[]; Image active[];
int currentRollover; int currentRollover;
int currentSelection; //int currentSelection;
JPopupMenu popup; JPopupMenu popup;
@ -112,7 +114,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
// see EditorStatus.java for details. // see EditorStatus.java for details.
//bgcolor = Preferences.getColor("buttons.bgcolor"); //bgcolor = Preferences.getColor("buttons.bgcolor");
bgcolor = new Color(0x04, 0x4F, 0x6F); bgcolor = new Color(0x04, 0x4F, 0x6F);
status = ""; status = "";
statusFont = Preferences.getFont("buttons.status.font"); statusFont = Preferences.getFont("buttons.status.font");
@ -234,10 +236,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
if (sel == -1) return; if (sel == -1) return;
if (state[sel] != ACTIVE) { if (state[sel] != ACTIVE) {
if (!(disableRun && ((sel == RUN) || (sel == STOP)))) { //if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
setState(sel, ROLLOVER, true); setState(sel, ROLLOVER, true);
currentRollover = sel; currentRollover = sel;
} //}
} }
} }
@ -284,6 +286,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public void mouseExited(MouseEvent e) { public void mouseExited(MouseEvent e) {
// if the popup menu for is visible, don't register this,
// because the popup being set visible will fire a mouseExited() event
if ((popup != null) && popup.isVisible()) return;
if (state[OPEN] != INACTIVE) { if (state[OPEN] != INACTIVE) {
setState(OPEN, INACTIVE, true); setState(OPEN, INACTIVE, true);
} }
@ -295,27 +301,78 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
int x = e.getX(); final int x = e.getX();
int y = e.getY(); final int y = e.getY();
int sel = findSelection(x, y); int sel = findSelection(x, y);
///if (sel == -1) return false; ///if (sel == -1) return false;
if (sel == -1) return; if (sel == -1) return;
currentRollover = -1; currentRollover = -1;
currentSelection = sel; //int currentSelection = sel;
if (!(disableRun && ((sel == RUN) || (sel == STOP)))) { //if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
setState(sel, ACTIVE, true); // moving the handling of this over into the editor
} //setState(sel, ACTIVE, true);
//}
if (currentSelection == OPEN) { //if (currentSelection == OPEN) {
//switch (currentSelection) {
switch (sel) {
case RUN:
//if (!disableRun) {
editor.handleRun(e.isShiftDown());
//}
break;
case STOP:
//if (!disableRun) {
//setState(RUN, INACTIVE, true);
//setInactive();
editor.handleStop();
//}
break;
case OPEN:
if (popup == null) { if (popup == null) {
//popup = new JPopupMenu(); //popup = new JPopupMenu();
popup = editor.sketchbook.getPopupMenu(); popup = editor.sketchbook.getPopupMenu();
// no events properly being fired, so nevermind
/*
popup.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("action " + e);
}
});
popup.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
System.out.println("hidden " + e);
}
});
*/
add(popup); add(popup);
} }
//editor.sketchbook.rebuildPopup(popup); //activate(OPEN);
popup.show(this, x, y); //SwingUtilities.invokeLater(new Runnable() {
} //public void run() {
popup.show(EditorButtons.this, x, y);
//}});
break;
case NEW:
editor.handleNew(e.isShiftDown());
break;
case SAVE:
editor.handleSave(false);
break;
case EXPORT:
editor.handleExport();
break;
case SERIAL:
editor.handleSerial();
break;
}
} }
@ -323,6 +380,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
/*
switch (currentSelection) { switch (currentSelection) {
case RUN: case RUN:
if (!disableRun) { if (!disableRun) {
@ -344,14 +402,47 @@ public class EditorButtons extends JComponent implements MouseInputListener {
case SERIAL: editor.handleSerial(); break; case SERIAL: editor.handleSerial(); break;
} }
currentSelection = -1; currentSelection = -1;
*/
} }
public void disableRun(boolean what) { //public void disableRun(boolean what) {
disableRun = what; //disableRun = what;
//}
/*
public void run() {
if (inactive == null) return;
clear();
setState(RUN, ACTIVE, true);
}
*/
public void running(boolean yesno) {
setState(RUN, yesno ? ACTIVE : INACTIVE, true);
} }
/**
* Set a particular button to be active.
*/
public void activate(int what) {
if (inactive == null) return;
setState(what, ACTIVE, true);
}
//public void clearRun() {
//if (inactive == null) return;
//setState(RUN, INACTIVE, true);
//}
/**
* Clear all the state of all buttons.
*/
public void clear() { // (int button) { public void clear() { // (int button) {
if (inactive == null) return; if (inactive == null) return;
@ -363,24 +454,6 @@ public class EditorButtons extends JComponent implements MouseInputListener {
} }
public void run() {
if (inactive == null) return;
clear();
setState(RUN, ACTIVE, true);
}
public void running(boolean yesno) {
setState(RUN, yesno ? ACTIVE : INACTIVE, true);
}
public void clearRun() {
if (inactive == null) return;
setState(RUN, INACTIVE, true);
}
public void message(String msg) { public void message(String msg) {
//status.setText(msg + " "); // don't mind the hack //status.setText(msg + " "); // don't mind the hack
status = msg; status = msg;

View File

@ -28,7 +28,7 @@ import java.awt.event.*;
import java.io.*; import java.io.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.text.*; import javax.swing.text.*;
import java.util.*;
/** /**
* Message console that sits below the editing area. * Message console that sits below the editing area.
@ -41,7 +41,7 @@ public class EditorConsole extends JScrollPane {
Editor editor; Editor editor;
JTextPane consoleTextPane; JTextPane consoleTextPane;
StyledDocument consoleDoc; BufferedStyledDocument consoleDoc;
MutableAttributeSet stdStyle; MutableAttributeSet stdStyle;
MutableAttributeSet errStyle; MutableAttributeSet errStyle;
@ -51,6 +51,10 @@ public class EditorConsole extends JScrollPane {
//int maxCharCount; //int maxCharCount;
int maxLineCount; int maxLineCount;
static File errFile;
static File outFile;
static File tempFolder;
static PrintStream systemOut; static PrintStream systemOut;
static PrintStream systemErr; static PrintStream systemErr;
@ -66,9 +70,9 @@ public class EditorConsole extends JScrollPane {
maxLineCount = Preferences.getInteger("console.length"); maxLineCount = Preferences.getInteger("console.length");
consoleTextPane = new JTextPane(); consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
consoleTextPane = new JTextPane(consoleDoc);
consoleTextPane.setEditable(false); consoleTextPane.setEditable(false);
consoleDoc = consoleTextPane.getStyledDocument();
// necessary? // necessary?
MutableAttributeSet standard = new SimpleAttributeSet(); MutableAttributeSet standard = new SimpleAttributeSet();
@ -115,15 +119,20 @@ public class EditorConsole extends JScrollPane {
systemOut = System.out; systemOut = System.out;
systemErr = System.err; systemErr = System.err;
tempFolder = Base.createTempFolder("console");
try { try {
String outFileName = Preferences.get("console.output.file"); String outFileName = Preferences.get("console.output.file");
if (outFileName != null) { if (outFileName != null) {
stdoutFile = new FileOutputStream(outFileName); outFile = new File(tempFolder, outFileName);
stdoutFile = new FileOutputStream(outFile);
//outFile.deleteOnExit();
} }
String errFileName = Preferences.get("console.error.file"); String errFileName = Preferences.get("console.error.file");
if (errFileName != null) { if (errFileName != null) {
stderrFile = new FileOutputStream(outFileName); errFile = new File(tempFolder, errFileName);
stderrFile = new FileOutputStream(errFile);
//errFile.deleteOnExit();
} }
} catch (IOException e) { } catch (IOException e) {
Base.showWarning("Console Error", Base.showWarning("Console Error",
@ -151,6 +160,52 @@ public class EditorConsole extends JScrollPane {
if (Base.isMacOS()) { if (Base.isMacOS()) {
setBorder(null); setBorder(null);
} }
// periodically post buffered messages to the console
// should the interval come from the preferences file?
new javax.swing.Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// only if new text has been added
if (consoleDoc.hasAppendage) {
// insert the text that's been added in the meantime
consoleDoc.insertAll();
// always move to the end of the text as it's added
consoleTextPane.setCaretPosition(consoleDoc.getLength());
}
}
}).start();
}
/**
* Close the streams so that the temporary files can be deleted.
* <p/>
* File.deleteOnExit() cannot be used because the stdout and stderr
* files are inside a folder, and have to be deleted before the
* folder itself is deleted, which can't be guaranteed when using
* the deleteOnExit() method.
*/
public void handleQuit() {
// replace original streams to remove references to console's streams
System.setOut(systemOut);
System.setErr(systemErr);
// close the PrintStream
consoleOut.close();
consoleErr.close();
// also have to close the original FileOutputStream
// otherwise it won't be shut down completely
try {
stdoutFile.close();
stderrFile.close();
} catch (IOException e) {
e.printStackTrace(systemOut);
}
outFile.delete();
errFile.delete();
tempFolder.delete();
} }
@ -174,10 +229,8 @@ public class EditorConsole extends JScrollPane {
synchronized public void message(String what, boolean err, boolean advance) { synchronized public void message(String what, boolean err, boolean advance) {
if (err) { if (err) {
systemErr.print(what); systemErr.print(what);
//systemErr.print("CE" + what);
} else { } else {
systemOut.print(what); systemOut.print(what);
//systemOut.print("CO" + what);
} }
if (advance) { if (advance) {
@ -204,66 +257,13 @@ public class EditorConsole extends JScrollPane {
* and eventually leads to EditorConsole.appendText(), which directly * and eventually leads to EditorConsole.appendText(), which directly
* updates the Swing text components, causing deadlock. * updates the Swing text components, causing deadlock.
* <P> * <P>
* A quick hack from Francis Li (who found this to be a problem) * Updates are buffered to the console and displayed at regular
* wraps the contents of appendText() into a Runnable and uses * intervals on Swing's event-dispatching thread. (patch by David Mellis)
* SwingUtilities.invokeLater() to ensure that the updates only
* occur on the main event dispatching thread, and that appears
* to have solved the problem.
* <P>
* unfortunately this is probably extremely slow and helping cause
* some of the general print() and println() mess.. need to fix
* up so that it's using a proper queue instead.
*/ */
synchronized private void appendText(String txt, boolean e) { synchronized private void appendText(String txt, boolean e) {
final String text = txt; consoleDoc.appendString(txt, e ? errStyle : stdStyle);
final boolean err = e;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
// check how many lines have been used so far
// if too many, shave off a few lines from the beginning
Element element = consoleDoc.getDefaultRootElement();
int lineCount = element.getElementCount();
int overage = lineCount - maxLineCount;
if (overage > 0) {
// if 1200 lines, and 1000 lines is max,
// find the position of the end of the 200th line
//systemOut.println("overage is " + overage);
Element lineElement = element.getElement(overage);
if (lineElement == null) return; // do nuthin
int endOffset = lineElement.getEndOffset();
// remove to the end of the 200th line
consoleDoc.remove(0, endOffset);
}
// make sure this line doesn't go over 32k chars
lineCount = element.getElementCount(); // may have changed
Element currentElement = element.getElement(lineCount-1);
int currentStart = currentElement.getStartOffset();
int currentEnd = currentElement.getEndOffset();
//systemOut.println(currentEnd - currentStart);
if (currentEnd - currentStart > 10000) { // force a newline
consoleDoc.insertString(consoleDoc.getLength(), "\n",
err ? errStyle : stdStyle);
}
// add the text to the end of the console,
consoleDoc.insertString(consoleDoc.getLength(), text,
err ? errStyle : stdStyle);
// always move to the end of the text as it's added
consoleTextPane.setCaretPosition(consoleDoc.getLength());
} catch (BadLocationException e) {
// ignore the error otherwise this will cause an infinite loop
// maybe not a good idea in the long run?
}
}
});
} }
public void clear() { public void clear() {
try { try {
consoleDoc.remove(0, consoleDoc.getLength()); consoleDoc.remove(0, consoleDoc.getLength());
@ -332,3 +332,87 @@ class EditorConsoleStream extends OutputStream {
} }
} }
} }
/**
* Buffer updates to the console and output them in batches. For info, see:
* http://java.sun.com/products/jfc/tsc/articles/text/element_buffer and
* http://javatechniques.com/public/java/docs/gui/jtextpane-speed-part2.html
* appendString() is called from multiple threads, and insertAll from the
* swing event thread, so they need to be synchronized
*/
class BufferedStyledDocument extends DefaultStyledDocument {
ArrayList elements = new ArrayList();
int maxLineLength, maxLineCount;
int currentLineLength = 0;
boolean needLineBreak = false;
boolean hasAppendage = false;
public BufferedStyledDocument(int maxLineLength, int maxLineCount) {
this.maxLineLength = maxLineLength;
this.maxLineCount = maxLineCount;
}
/** buffer a string for insertion at the end of the DefaultStyledDocument */
public synchronized void appendString(String str, AttributeSet a) {
// do this so that it's only updated when needed (otherwise console
// updates every 250 ms when an app isn't even running.. see bug 180)
hasAppendage = true;
// process each line of the string
while (str.length() > 0) {
// newlines within an element have (almost) no effect, so we need to
// replace them with proper paragraph breaks (start and end tags)
if (needLineBreak || currentLineLength > maxLineLength) {
elements.add(new ElementSpec(a, ElementSpec.EndTagType));
elements.add(new ElementSpec(a, ElementSpec.StartTagType));
currentLineLength = 0;
}
if (str.indexOf('\n') == -1) {
elements.add(new ElementSpec(a, ElementSpec.ContentType,
str.toCharArray(), 0, str.length()));
currentLineLength += str.length();
needLineBreak = false;
str = str.substring(str.length()); // eat the string
} else {
elements.add(new ElementSpec(a, ElementSpec.ContentType,
str.toCharArray(), 0, str.indexOf('\n') + 1));
needLineBreak = true;
str = str.substring(str.indexOf('\n') + 1); // eat the line
}
}
}
/** insert the buffered strings */
public synchronized void insertAll() {
ElementSpec[] elementArray = new ElementSpec[elements.size()];
elements.toArray(elementArray);
try {
// check how many lines have been used so far
// if too many, shave off a few lines from the beginning
Element element = super.getDefaultRootElement();
int lineCount = element.getElementCount();
int overage = lineCount - maxLineCount;
if (overage > 0) {
// if 1200 lines, and 1000 lines is max,
// find the position of the end of the 200th line
//systemOut.println("overage is " + overage);
Element lineElement = element.getElement(overage);
if (lineElement == null) return; // do nuthin
int endOffset = lineElement.getEndOffset();
// remove to the end of the 200th line
super.remove(0, endOffset);
}
super.insert(super.getLength(), elementArray);
} catch (BadLocationException e) {
// ignore the error otherwise this will cause an infinite loop
// maybe not a good idea in the long run?
}
elements.clear();
hasAppendage = false;
}
}

View File

@ -339,8 +339,10 @@ public class EditorHeader extends JComponent {
Sketch sketch = editor.sketch; Sketch sketch = editor.sketch;
if (sketch != null) { if (sketch != null) {
for (int i = 0; i < sketch.hiddenCount; i++) { for (int i = 0; i < sketch.hiddenCount; i++) {
item = new JMenuItem(sketch.hidden[i].name); item = new JMenuItem(sketch.hidden[i].name +
item.setActionCommand(sketch.hidden[i].name); Sketch.flavorExtensionsShown[sketch.hidden[i].flavor]);
item.setActionCommand(sketch.hidden[i].name +
Sketch.flavorExtensionsShown[sketch.hidden[i].flavor]);
item.addActionListener(unhideListener); item.addActionListener(unhideListener);
unhide.add(item); unhide.add(item);
} }
@ -360,7 +362,8 @@ public class EditorHeader extends JComponent {
} }
}; };
for (int i = 0; i < sketch.codeCount; i++) { for (int i = 0; i < sketch.codeCount; i++) {
item = new JMenuItem(sketch.code[i].name); item = new JMenuItem(sketch.code[i].name +
Sketch.flavorExtensionsShown[sketch.code[i].flavor]);
item.addActionListener(jumpListener); item.addActionListener(jumpListener);
menu.add(item); menu.add(item);
} }

View File

@ -35,13 +35,25 @@ import javax.swing.event.*;
/** /**
* Filters key events for tab expansion/indent/etc. * Filters key events for tab expansion/indent/etc.
* <p/>
* For version 0099, some changes have been made to make the indents
* smarter. There are still issues though:
* + indent happens when it picks up a curly brace on the previous line,
* but not if there's a blank line between them.
* + It also doesn't handle single indent situations where a brace
* isn't used (i.e. an if statement or for loop that's a single line).
* It shouldn't actually be using braces.
* Solving these issues, however, would probably best be done by a
* smarter parser/formatter, rather than continuing to hack this class.
*/ */
public class EditorListener { public class EditorListener {
Editor editor; Editor editor;
JEditTextArea textarea; JEditTextArea textarea;
boolean externalEditor; boolean externalEditor;
boolean expandTabs; boolean tabsExpand;
boolean tabsIndent;
int tabSize;
String tabString; String tabString;
boolean autoIndent; boolean autoIndent;
@ -61,8 +73,9 @@ public class EditorListener {
public void applyPreferences() { public void applyPreferences() {
expandTabs = Preferences.getBoolean("editor.tabs.expand"); tabsExpand = Preferences.getBoolean("editor.tabs.expand");
int tabSize = Preferences.getInteger("editor.tabs.size"); //tabsIndent = Preferences.getBoolean("editor.tabs.indent");
tabSize = Preferences.getInteger("editor.tabs.size");
tabString = Editor.EMPTY.substring(0, tabSize); tabString = Editor.EMPTY.substring(0, tabSize);
autoIndent = Preferences.getBoolean("editor.indent"); autoIndent = Preferences.getBoolean("editor.indent");
externalEditor = Preferences.getBoolean("editor.external"); externalEditor = Preferences.getBoolean("editor.external");
@ -74,7 +87,13 @@ public class EditorListener {
//} //}
// called by JEditTextArea inside processKeyEvent /**
* Intercepts key pressed events for JEditTextArea.
* <p/>
* Called by JEditTextArea inside processKeyEvent(). Note that this
* won't intercept actual characters, because those are fired on
* keyTyped().
*/
public boolean keyPressed(KeyEvent event) { public boolean keyPressed(KeyEvent event) {
// don't do things if the textarea isn't editable // don't do things if the textarea isn't editable
if (externalEditor) return false; if (externalEditor) return false;
@ -92,21 +111,148 @@ public class EditorListener {
} }
// TODO i don't like these accessors. clean em up later. // TODO i don't like these accessors. clean em up later.
if (!editor.sketch.current.modified) { if (!editor.sketch.modified) {
if ((code == KeyEvent.VK_BACK_SPACE) || (code == KeyEvent.VK_TAB) || if ((code == KeyEvent.VK_BACK_SPACE) || (code == KeyEvent.VK_TAB) ||
(code == KeyEvent.VK_ENTER) || ((c >= 32) && (c < 128))) { (code == KeyEvent.VK_ENTER) || ((c >= 32) && (c < 128))) {
editor.sketch.setModified(); editor.sketch.setModified(true);
} }
} }
if ((code == KeyEvent.VK_UP) &&
((event.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
// back up to the last empty line
char contents[] = textarea.getText().toCharArray();
//int origIndex = textarea.getCaretPosition() - 1;
int caretIndex = textarea.getCaretPosition();
int index = calcLineStart(caretIndex - 1, contents);
//System.out.println("line start " + (int) contents[index]);
index -= 2; // step over the newline
//System.out.println((int) contents[index]);
boolean onlySpaces = true;
while (index > 0) {
if (contents[index] == 10) {
if (onlySpaces) {
index++;
break;
} else {
onlySpaces = true; // reset
}
} else if (contents[index] != ' ') {
onlySpaces = false;
}
index--;
}
// if the first char, index will be -2
if (index < 0) index = 0;
if ((event.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
textarea.setSelectionStart(caretIndex);
textarea.setSelectionEnd(index);
} else {
textarea.setCaretPosition(index);
}
event.consume();
return true;
} else if ((code == KeyEvent.VK_DOWN) &&
((event.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
char contents[] = textarea.getText().toCharArray();
int caretIndex = textarea.getCaretPosition();
int index = caretIndex;
int lineStart = 0;
boolean onlySpaces = false; // don't count this line
while (index < contents.length) {
if (contents[index] == 10) {
if (onlySpaces) {
index = lineStart; // this is it
break;
} else {
lineStart = index + 1;
onlySpaces = true; // reset
}
} else if (contents[index] != ' ') {
onlySpaces = false;
}
index++;
}
// if the first char, index will be -2
//if (index < 0) index = 0;
//textarea.setSelectionStart(index);
//textarea.setSelectionEnd(index);
if ((event.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
textarea.setSelectionStart(caretIndex);
textarea.setSelectionEnd(index);
} else {
textarea.setCaretPosition(index);
}
event.consume();
return true;
}
switch ((int) c) { switch ((int) c) {
case 9: // expand tabs case 9: // expand tabs
if (expandTabs) { if (tabsExpand) {
//tc.replaceSelection(tabString);
textarea.setSelectedText(tabString); textarea.setSelectedText(tabString);
event.consume(); event.consume();
return true; return true;
} else if (tabsIndent) {
// this code is incomplete
// if this brace is the only thing on the line, outdent
//char contents[] = getCleanedContents();
char contents[] = textarea.getText().toCharArray();
// index to the character to the left of the caret
int prevCharIndex = textarea.getCaretPosition() - 1;
// now find the start of this line
int lineStart = calcLineStart(prevCharIndex, contents);
int lineEnd = lineStart;
while ((lineEnd < contents.length - 1) &&
(contents[lineEnd] != 10)) {
lineEnd++;
}
// get the number of braces, to determine whether this is an indent
int braceBalance = 0;
int index = lineStart;
while ((index < contents.length) &&
(contents[index] != 10)) {
if (contents[index] == '{') {
braceBalance++;
} else if (contents[index] == '}') {
braceBalance--;
}
index++;
}
// if it's a starting indent, need to ignore it, so lineStart
// will be the counting point. but if there's a closing indent,
// then the lineEnd should be used.
int where = (braceBalance > 0) ? lineStart : lineEnd;
int indent = calcBraceIndent(where, contents);
if (indent == -1) {
// no braces to speak of, do nothing
indent = 0;
} else {
indent += tabSize;
}
// and the number of spaces it has
int spaceCount = calcSpaceCount(prevCharIndex, contents);
textarea.setSelectionStart(lineStart);
textarea.setSelectionEnd(lineStart + spaceCount);
textarea.setSelectedText(Editor.EMPTY.substring(0, indent));
event.consume();
return true;
} }
break; break;
@ -115,13 +261,18 @@ public class EditorListener {
if (autoIndent) { if (autoIndent) {
char contents[] = textarea.getText().toCharArray(); char contents[] = textarea.getText().toCharArray();
// this is the position of the caret, if the textarea // this is the previous character
// only used a single kind of line ending // (i.e. when you hit return, it'll be the last character
// just before where the newline will be inserted)
int origIndex = textarea.getCaretPosition() - 1; int origIndex = textarea.getCaretPosition() - 1;
// NOTE all this cursing about CRLF stuff is probably moot
// NOTE since the switch to JEditTextArea, which seems to use
// NOTE only LFs internally (thank god). disabling for 0099.
// walk through the array to the current caret position, // walk through the array to the current caret position,
// and count how many weirdo windows line endings there are, // and count how many weirdo windows line endings there are,
// which would be throwing off the caret position number // which would be throwing off the caret position number
/*
int offset = 0; int offset = 0;
int realIndex = origIndex; int realIndex = origIndex;
for (int i = 0; i < realIndex-1; i++) { for (int i = 0; i < realIndex-1; i++) {
@ -130,38 +281,140 @@ public class EditorListener {
realIndex++; realIndex++;
} }
} }
// back up until \r \r\n or \n.. @#($* cross platform // back up until \r \r\n or \n.. @#($* cross platform
//System.out.println(origIndex + " offset = " + offset); //System.out.println(origIndex + " offset = " + offset);
origIndex += offset; // ARGH!#(* WINDOWS#@($* origIndex += offset; // ARGH!#(* WINDOWS#@($*
*/
int index = origIndex; int spaceCount = calcSpaceCount(origIndex, contents);
int spaceCount = 0; //int origCount = spaceCount;
boolean finished = false;
while ((index != -1) && (!finished)) { // now before inserting this many spaces, walk forward from
if ((contents[index] == 10) || // the caret position, so that the number of spaces aren't
(contents[index] == 13)) { // just being duplicated again
finished = true; int index = origIndex + 1;
index++; // maybe ? int extraCount = 0;
} else { while ((index < contents.length) &&
index--; // new (contents[index] == ' ')) {
//spaceCount--;
extraCount++;
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;
if (spaceCount - extraCount > 0) {
spaceCount -= extraCount;
}
// if the last character was a left curly brace, then indent
if (origIndex != -1) {
if (contents[origIndex] == '{') {
spaceCount += tabSize;
} }
} }
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
textarea.setSelectedText(insertion);
// mark this event as already handled
event.consume();
return true;
}
break;
case '}':
if (autoIndent) {
// first remove anything that was there (in case this multiple
// characters are selected, so that it's not in the way of the
// spaces for the auto-indent
if (textarea.getSelectionStart() != textarea.getSelectionEnd()) {
textarea.setSelectedText("");
}
// if this brace is the only thing on the line, outdent
char contents[] = textarea.getText().toCharArray();
// index to the character to the left of the caret
int prevCharIndex = textarea.getCaretPosition() - 1;
// backup from the current caret position to the last newline,
// checking for anything besides whitespace along the way.
// if there's something besides whitespace, exit without
// messing any sort of indenting.
int index = prevCharIndex;
boolean finished = false;
while ((index != -1) && (!finished)) {
if (contents[index] == 10) {
finished = true;
index++;
} else if (contents[index] != ' ') {
// don't do anything, this line has other stuff on it
return false;
} else {
index--;
}
}
if (!finished) return false; // brace with no start
int lineStartIndex = index;
/*
// now that we know things are ok to be indented, walk
// backwards to the last { to see how far its line is indented.
// this isn't perfect cuz it'll pick up commented areas,
// but that's not really a big deal and can be fixed when
// this is all given a more complete (proper) solution.
index = prevCharIndex;
int braceDepth = 1;
finished = false;
while ((index != -1) && (!finished)) {
if (contents[index] == '}') {
// aww crap, this means we're one deeper
// and will have to find one more extra {
braceDepth++;
index--;
} else if (contents[index] == '{') {
braceDepth--;
if (braceDepth == 0) {
finished = true;
} // otherwise just teasing, keep going..
} else {
index--;
}
}
// never found a proper brace, be safe and don't do anything
if (!finished) return false;
// check how many spaces on the line with the matching open brace
int pairedSpaceCount = calcSpaceCount(index, contents);
//System.out.println(pairedSpaceCount);
*/
int pairedSpaceCount = calcBraceIndent(prevCharIndex, contents); //, 1);
if (pairedSpaceCount == -1) return false;
/*
// now walk forward and figure out how many spaces there are
while ((index < contents.length) && (index >= 0) && while ((index < contents.length) && (index >= 0) &&
(contents[index++] == ' ')) { (contents[index++] == ' ')) {
spaceCount++; spaceCount++;
} }
*/
// seems that \r is being inserted anyway // number of spaces found on this line
// so no need to insert the platform's line separator //int newSpaceCount = Math.max(0, spaceCount - tabSize);
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount); // number of spaces on this current line
//tc.replaceSelection(insertion); //int spaceCount = calcSpaces(caretIndex, contents);
textarea.setSelectedText(insertion); //System.out.println("spaces is " + spaceCount);
// microsoft vm version: //String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
//tc.setCaretPosition(oldCarrot + insertion.length() - 1); //int differential = newSpaceCount - spaceCount;
// sun vm version: //System.out.println("diff is " + differential);
// tc.setCaretPosition(oldCarrot + insertion.length()); //int newStart = textarea.getSelectionStart() + differential;
//textarea.setSelectionStart(newStart);
//textarea.setSelectedText("}");
textarea.setSelectionStart(lineStartIndex);
textarea.setSelectedText(Editor.EMPTY.substring(0, pairedSpaceCount));
// mark this event as already handled
event.consume(); event.consume();
return true; return true;
} }
@ -169,4 +422,143 @@ public class EditorListener {
} }
return false; return false;
} }
/**
* Return the index for the first character on this line.
*/
protected int calcLineStart(int index, char contents[]) {
// backup from the current caret position to the last newline,
// so that we can figure out how far this line was indented
int spaceCount = 0;
boolean finished = false;
while ((index != -1) && (!finished)) {
if ((contents[index] == 10) ||
(contents[index] == 13)) {
finished = true;
//index++; // maybe ?
} else {
index--; // new
}
}
// add one because index is either -1 (the start of the document)
// or it's the newline character for the previous line
return index + 1;
}
/**
* Calculate the number of spaces on this line.
*/
protected int calcSpaceCount(int index, char contents[]) {
index = calcLineStart(index, contents);
int spaceCount = 0;
// now walk forward and figure out how many spaces there are
while ((index < contents.length) && (index >= 0) &&
(contents[index++] == ' ')) {
spaceCount++;
}
return spaceCount;
}
/**
* Walk back from 'index' until the brace that seems to be
* the beginning of the current block, and return the number of
* spaces found on that line.
*/
protected int calcBraceIndent(int index, char contents[]) {
// now that we know things are ok to be indented, walk
// backwards to the last { to see how far its line is indented.
// this isn't perfect cuz it'll pick up commented areas,
// but that's not really a big deal and can be fixed when
// this is all given a more complete (proper) solution.
int braceDepth = 1;
boolean finished = false;
while ((index != -1) && (!finished)) {
if (contents[index] == '}') {
// aww crap, this means we're one deeper
// and will have to find one more extra {
braceDepth++;
//if (braceDepth == 0) {
//finished = true;
//}
index--;
} else if (contents[index] == '{') {
braceDepth--;
if (braceDepth == 0) {
finished = true;
}
index--;
} else {
index--;
}
}
// never found a proper brace, be safe and don't do anything
if (!finished) return -1;
// check how many spaces on the line with the matching open brace
//int pairedSpaceCount = calcSpaceCount(index, contents);
//System.out.println(pairedSpaceCount);
return calcSpaceCount(index, contents);
}
/**
* Get the character array and blank out the commented areas.
* This hasn't yet been tested, the plan was to make auto-indent
* less gullible (it gets fooled by braces that are commented out).
*/
protected char[] getCleanedContents() {
char c[] = textarea.getText().toCharArray();
int index = 0;
while (index < c.length - 1) {
if ((c[index] == '/') && (c[index+1] == '*')) {
c[index++] = 0;
c[index++] = 0;
while ((index < c.length - 1) &&
!((c[index] == '*') && (c[index+1] == '/'))) {
c[index++] = 0;
}
} else if ((c[index] == '/') && (c[index+1] == '/')) {
// clear out until the end of the line
while ((index < c.length) && (c[index] != 10)) {
c[index++] = 0;
}
if (index != c.length) {
index++; // skip over the newline
}
}
}
return c;
}
/*
protected char[] getCleanedContents() {
char c[] = textarea.getText().toCharArray();
boolean insideMulti; // multi-line comment
boolean insideSingle; // single line double slash
//for (int i = 0; i < c.length - 1; i++) {
int index = 0;
while (index < c.length - 1) {
if (insideMulti && (c[index] == '*') && (c[index+1] == '/')) {
insideMulti = false;
index += 2;
} else if ((c[index] == '/') && (c[index+1] == '*')) {
insideMulti = true;
index += 2;
} else if ((c[index] == '/') && (c[index+1] == '/')) {
// clear out until the end of the line
while (c[index] != 10) {
c[index++] = 0;
}
index++;
}
}
}
*/
} }

View File

@ -422,7 +422,7 @@ public class EditorStatus extends JPanel implements ActionListener {
} else if (e.getSource() == yesButton) { } else if (e.getSource() == yesButton) {
// answer was in response to "save changes?" // answer was in response to "save changes?"
unprompt(); unprompt();
editor.handleSave(); editor.handleSave(true);
editor.checkModified2(); editor.checkModified2();
} else if (e.getSource() == cancelButton) { } else if (e.getSource() == cancelButton) {

View File

@ -29,10 +29,21 @@ import javax.swing.*;
/** /**
* Find & Replace window for the processing editor. * Find & Replace window for the Processing editor.
* <p/>
* One major annoyance in this is that the window is re-created each time
* that "Find" is called. This is because Mac OS X has a strange focus
* issue with windows that are re-shown with setVisible() or show().
* requestFocusInWindow() properly sets the focus to the find field,
* however, just a short moment later, the focus is set to null. Even
* trying to catch this scenario and request it again doesn't seem to work.
* Most likely this is some annoyance buried deep in one of Apple's docs,
* or in the doc for the focus stuff (I tend to think the former because
* Windows doesn't seem to be quite so beligerent). Filed as
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=244"> Bug 244</A>
* should anyone have clues about how to fix.
*/ */
public class FindReplace extends JFrame public class FindReplace extends JFrame implements ActionListener {
implements ActionListener, KeyListener {
static final int BIG = 13; static final int BIG = 13;
static final int SMALL = 6; static final int SMALL = 6;
@ -41,16 +52,17 @@ public class FindReplace extends JFrame
JTextField findField; JTextField findField;
JTextField replaceField; JTextField replaceField;
static String findString;
static String replaceString;
JButton replaceButton; JButton replaceButton;
JButton replaceAllButton; JButton replaceAllButton;
JButton findButton; JButton findButton;
JCheckBox ignoreCaseBox; JCheckBox ignoreCaseBox;
boolean ignoreCase; static boolean ignoreCase = true;
KeyStroke windowClose;
/// true when there's something selected in the editor
boolean found; boolean found;
@ -74,6 +86,27 @@ public class FindReplace extends JFrame
pain.add(replaceField = new JTextField(20)); pain.add(replaceField = new JTextField(20));
Dimension d2 = findField.getPreferredSize(); Dimension d2 = findField.getPreferredSize();
if (findString != null) findField.setText(findString);
if (replaceString != null) replaceField.setText(replaceString);
//System.out.println("setting find str to " + findString);
//findField.requestFocusInWindow();
//pain.setDefault
/*
findField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
System.out.println("Focus gained " + e.getOppositeComponent());
}
public void focusLost(FocusEvent e) {
System.out.println("Focus lost "); // + e.getOppositeComponent());
if (e.getOppositeComponent() == null) {
requestFocusInWindow();
}
}
});
*/
// +1 since it's better to tend downwards // +1 since it's better to tend downwards
int yoff = (1 + d2.height - d1.height) / 2; int yoff = (1 + d2.height - d1.height) / 2;
@ -82,7 +115,7 @@ public class FindReplace extends JFrame
replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff, replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff,
d1.width, d1.height); d1.width, d1.height);
ignoreCase = true; //ignoreCase = true;
ignoreCaseBox = new JCheckBox("Ignore Case"); ignoreCaseBox = new JCheckBox("Ignore Case");
ignoreCaseBox.addActionListener(new ActionListener() { ignoreCaseBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -110,12 +143,8 @@ public class FindReplace extends JFrame
} }
pain.add(buttons); pain.add(buttons);
// 0069 TEMPORARILY DISABLED!
//replaceAllButton.setEnabled(false);
// to fix ugliness.. normally macosx java 1.3 puts an // to fix ugliness.. normally macosx java 1.3 puts an
// ugly white border around this object, so turn it off. // ugly white border around this object, so turn it off.
//if (Base.platform == Base.MACOSX) {
if (Base.isMacOS()) { if (Base.isMacOS()) {
buttons.setBorder(null); buttons.setBorder(null);
} }
@ -146,7 +175,7 @@ public class FindReplace extends JFrame
replaceButton.setEnabled(false); replaceButton.setEnabled(false);
// so that typing will go straight to this field // so that typing will go straight to this field
findField.requestFocus(); //findField.requestFocus();
// make the find button the blinky default // make the find button the blinky default
getRootPane().setDefaultButton(findButton); getRootPane().setDefaultButton(findButton);
@ -161,48 +190,62 @@ public class FindReplace extends JFrame
(screen.height - high) / 2, wide, high); (screen.height - high) / 2, wide, high);
// add key listener to trap esc and ctrl/cmd-w // add key listener to trap esc and ctrl/cmd-w
findField.addKeyListener(this); /*
replaceField.addKeyListener(this); KeyListener listener = new KeyAdapter() {
addKeyListener(this); 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);
/*
// hack to to get first field to focus properly on osx // hack to to get first field to focus properly on osx
// though this still doesn't seem to work // though this still doesn't seem to work
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) { public void windowActivated(WindowEvent e) {
//System.out.println("activating"); //System.out.println("activating");
findField.requestFocus(); //boolean ok = findField.requestFocusInWindow();
findField.selectAll(); //System.out.println("got " + ok);
//findField.selectAll();
} }
}); });
*/
} }
/** public void handleClose() {
* Handle window closing commands for ctrl/cmd-W or hitting ESC. //System.out.println("handling close now");
*/ findString = findField.getText();
public void keyPressed(KeyEvent e) { replaceString = replaceField.getText();
if (windowClose == null) {
int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); // this object should eventually become dereferenced
windowClose = KeyStroke.getKeyStroke('W', modifiers); hide();
}
if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
(KeyStroke.getKeyStrokeForEvent(e).equals(windowClose))) {
hide();
//} else {
//System.out.println("event " + e);
}
} }
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
/* /*
public void show() { public void show() {
findField.requestFocusInWindow();
super.show(); super.show();
findField.selectAll(); //findField.selectAll();
findField.requestFocus(); //findField.requestFocus();
} }
*/ */
@ -266,9 +309,10 @@ public class FindReplace extends JFrame
} }
// replace the current selection with whatever's in the /**
// replacement text field * Replace the current selection with whatever's in the
* replacement text field.
*/
public void replace() { public void replace() {
if (!found) return; // don't replace if nothing found if (!found) return; // don't replace if nothing found
@ -284,15 +328,17 @@ public class FindReplace extends JFrame
editor.textarea.setSelectedText(replaceField.getText()); editor.textarea.setSelectedText(replaceField.getText());
//editor.setSketchModified(true); //editor.setSketchModified(true);
//editor.sketch.setCurrentModified(true); //editor.sketch.setCurrentModified(true);
editor.sketch.setModified(); editor.sketch.setModified(true);
// don't allow a double replace // don't allow a double replace
replaceButton.setEnabled(false); replaceButton.setEnabled(false);
} }
// keep doing find and replace alternately until nothing more found /**
* Replace everything that matches by doing find and replace
* alternately until nothing more found.
*/
public void replaceAll() { public void replaceAll() {
// move to the beginning // move to the beginning
editor.textarea.select(0, 0); editor.textarea.select(0, 0);

444
app/Library.java Executable file
View File

@ -0,0 +1,444 @@
/*
Library.java - Library System for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package processing.app;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/*
* Provides information about and builds a library
*/
public class Library implements MessageConsumer{
private File libFolder;
private LibraryManager libManager;
RunnerException exception;
static final String BUGS_URL = "https://developer.berlios.de/bugs/?group_id=3590";
static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL;
/*
* Create a Library
*/
public Library(LibraryManager manager, File folder)
{
libFolder = folder;
libManager = manager;
/* for debug output
System.out.println("library: " + getName());
System.out.println("folder: " + getFolder());
System.out.println("built: " + isBuilt());
System.out.println("buildable: " + isBuildable());
System.out.println("o files: " + getObjectFiles().length);
System.out.println("c files: " + getCSourceFiles().length);
System.out.println("cpp files: " + getCPPSourceFiles().length);
*/
}
/*
* Directory of library
* @return File object of library's folder
*/
public File getFolder()
{
return libFolder;
}
/*
* The name of library
* @return String with library name, derived from folder
* note: this will be eventually taken from xml description file
*/
public String getName()
{
return libFolder.getName();
}
/*
* Tests if library is built
* @return True if library has .o files, false otherwise
*/
public boolean isBuilt()
{
FileFilter onlyObjectFiles = new FileFilter() {
public boolean accept(File file) {
return file.getName().endsWith(".o");
}
};
if(0 < (libFolder.listFiles(onlyObjectFiles)).length){
return true;
}
return false;
}
/*
* Tests if library is buildable
* @return True if library has .cpp files, false otherwise
*/
public boolean isBuildable()
{
FileFilter onlySourceFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".cpp");
}
};
if(0 < (libFolder.listFiles(onlySourceFiles)).length){
return true;
}
return false;
}
/*
* Tests if library is unbuilt but buildable
* @return True if library has .cpp files but no .o files, false otherwise
*/
public boolean isUnbuiltBuildable()
{
if(isBuildable()){
if(!isBuilt()){
return true;
}
}
return false;
}
/*
* Finds examples folder
* @return "examples" folder as file object or null
*/
private File getExamplesFolder()
{
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
if(file.isDirectory()){
if((file.getName()).equalsIgnoreCase("examples")){
return true;
}
}
return false;
}
};
File[] files = libFolder.listFiles(filter);
if(files.length > 0){
return files[0];
}
return null;
}
/*
* Populates example menu or submenu with files
*/
private void populateWithExamples(File folder, JMenu menu, ActionListener listener) {
FileFilter onlyfolders = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
File[] folders = folder.listFiles(onlyfolders);
File file;
JMenu submenu;
JMenuItem item;
for(int i = 0; i < folders.length; ++i){
file = new File(folders[i], folders[i].getName() + ".pde");
if(file.exists()){
item = new JMenuItem(folders[i].getName());
item.setActionCommand(file.getAbsolutePath());
item.addActionListener(listener);
menu.add(item);
}else{
submenu = new JMenu(folders[i].getName());
populateWithExamples(folders[i], submenu, listener);
menu.add(submenu);
}
}
}
/*
* Builds and returns an examples menu
* @return JMenu object with example files, or null if none
*/
public JMenu getExamplesMenu(ActionListener listener) {
JMenu submenu;
File examplesFolder = getExamplesFolder();
if(null != examplesFolder){
submenu = new JMenu("Library-" + getName());
populateWithExamples(examplesFolder, submenu, listener);
return submenu;
}
return null;
}
/*
* List of object files for linking
* @return Array of library's object files as File objects
*/
public File[] getObjectFiles()
{
FileFilter onlyObjectFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".o");
}
};
return libFolder.listFiles(onlyObjectFiles);
}
/*
* List of header source files for inclusion
* @return Array of library's header source files as File objects
*/
public File[] getHeaderFiles()
{
FileFilter onlyHFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".h");
}
};
return libFolder.listFiles(onlyHFiles);
}
/*
* List of C source files for compiling
* @return Array of library's C source files as File objects
*/
private File[] getCSourceFiles()
{
FileFilter onlyCFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".c");
}
};
return libFolder.listFiles(onlyCFiles);
}
/*
* List of C++ source files for compiling
* @return Array of library's C++ source files as File objects
*/
private File[] getCPPSourceFiles()
{
FileFilter onlyCPPFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".cpp");
}
};
return libFolder.listFiles(onlyCPPFiles);
}
/*
* Attempt to build library
* @return true on successful build, false otherwise
*/
public boolean build() throws RunnerException
{
if(isBuildable()){
String userDir = System.getProperty("user.dir") + File.separator;
String[] baseCompileCommandC = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : userDir + "tools/avr/bin/avr-gcc"),
"-c",
"-g",
"-Os",
"-Wall",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-Ilib",
"-I" + getFolder(),
};
String[] baseCompileCommandCPP = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : userDir + "tools/avr/bin/avr-g++"),
"-c",
"-g",
"-Os",
"-Wall",
"-fno-exceptions",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-Ilib",
"-I" + getFolder(),
};
// use built lib directories in include paths when searching for headers
// this allows libs to use other libs easily
String[] libDirs = libManager.getFolderPaths();
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + 2];
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + 2];
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
for (int i = 0; i < libDirs.length; ++i) {
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
}
File[] sourcesC = getCSourceFiles();
File[] sourcesCPP = getCPPSourceFiles();
// execute the compiler, and create threads to deal
// with the input and error streams
//
int result = 0;
try {
String nameSansExtension;
Process process;
boolean compiling = true;
// compile c sources
for(int i = 0; i < sourcesC.length; ++i) {
nameSansExtension = sourcesC[i].getName();
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 2); // -2 because ".c"
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
compileCommandC[compileCommandC.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandC);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
// compile c++ sources
for(int i = 0; i < sourcesCPP.length; ++i) {
nameSansExtension = sourcesCPP[i].getName();
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 4); // -4 because ".cpp"
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandCPP);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
} catch (Exception e) {
String msg = e.getMessage();
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-gcc is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-g++ is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else {
e.printStackTrace();
result = -1;
}
}
// an error was queued up by message()
if (exception != null) {
throw exception;
}
if (result != 0 && result != 1 ) {
Base.openURL(BUGS_URL);
throw new RunnerException(SUPER_BADNESS);
}
// success would mean that 'result' is set to zero
return (result == 0); // ? true : false;
}
return false; // library is not buildable (contains no sources)
}
/**
* Part of the MessageConsumer interface, this is called
* whenever a piece (usually a line) of error message is spewed
* out from the compiler. The errors are parsed for their contents
* and line number, which is then reported back to Editor.
*/
public void message(String inString) {
// This receives messages as full lines, so a newline needs
// to be added as they're printed to the console.
// always print all compilation output for library writers!
String outString = "";
// shorten file paths so that they are friendlier
int start = 0;
int end = 0;
String substring = libFolder.getPath() + File.separator;
StringBuffer result = new StringBuffer();
while ((end = inString.indexOf(substring, start)) >= 0) {
result.append(inString.substring(start, end));
start = end + substring.length();
}
result.append(inString.substring(start));
outString = result.toString();
System.err.print(outString);
// prepare error for throwing
if (inString.indexOf("error") != -1){
exception = new RunnerException("Error building library \"" + getName() + "\"");
}
}
}

217
app/LibraryManager.java Executable file
View File

@ -0,0 +1,217 @@
/*
LibraryManager.java - Library System for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package processing.app;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.awt.event.*;
import javax.swing.*;
/*
* Provides information about and builds libraries
*/
public class LibraryManager {
private File libDir;
private List libraries = new ArrayList();
/*
* Create a LibraryManager.
*/
public LibraryManager()
{
String userDir = System.getProperty("user.dir") + File.separator;
libDir = new File(
((!Base.isMacOS()) ? "" : userDir) + "lib" + File.separator +
"targets" + File.separator + "libraries");
refreshLibraries();
}
/*
* Scans for libraries and refreshes internal list
*/
private void refreshLibraries()
{
FileFilter onlyDirs = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
libraries.clear();
File[] libs = libDir.listFiles(onlyDirs);
for(int i = 0; i < libs.length; ++i){
libraries.add(new Library(this, libs[i]));
}
}
/*
* Returns a collection of all library objects
* @return A read-only collection of Library objects
*/
public Collection getAll() {
refreshLibraries();
return Collections.unmodifiableList(libraries);
}
/*
* Returns a collection of all built library objects
* @return A read-only collection of built Library objects
*/
public Collection getBuiltLibraries() {
refreshLibraries();
List builtLibraries = new ArrayList();
Library library;
ListIterator libIterator = libraries.listIterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
if(library.isBuilt()){
builtLibraries.add(library);
}
}
return Collections.unmodifiableList(builtLibraries);
}
/*
* Returns a collection of all buildable library objects
* @return A read-only collection of built Library objects
*/
public Collection getLibrariesToBuild() {
refreshLibraries();
List buildableLibraries = new ArrayList();
Library library;
ListIterator libIterator = libraries.listIterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
if(library.isUnbuiltBuildable()){
buildableLibraries.add(library);
}
}
return Collections.unmodifiableList(buildableLibraries);
}
/*
* Gathers paths to object files
* @return Array of strings of paths to object files
*/
public String[] getObjectFiles() {
ArrayList filesArrayList = new ArrayList();
Collection builtLibraries = getBuiltLibraries();
Library library;
File[] files;
Iterator libIterator = builtLibraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
files = library.getObjectFiles();
for(int i = 0; i < files.length; ++i){
filesArrayList.add(files[i].getPath());
}
}
String[] filesArray = new String[filesArrayList.size()];
filesArrayList.toArray(filesArray);
return filesArray;
}
/*
* Gathers filenames of header files
* @return Array of strings of filenames of header files
*/
public String[] getHeaderFiles() {
ArrayList filesArrayList = new ArrayList();
Collection builtLibraries = getBuiltLibraries();
Library library;
File[] files;
Iterator libIterator = builtLibraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
files = library.getHeaderFiles();
for(int i = 0; i < files.length; ++i){
filesArrayList.add(files[i].getName());
}
}
String[] filesArray = new String[filesArrayList.size()];
filesArrayList.toArray(filesArray);
return filesArray;
}
/*
* Gathers paths to library folders
* @return Array of strings of paths to library folders
*/
public String[] getFolderPaths() {
ArrayList foldersArrayList = new ArrayList();
Collection builtLibraries = getBuiltLibraries();
Library library;
Iterator libIterator = builtLibraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
foldersArrayList.add(library.getFolder().getPath());
}
String[] foldersArray = new String[foldersArrayList.size()];
foldersArrayList.toArray(foldersArray);
return foldersArray;
}
/*
* Builds unbuilt libraries
* @return Number of libraries built as int, -1 & exception on error
*/
public int buildAllUnbuilt() throws RunnerException {
Collection buildableLibraries = getLibrariesToBuild();
Library library;
Iterator libIterator = buildableLibraries.iterator();
int countBuilt = 0;
while(libIterator.hasNext()){
library = (Library)libIterator.next();
//System.out.println("Building library \"" + library.getName() + "\"");
try {
if(library.build()){
++countBuilt;
}else{
return -1;
}
}catch (RunnerException re) {
throw new RunnerException(re.getMessage());
} catch (Exception ex) {
throw new RunnerException(ex.toString());
}
}
return countBuilt;
}
/*
* Populates examples menu with library folders
*/
public void populateExamplesMenu(JMenu examplesMenu, ActionListener listener) {
Library library;
Collection libraries = getBuiltLibraries();
Iterator iterator = libraries.iterator();
JMenu libraryExamples;
while(iterator.hasNext()){
library = (Library)iterator.next();
libraryExamples = library.getExamplesMenu(listener);
if(null != libraryExamples){
examplesMenu.add(libraryExamples);
}
}
}
}

View File

@ -41,6 +41,7 @@ import javax.swing.filechooser.*;
import javax.swing.text.*; import javax.swing.text.*;
import javax.swing.undo.*; import javax.swing.undo.*;
//import processing.core.PApplet;
/** /**
@ -50,7 +51,7 @@ import javax.swing.undo.*;
* properties files are iso8859-1, which is highly likely to * properties files are iso8859-1, which is highly likely to
* be a problem when trying to save sketch folders and locations. * be a problem when trying to save sketch folders and locations.
*/ */
public class Preferences extends JComponent { public class Preferences {
// what to call the feller // what to call the feller
@ -72,16 +73,32 @@ public class Preferences extends JComponent {
static final String PROMPT_OK = "OK"; static final String PROMPT_OK = "OK";
static final String PROMPT_BROWSE = "Browse"; static final String PROMPT_BROWSE = "Browse";
// mac needs it to be 70, windows needs 66, linux needs 76 /**
* Standardized width for buttons. Mac OS X 10.3 wants 70 as its default,
* Windows XP needs 66, and Linux needs 76, so 76 seems proper.
*/
static public int BUTTON_WIDTH = 76;
static int BUTTON_WIDTH = 76; /**
static int BUTTON_HEIGHT = 24; * Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29,
* presumably because it now includes the blue border, where it didn't
* in Java 1.3. Windows XP only wants 23 (not sure what default Linux
* would be). Because of the disparity, on Mac OS X, it will be set
* inside a static block.
*/
static public int BUTTON_HEIGHT = 24;
static {
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
}
// value for the size bars, buttons, etc // value for the size bars, buttons, etc
static final int GRID_SIZE = 33; static final int GRID_SIZE = 33;
// gui variables
// indents and spacing standards. these probably need to be modified
// per platform as well, since macosx is so huge, windows is smaller,
// and linux is all over the map
static final int GUI_BIG = 13; static final int GUI_BIG = 13;
static final int GUI_BETWEEN = 10; static final int GUI_BETWEEN = 10;
@ -89,14 +106,12 @@ public class Preferences extends JComponent {
// gui elements // gui elements
//JFrame frame; JDialog dialog;
JDialog frame;
int wide, high; int wide, high;
JTextField sketchbookLocationField; JTextField sketchbookLocationField;
JCheckBox sketchPromptBox; JCheckBox sketchPromptBox;
JCheckBox sketchCleanBox; JCheckBox sketchCleanBox;
//JCheckBox exportLibraryBox;
JCheckBox externalEditorBox; JCheckBox externalEditorBox;
JCheckBox checkUpdatesBox; JCheckBox checkUpdatesBox;
@ -111,7 +126,6 @@ public class Preferences extends JComponent {
static Hashtable table = new Hashtable();; static Hashtable table = new Hashtable();;
static File preferencesFile; static File preferencesFile;
//boolean firstTime; // first time this feller has been run
static public void init() { static public void init() {
@ -152,9 +166,6 @@ public class Preferences extends JComponent {
// next load user preferences file // next load user preferences file
//File home = new File(System.getProperty("user.home"));
//File arduinoHome = new File(home, "Arduino");
//preferencesFile = new File(home, PREFS_FILE);
preferencesFile = Base.getSettingsFile(PREFS_FILE); preferencesFile = Base.getSettingsFile(PREFS_FILE);
if (!preferencesFile.exists()) { if (!preferencesFile.exists()) {
@ -181,14 +192,12 @@ public class Preferences extends JComponent {
public Preferences() { public Preferences() {
// setup frame for the prefs // setup dialog for the prefs
//frame = new JFrame("Preferences"); dialog = new JDialog(editor, "Preferences", true);
frame = new JDialog(editor, "Preferences", true); dialog.setResizable(false);
//frame.setResizable(false);
//Container pain = this; Container pain = dialog.getContentPane();
Container pain = frame.getContentPane();
pain.setLayout(null); pain.setLayout(null);
int top = GUI_BIG; int top = GUI_BIG;
@ -284,20 +293,6 @@ public class Preferences extends JComponent {
top += d.height + GUI_BETWEEN; top += d.height + GUI_BETWEEN;
// [ ] Enable export to "Library"
/*
exportLibraryBox = new JCheckBox("Enable advanced \"Library\" features" +
" (requires restart)");
exportLibraryBox.setEnabled(false);
pain.add(exportLibraryBox);
d = exportLibraryBox.getPreferredSize();
exportLibraryBox.setBounds(left, top, d.width, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
*/
// [ ] Use external editor // [ ] Use external editor
externalEditorBox = new JCheckBox("Use external editor"); externalEditorBox = new JCheckBox("Use external editor");
@ -320,21 +315,6 @@ public class Preferences extends JComponent {
// More preferences are in the ... // More preferences are in the ...
/*
String blather =
"More preferences can be edited directly\n" +
"in the file " + preferencesFile.getAbsolutePath();
//"More preferences are in the 'lib' folder inside text files\n" +
//"named preferences.txt and pde_" +
//Base.platforms[Base.platform] + ".properties";
JTextArea textarea = new JTextArea(blather);
textarea.setEditable(false);
textarea.setBorder(new EmptyBorder(0, 0, 0, 0));
textarea.setBackground(null);
textarea.setFont(new Font("Dialog", Font.PLAIN, 12));
pain.add(textarea);
*/
label = new JLabel("More preferences can be edited directly in the file"); label = new JLabel("More preferences can be edited directly in the file");
pain.add(label); pain.add(label);
@ -362,9 +342,6 @@ public class Preferences extends JComponent {
// [ OK ] [ Cancel ] maybe these should be next to the message? // [ OK ] [ Cancel ] maybe these should be next to the message?
//right = Math.max(right, left + d.width + GUI_BETWEEN +
// BUTTON_WIDTH + GUI_SMALL + BUTTON_WIDTH);
button = new JButton(PROMPT_OK); button = new JButton(PROMPT_OK);
button.addActionListener(new ActionListener() { button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -376,9 +353,6 @@ public class Preferences extends JComponent {
d2 = button.getPreferredSize(); d2 = button.getPreferredSize();
BUTTON_HEIGHT = d2.height; BUTTON_HEIGHT = d2.height;
// smoosh up to the line before
//top -= BUTTON_HEIGHT;
h = right - (BUTTON_WIDTH + GUI_SMALL + BUTTON_WIDTH); h = right - (BUTTON_WIDTH + GUI_SMALL + BUTTON_WIDTH);
button.setBounds(h, top, BUTTON_WIDTH, BUTTON_HEIGHT); button.setBounds(h, top, BUTTON_WIDTH, BUTTON_HEIGHT);
h += BUTTON_WIDTH + GUI_SMALL; h += BUTTON_WIDTH + GUI_SMALL;
@ -398,32 +372,39 @@ public class Preferences extends JComponent {
// finish up // finish up
wide = right + GUI_BIG; wide = right + GUI_BIG;
high = top + GUI_SMALL; //GUI_BIG; high = top + GUI_SMALL;
setSize(wide, high); //setSize(wide, high);
// closing the window is same as hitting cancel button // closing the window is same as hitting cancel button
frame.addWindowListener(new WindowAdapter() { dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
disposeFrame(); disposeFrame();
} }
}); });
Container content = frame.getContentPane(); ActionListener disposer = new ActionListener() {
content.setLayout(new BorderLayout()); public void actionPerformed(ActionEvent actionEvent) {
content.add(this, BorderLayout.CENTER); disposeFrame();
}
frame.pack(); };
Base.registerWindowCloseKeys(dialog.getRootPane(), disposer);
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screen.width - wide) / 2, dialog.setLocation((screen.width - wide) / 2,
(screen.height - high) / 2); (screen.height - high) / 2);
dialog.pack(); // get insets
Insets insets = dialog.getInsets();
dialog.setSize(wide + insets.left + insets.right,
high + insets.top + insets.bottom);
// handle window closing commands for ctrl/cmd-W or hitting ESC. // handle window closing commands for ctrl/cmd-W or hitting ESC.
addKeyListener(new KeyAdapter() { pain.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE; KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) || if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
@ -435,6 +416,26 @@ public class Preferences extends JComponent {
} }
/*
protected JRootPane createRootPane() {
System.out.println("creating root pane esc received");
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//setVisible(false);
System.out.println("esc received");
}
};
JRootPane rootPane = new JRootPane();
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
rootPane.registerKeyboardAction(actionListener, stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
return rootPane;
}
*/
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
return new Dimension(wide, high); return new Dimension(wide, high);
} }
@ -447,7 +448,7 @@ public class Preferences extends JComponent {
* Close the window after an OK or Cancel. * Close the window after an OK or Cancel.
*/ */
public void disposeFrame() { public void disposeFrame() {
frame.dispose(); dialog.dispose();
} }
@ -487,7 +488,7 @@ public class Preferences extends JComponent {
externalEditorBox.setSelected(getBoolean("editor.external")); externalEditorBox.setSelected(getBoolean("editor.external"));
checkUpdatesBox.setSelected(getBoolean("update.check")); checkUpdatesBox.setSelected(getBoolean("update.check"));
frame.show(); dialog.show();
} }

View File

@ -1,7 +1,7 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* /*
Part of the Arduino project - http://arduino.berlios.de/ Part of the Processing project - http://processing.org
Copyright (c) 2004-05 Ben Fry and Casey Reas Copyright (c) 2004-05 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology Copyright (c) 2001-04 Massachusetts Institute of Technology
@ -19,8 +19,6 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id$
*/ */
package processing.app; package processing.app;
@ -67,7 +65,12 @@ public class Sketch {
public File codeFolder; public File codeFolder;
static final int PDE = 0; static final int PDE = 0;
static final int JAVA = 1; static final int CPP = 1;
static final int C = 2;
static final int HEADER = 3;
static final String flavorExtensionsReal[] = new String[] { ".pde", ".cpp", ".c", ".h" };
static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
public SketchCode current; public SketchCode current;
int codeCount; int codeCount;
@ -104,6 +107,8 @@ public class Sketch {
name = mainFilename.substring(0, mainFilename.length() - 4); name = mainFilename.substring(0, mainFilename.length() - 4);
} else if (mainFilename.endsWith(".c")) { } else if (mainFilename.endsWith(".c")) {
name = mainFilename.substring(0, mainFilename.length() - 2); name = mainFilename.substring(0, mainFilename.length() - 2);
} else if (mainFilename.endsWith(".h")) {
name = mainFilename.substring(0, mainFilename.length() - 2);
} else if (mainFilename.endsWith(".cpp")) { } else if (mainFilename.endsWith(".cpp")) {
name = mainFilename.substring(0, mainFilename.length() - 4); name = mainFilename.substring(0, mainFilename.length() - 4);
} }
@ -157,9 +162,11 @@ public class Sketch {
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
if (list[i].endsWith(".pde")) codeCount++; if (list[i].endsWith(".pde")) codeCount++;
else if (list[i].endsWith(".c")) codeCount++; else if (list[i].endsWith(".c")) codeCount++;
else if (list[i].endsWith(".h")) codeCount++;
else if (list[i].endsWith(".cpp")) codeCount++; else if (list[i].endsWith(".cpp")) codeCount++;
else if (list[i].endsWith(".pde.x")) hiddenCount++; else if (list[i].endsWith(".pde.x")) hiddenCount++;
else if (list[i].endsWith(".c.x")) hiddenCount++; else if (list[i].endsWith(".c.x")) hiddenCount++;
else if (list[i].endsWith(".h.x")) hiddenCount++;
else if (list[i].endsWith(".cpp.x")) hiddenCount++; else if (list[i].endsWith(".cpp.x")) hiddenCount++;
} }
@ -180,13 +187,19 @@ public class Sketch {
code[codeCounter++] = code[codeCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 2), new SketchCode(list[i].substring(0, list[i].length() - 2),
new File(folder, list[i]), new File(folder, list[i]),
JAVA); C);
} else if (list[i].endsWith(".h")) {
code[codeCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 2),
new File(folder, list[i]),
HEADER);
} else if (list[i].endsWith(".cpp")) { } else if (list[i].endsWith(".cpp")) {
code[codeCounter++] = code[codeCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 4), new SketchCode(list[i].substring(0, list[i].length() - 4),
new File(folder, list[i]), new File(folder, list[i]),
JAVA); CPP);
} else if (list[i].endsWith(".pde.x")) { } else if (list[i].endsWith(".pde.x")) {
hidden[hiddenCounter++] = hidden[hiddenCounter++] =
@ -198,12 +211,17 @@ public class Sketch {
hidden[hiddenCounter++] = hidden[hiddenCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 4), new SketchCode(list[i].substring(0, list[i].length() - 4),
new File(folder, list[i]), new File(folder, list[i]),
JAVA); C);
} else if (list[i].endsWith(".h.x")) {
hidden[hiddenCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 4),
new File(folder, list[i]),
HEADER);
} else if (list[i].endsWith(".cpp.x")) { } else if (list[i].endsWith(".cpp.x")) {
hidden[hiddenCounter++] = hidden[hiddenCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 6), new SketchCode(list[i].substring(0, list[i].length() - 6),
new File(folder, list[i]), new File(folder, list[i]),
JAVA); CPP);
} }
} }
@ -314,8 +332,7 @@ public class Sketch {
renamingCode = true; renamingCode = true;
String prompt = (current == code[0]) ? String prompt = (current == code[0]) ?
"New name for sketch:" : "New name for file:"; "New name for sketch:" : "New name for file:";
String oldName = String oldName = current.name + flavorExtensionsShown[current.flavor];
(current.flavor == PDE) ? current.name : current.name + ".cpp";
editor.status.edit(prompt, oldName); editor.status.edit(prompt, oldName);
} }
@ -348,6 +365,7 @@ public class Sketch {
} }
if (newName.trim().equals(".c") || if (newName.trim().equals(".c") ||
newName.trim().equals(".h") ||
newName.trim().equals(".pde") || newName.trim().equals(".pde") ||
newName.trim().equals(".cpp")) { newName.trim().equals(".cpp")) {
return; return;
@ -363,23 +381,28 @@ public class Sketch {
newName = newName.substring(0, newName.length() - 4); newName = newName.substring(0, newName.length() - 4);
newFlavor = PDE; newFlavor = PDE;
} else if (newName.endsWith(".c") || newName.endsWith(".cpp")) { } else if (newName.endsWith(".c") || newName.endsWith(".cpp") ||
newName.endsWith(".h")) {
// don't show this error if creating a new tab // don't show this error if creating a new tab
if (renamingCode && (code[0] == current)) { if (renamingCode && (code[0] == current)) {
Base.showWarning("Problem with rename", Base.showWarning("Problem with rename",
"The main .pde file cannot be .c or .cpp file.\n" + "The main .pde file cannot be .c, .cpp, or .h file.\n" +
"(It may be time for your to graduate to a\n" + "(It may be time for your to graduate to a\n" +
"\"real\" programming environment)", null); "\"real\" programming environment)", null);
return; return;
} }
newFilename = newName; newFilename = newName;
if(newName.endsWith(".c")) if(newName.endsWith(".c")) {
newName = newName.substring(0, newName.length() - 2); newName = newName.substring(0, newName.length() - 2);
else if(newName.endsWith(".cpp")) newFlavor = C;
} if(newName.endsWith(".h")) {
newName = newName.substring(0, newName.length() - 2);
newFlavor = HEADER;
} else if(newName.endsWith(".cpp")) {
newName = newName.substring(0, newName.length() - 4); newName = newName.substring(0, newName.length() - 4);
newFlavor = JAVA; newFlavor = CPP;
}
} else { } else {
newFilename = newName + ".pde"; newFilename = newName + ".pde";
newFlavor = PDE; newFlavor = PDE;
@ -538,7 +561,7 @@ public class Sketch {
sortCode(); sortCode();
// set the new guy as current // set the new guy as current
setCurrent(newName); setCurrent(newName + flavorExtensionsShown[newFlavor]);
// update the tabs // update the tabs
//editor.header.repaint(); //editor.header.repaint();
@ -572,7 +595,8 @@ public class Sketch {
Object[] options = { "OK", "Cancel" }; Object[] options = { "OK", "Cancel" };
String prompt = (current == code[0]) ? String prompt = (current == code[0]) ?
"Are you sure you want to delete this sketch?" : "Are you sure you want to delete this sketch?" :
"Are you sure you want to delete \"" + current.name + "\"?"; "Are you sure you want to delete \"" + current.name +
flavorExtensionsShown[current.flavor] + "\"?";
int result = JOptionPane.showOptionDialog(editor, int result = JOptionPane.showOptionDialog(editor,
prompt, prompt,
"Delete", "Delete",
@ -684,9 +708,14 @@ public class Sketch {
public void unhideCode(String what) { public void unhideCode(String what) {
SketchCode unhideCode = null; SketchCode unhideCode = null;
String name = what.substring(0,
(what.indexOf(".") == -1 ? what.length() : what.indexOf(".")));
String extension = what.indexOf(".") == -1 ? "" :
what.substring(what.indexOf("."));
for (int i = 0; i < hiddenCount; i++) { for (int i = 0; i < hiddenCount; i++) {
if (hidden[i].name.equals(what)) { if (hidden[i].name.equals(name) &&
Sketch.flavorExtensionsShown[hidden[i].flavor].equals(extension)) {
//unhideIndex = i; //unhideIndex = i;
unhideCode = hidden[i]; unhideCode = hidden[i];
@ -730,8 +759,8 @@ public class Sketch {
/** /**
* Sets the modified value for the code in the frontmost tab. * Sets the modified value for the code in the frontmost tab.
*/ */
public void setModified() { public void setModified(boolean state) {
current.modified = true; current.modified = state;
calcModified(); calcModified();
} }
@ -996,6 +1025,26 @@ public class Sketch {
// it move instead of copy, they can do it by hand // it move instead of copy, they can do it by hand
File sourceFile = new File(directory, filename); File sourceFile = new File(directory, filename);
// now do the work of adding the file
addFile(sourceFile);
}
/**
* Add a file to the sketch.
* <p/>
* .pde or .java files will be added to the sketch folder. <br/>
* .jar, .class, .dll, .jnilib, and .so files will all
* be added to the "code" folder. <br/>
* All other files will be added to the "data" folder.
* <p/>
* If they don't exist already, the "code" or "data" folder
* will be created.
* <p/>
* @return true if successful.
*/
public boolean addFile(File sourceFile) {
String filename = sourceFile.getName();
File destFile = null; File destFile = null;
boolean addingCode = false; boolean addingCode = false;
@ -1012,6 +1061,7 @@ public class Sketch {
} else if (filename.toLowerCase().endsWith(".pde") || } else if (filename.toLowerCase().endsWith(".pde") ||
filename.toLowerCase().endsWith(".c") || filename.toLowerCase().endsWith(".c") ||
filename.toLowerCase().endsWith(".h") ||
filename.toLowerCase().endsWith(".cpp")) { filename.toLowerCase().endsWith(".cpp")) {
destFile = new File(this.folder, filename); destFile = new File(this.folder, filename);
addingCode = true; addingCode = true;
@ -1028,7 +1078,7 @@ public class Sketch {
"This file has already been copied to the\n" + "This file has already been copied to the\n" +
"location where you're trying to add it.\n" + "location where you're trying to add it.\n" +
"I ain't not doin nuthin'.", null); "I ain't not doin nuthin'.", null);
return; return false;
} }
// in case the user is "adding" the code in an attempt // in case the user is "adding" the code in an attempt
@ -1036,10 +1086,12 @@ public class Sketch {
if (!sourceFile.equals(destFile)) { if (!sourceFile.equals(destFile)) {
try { try {
Base.copyFile(sourceFile, destFile); Base.copyFile(sourceFile, destFile);
} catch (IOException e) { } catch (IOException e) {
Base.showWarning("Error adding file", Base.showWarning("Error adding file",
"Could not add '" + filename + "Could not add '" + filename +
"' to the sketch.", e); "' to the sketch.", e);
return false;
} }
} }
@ -1050,9 +1102,15 @@ public class Sketch {
if (newName.toLowerCase().endsWith(".pde")) { if (newName.toLowerCase().endsWith(".pde")) {
newName = newName.substring(0, newName.length() - 4); newName = newName.substring(0, newName.length() - 4);
newFlavor = PDE; newFlavor = PDE;
} else { } else if (newName.toLowerCase().endsWith(".c")) {
newName = newName.substring(0, newName.length() - 2); newName = newName.substring(0, newName.length() - 2);
newFlavor = JAVA; newFlavor = C;
} else if (newName.toLowerCase().endsWith(".h")) {
newName = newName.substring(0, newName.length() - 2);
newFlavor = HEADER;
} else { // ".cpp"
newName = newName.substring(0, newName.length() - 4);
newFlavor = CPP;
} }
// see also "nameCode" for identical situation // see also "nameCode" for identical situation
@ -1062,6 +1120,7 @@ public class Sketch {
setCurrent(newName); setCurrent(newName);
editor.header.repaint(); editor.header.repaint();
} }
return true;
} }
@ -1145,8 +1204,15 @@ public class Sketch {
* based on a name (used by codeNew and codeRename). * based on a name (used by codeNew and codeRename).
*/ */
protected void setCurrent(String findName) { protected void setCurrent(String findName) {
SketchCode unhideCode = null;
String name = findName.substring(0,
(findName.indexOf(".") == -1 ? findName.length() : findName.indexOf(".")));
String extension = findName.indexOf(".") == -1 ? "" :
findName.substring(findName.indexOf("."));
for (int i = 0; i < codeCount; i++) { for (int i = 0; i < codeCount; i++) {
if (findName.equals(code[i].name)) { if (name.equals(code[i].name) &&
Sketch.flavorExtensionsShown[code[i].flavor].equals(extension)) {
setCurrent(i); setCurrent(i);
return; return;
} }
@ -1264,6 +1330,20 @@ public class Sketch {
*/ */
protected String build(Target target, String buildPath, String suggestedClassName) protected String build(Target target, String buildPath, String suggestedClassName)
throws RunnerException { throws RunnerException {
// build unbuilt buildable libraries
// completely independent from sketch, so run all the time
LibraryManager libraryManager = new LibraryManager();
try {
libraryManager.buildAllUnbuilt();
} catch (RunnerException re) {
throw new RunnerException(re.getMessage());
} catch (Exception ex) {
throw new RunnerException(ex.toString());
}
// update sketchbook menu, this adds examples of any built libs
editor.sketchbook.rebuildMenus();
// make sure the user didn't hide the sketch folder // make sure the user didn't hide the sketch folder
ensureExistence(); ensureExistence();
@ -1316,7 +1396,7 @@ public class Sketch {
// check to see if multiple files that include a .java file // check to see if multiple files that include a .java file
externalRuntime = false; externalRuntime = false;
for (int i = 0; i < codeCount; i++) { for (int i = 0; i < codeCount; i++) {
if (code[i].flavor == JAVA) { if (code[i].flavor == C || code[i].flavor == CPP) {
externalRuntime = true; externalRuntime = true;
break; break;
} }
@ -1382,7 +1462,6 @@ public class Sketch {
//System.out.println(); //System.out.println();
} else { } else {
//code[0].preprocName = className + "." + Preferences.get("build.extension");
code[0].preprocName = className + ".cpp"; code[0].preprocName = className + ".cpp";
} }
@ -1408,6 +1487,7 @@ public class Sketch {
} }
errorLine -= code[errorFile].preprocOffset; errorLine -= code[errorFile].preprocOffset;
errorLine -= preprocessor.prototypeCount; errorLine -= preprocessor.prototypeCount;
errorLine -= preprocessor.headerCount;
throw new RunnerException(re.getMessage(), errorFile, throw new RunnerException(re.getMessage(), errorFile,
errorLine, re.getColumn()); errorLine, re.getColumn());
@ -1449,6 +1529,7 @@ public class Sketch {
} }
errorLine -= code[errorFile].preprocOffset; errorLine -= code[errorFile].preprocOffset;
errorLine -= preprocessor.prototypeCount; errorLine -= preprocessor.prototypeCount;
errorLine -= preprocessor.headerCount;
throw new RunnerException(tsre.getMessage(), throw new RunnerException(tsre.getMessage(),
errorFile, errorLine, errorColumn); errorFile, errorLine, errorColumn);
@ -1507,13 +1588,12 @@ public class Sketch {
// 3. then loop over the code[] and save each .java file // 3. then loop over the code[] and save each .java file
for (int i = 0; i < codeCount; i++) { for (int i = 0; i < codeCount; i++) {
if (code[i].flavor == JAVA) { if (code[i].flavor == CPP || code[i].flavor == C || code[i].flavor == HEADER) {
// no pre-processing services necessary for java files // no pre-processing services necessary for java files
// just write the the contents of 'program' to a .java file // just write the the contents of 'program' to a .java file
// into the build directory. uses byte stream and reader/writer // into the build directory. uses byte stream and reader/writer
// shtuff so that unicode bunk is properly handled // shtuff so that unicode bunk is properly handled
//String filename = code[i].name + "." + Preferences.get("build.extension"); String filename = code[i].name + flavorExtensionsReal[code[i].flavor];
String filename = code[i].name + ".cpp";
try { try {
Base.saveFile(code[i].program, new File(buildPath, filename)); Base.saveFile(code[i].program, new File(buildPath, filename));
} catch (IOException e) { } catch (IOException e) {
@ -1538,7 +1618,7 @@ public class Sketch {
} catch (RunnerException re) { } catch (RunnerException re) {
throw new RunnerException(re.getMessage(), throw new RunnerException(re.getMessage(),
re.file, re.file,
re.line - preprocessor.prototypeCount, re.line - preprocessor.prototypeCount - preprocessor.headerCount,
re.column); re.column);
} catch (Exception ex) { } catch (Exception ex) {
// TODO better method for handling this? // TODO better method for handling this?

View File

@ -382,10 +382,18 @@ public class Sketchbook {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
LibraryManager libManager = new LibraryManager();
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
editor.handleOpen(e.getActionCommand());
}
};
try { try {
JMenu examplesMenu = new JMenu("Examples"); JMenu examplesMenu = new JMenu("Examples");
addSketches(examplesMenu, examplesFolder); addSketches(examplesMenu, examplesFolder);
libManager.populateExamplesMenu(examplesMenu, listener);
menu.add(examplesMenu); menu.add(examplesMenu);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -542,8 +550,10 @@ public class Sketchbook {
list[i].equals("CVS")) continue; list[i].equals("CVS")) continue;
File subfolder = new File(folder, list[i]); File subfolder = new File(folder, list[i]);
if (!subfolder.isDirectory()) continue;
File exported = new File(subfolder, "library"); File exported = new File(subfolder, "library");
File entry = new File(exported, list[i] + ".jar"); File entry = new File(exported, list[i] + ".o");
// if a .jar file of the same prefix as the folder exists // if a .jar file of the same prefix as the folder exists
// inside the 'library' subfolder of the sketch // inside the 'library' subfolder of the sketch
if (entry.exists()) { if (entry.exists()) {
@ -556,7 +566,7 @@ public class Sketchbook {
Base.showMessage("Ignoring bad sketch name", mess); Base.showMessage("Ignoring bad sketch name", mess);
continue; continue;
} }
/*
// get the path for all .jar files in this code folder // get the path for all .jar files in this code folder
String libraryClassPath = String libraryClassPath =
Compiler.contentsToClassPath(exported); Compiler.contentsToClassPath(exported);
@ -565,12 +575,12 @@ public class Sketchbook {
librariesClassPath += librariesClassPath +=
File.pathSeparatorChar + libraryClassPath; File.pathSeparatorChar + libraryClassPath;
// need to associate each import with a library folder // need to associate each import with a library folder
String packages[] = new String[0]; String packages[] =
//Compiler.packageListFromClassPath(libraryClassPath); Compiler.packageListFromClassPath(libraryClassPath);
for (int k = 0; k < packages.length; k++) { for (int k = 0; k < packages.length; k++) {
importToLibraryTable.put(packages[k], exported); importToLibraryTable.put(packages[k], exported);
} }
*/
JMenuItem item = new JMenuItem(list[i]); JMenuItem item = new JMenuItem(list[i]);
item.addActionListener(listener); item.addActionListener(listener);
item.setActionCommand(entry.getAbsolutePath()); item.setActionCommand(entry.getAbsolutePath());
@ -589,7 +599,7 @@ public class Sketchbook {
} }
} }
return ifound; return ifound;
} /*return false;*/ }
/** /**

View File

@ -74,6 +74,9 @@ public class PdePreprocessor {
// stores number of built user-defined function prototypes // stores number of built user-defined function prototypes
public int prototypeCount = 0; public int prototypeCount = 0;
// stores number of included library headers written
public int headerCount = 0;
/** /**
* These may change in-between (if the prefs panel adds this option) * These may change in-between (if the prefs panel adds this option)
* so grab them here on construction. * so grab them here on construction.
@ -236,24 +239,22 @@ public class PdePreprocessor {
String returntype, functioname, parameterlist, prototype; String returntype, functioname, parameterlist, prototype;
java.util.LinkedList prototypes = new java.util.LinkedList(); java.util.LinkedList prototypes = new java.util.LinkedList();
//System.out.println("prototypes:"); //System.out.println("prototypes:");
//if (Preferences.get("build.extension").equals("cpp")) { while(matcher.contains(input, pattern)){
while(matcher.contains(input, pattern)){ result = matcher.getMatch();
result = matcher.getMatch(); //System.out.println(result);
//System.out.println(result); returntype = result.group(1).toString();
returntype = result.group(1).toString(); functioname = result.group(2).toString();
functioname = result.group(2).toString(); parameterlist = result.group(3).toString().replace('\n', ' ');
parameterlist = result.group(3).toString().replace('\n', ' '); prototype = returntype + " " + functioname + "(" + parameterlist + ");";
prototype = returntype + " " + functioname + "(" + parameterlist + ");"; if(0 == functioname.compareTo("setup")){
if(0 == functioname.compareTo("setup")){ continue;
continue;
}
if(0 == functioname.compareTo("loop")){
continue;
}
prototypes.add(prototype);
//System.out.println(prototype);
} }
//} if(0 == functioname.compareTo("loop")){
continue;
}
prototypes.add(prototype);
//System.out.println(prototype);
}
// store # of prototypes so that line number reporting can be adjusted // store # of prototypes so that line number reporting can be adjusted
prototypeCount = prototypes.size(); prototypeCount = prototypes.size();
@ -263,6 +264,7 @@ public class PdePreprocessor {
// through so that the line numbers when the compiler reports errors // through so that the line numbers when the compiler reports errors
// match those that will be highlighted in the PDE IDE // match those that will be highlighted in the PDE IDE
// //
//System.out.println(program);
WLexer lexer = new WLexer(programReader); WLexer lexer = new WLexer(programReader);
//lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken"); //lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken");
lexer.setTokenObjectClass("processing.app.preproc.CToken"); lexer.setTokenObjectClass("processing.app.preproc.CToken");
@ -329,7 +331,6 @@ public class PdePreprocessor {
// output the code // output the code
// //
WEmitter emitter = new WEmitter(lexer.getPreprocessorInfoChannel()); WEmitter emitter = new WEmitter(lexer.getPreprocessorInfoChannel());
//File streamFile = new File(buildPath, name + "." + Preferences.get("build.extension"));
File streamFile = new File(buildPath, name + ".cpp"); File streamFile = new File(buildPath, name + ".cpp");
PrintStream stream = new PrintStream(new FileOutputStream(streamFile)); PrintStream stream = new PrintStream(new FileOutputStream(streamFile));
@ -381,6 +382,16 @@ public class PdePreprocessor {
*/ */
void writeHeader(PrintStream out, String className, java.util.LinkedList prototypes) { void writeHeader(PrintStream out, String className, java.util.LinkedList prototypes) {
out.print("#include \"WProgram.h\"\n"); out.print("#include \"WProgram.h\"\n");
// print library headers
LibraryManager libraryManager = new LibraryManager();
String[] headerFiles = libraryManager.getHeaderFiles();
for(int i = 0; i < headerFiles.length; ++i){
out.print("#include \"" + headerFiles[i] + "\"\n");
}
// record number of header lines written for error line adjustment
headerCount = headerFiles.length;
// print user defined prototypes // print user defined prototypes
while(0 < prototypes.size()){ while(0 < prototypes.size()){

View File

@ -1647,7 +1647,7 @@ public class JEditTextArea extends JComponent
inputHandler.keyTyped(evt); inputHandler.keyTyped(evt);
break; break;
case KeyEvent.KEY_PRESSED: case KeyEvent.KEY_PRESSED:
if (!editorListener.keyPressed(evt)) { if ((editorListener != null) && !editorListener.keyPressed(evt)) {
inputHandler.keyPressed(evt); inputHandler.keyPressed(evt);
} }
break; break;

View File

@ -475,6 +475,42 @@ public class TextAreaPainter extends JComponent implements TabExpander
Token currentLineTokens; Token currentLineTokens;
Segment currentLine; Segment currentLine;
/**
* Accessor used by tools that want to hook in and grab the formatting.
*/
public int getCurrentLineIndex() {
return currentLineIndex;
}
/**
* Accessor used by tools that want to hook in and grab the formatting.
*/
public void setCurrentLineIndex(int what) {
currentLineIndex = what;
}
/**
* Accessor used by tools that want to hook in and grab the formatting.
*/
public Token getCurrentLineTokens() {
return currentLineTokens;
}
/**
* Accessor used by tools that want to hook in and grab the formatting.
*/
public void setCurrentLineTokens(Token tokens) {
currentLineTokens = tokens;
}
/**
* Accessor used by tools that want to hook in and grab the formatting.
*/
public Segment getCurrentLine() {
return currentLine;
}
// protected members // protected members
protected JEditTextArea textArea; protected JEditTextArea textArea;

156
app/tools/Archiver.java Executable file
View File

@ -0,0 +1,156 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Archiver - plugin tool for archiving sketches
Part of the Processing project - http://processing.org
Copyright (c) 2004-05 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.tools;
import processing.app.*;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
public class Archiver {
Editor editor;
// someday these will be settable
boolean useDate = true; //false;
int digits = 3;
NumberFormat numberFormat;
SimpleDateFormat dateFormat;
public Archiver(Editor editor) {
this.editor = editor;
numberFormat = NumberFormat.getInstance();
numberFormat.setGroupingUsed(false); // no commas
numberFormat.setMinimumIntegerDigits(digits);
dateFormat = new SimpleDateFormat("yyMMdd");
}
public void show() {
// first save the sketch so that things don't archive strangely
boolean success = false;
try {
success = editor.sketch.save();
} catch (Exception e) {
e.printStackTrace();
}
if (!success) {
Base.showWarning("Couldn't archive sketch",
"Archiving the sketch has been canceled because\n" +
"the sketch couldn't save properly.", null);
return;
}
File location = editor.sketch.folder;
String name = location.getName();
File parent = new File(location.getParent());
//System.out.println("loc " + location);
//System.out.println("par " + parent);
File newbie = null;
String namely = null;
int index = 0;
do {
if (useDate) {
String purty = dateFormat.format(new Date());
String stamp = purty + ((char) ('a' + index));
namely = name + "-" + stamp;
newbie = new File(parent, namely + ".zip");
} else {
String diggie = numberFormat.format(index + 1);
namely = name + "-" + diggie;
newbie = new File(parent, namely + ".zip");
}
index++;
} while (newbie.exists());
try {
//System.out.println(newbie);
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
// recursively fill the zip file
buildZip(location, name, zos);
// close up the jar file
zos.flush();
zos.close();
editor.message("Created archive " + newbie.getName() + ".");
} catch (IOException e) {
e.printStackTrace();
}
}
public void buildZip(File dir, String sofar,
ZipOutputStream zos) throws IOException {
String files[] = dir.list();
for (int i = 0; i < files.length; i++) {
if (files[i].equals(".") ||
files[i].equals("..")) continue;
File sub = new File(dir, files[i]);
String nowfar = (sofar == null) ?
files[i] : (sofar + "/" + files[i]);
if (sub.isDirectory()) {
// directories are empty entries and have / at the end
ZipEntry entry = new ZipEntry(nowfar + "/");
//System.out.println(entry);
zos.putNextEntry(entry);
zos.closeEntry();
buildZip(sub, nowfar, zos);
} else {
ZipEntry entry = new ZipEntry(nowfar);
entry.setTime(sub.lastModified());
zos.putNextEntry(entry);
zos.write(Base.grabFile(sub));
zos.closeEntry();
}
}
}
}
/*
int index = 0;
SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
String purty = formatter.format(new Date());
do {
newbieName = "sketch_" + purty + ((char) ('a' + index));
newbieDir = new File(newbieParentDir, newbieName);
index++;
} while (newbieDir.exists());
*/

File diff suppressed because it is too large Load Diff

120
app/tools/ExportFolder.java Executable file
View File

@ -0,0 +1,120 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
ExportFolder - tool to export all sketches within a certain folder
Part of the Processing project - http://processing.org
Copyright (c) 2005-06 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.tools;
import processing.app.*;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
import javax.swing.*;
public class ExportFolder {
Editor editor;
static JFileChooser fc;
public ExportFolder(Editor editor) {
this.editor = editor;
if (fc == null) {
fc = new JFileChooser();
fc.setSelectedFile(new File(Sketchbook.getSketchbookPath()));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
}
public void show() {
if (fc.showOpenDialog(new JDialog()) != JFileChooser.APPROVE_OPTION) {
return;
}
File folder = fc.getSelectedFile();
// export everything under this folder
Vector sketches = new Vector();
try {
addSketches(sketches, folder);
} catch (IOException e) {
e.printStackTrace();
}
boolean success = true;
int counter = 0;
try {
// iterate through the list
Enumeration en = sketches.elements();
while (en.hasMoreElements()) {
editor.message("Exporting sketch " + (++counter) +
" of " + sketches.size());
String path = (String) en.nextElement();
editor.handleOpen(path);
// success may not be that useful, usually an ex is thrown
success = editor.sketch.exportApplet(new Target(
System.getProperty("user.dir") + File.separator + "lib" +
File.separator + "targets", Preferences.get("build.target")));
if (!success) break;
//System.out.println("success was " + success);
}
} catch (Exception e) {
editor.error(e);
success = false;
//e.printStackTrace();
}
if (success) {
editor.message("Done exporting.");
} // else the error message will be visible
}
protected void addSketches(Vector sketches, File folder) throws IOException {
// skip .DS_Store files, etc
if (!folder.isDirectory()) return; // false;
String list[] = folder.list();
// if a bad folder or something like that, this might come back null
if (list == null) return; // false;
for (int i = 0; i < list.length; i++) {
if (list[i].charAt(0) == '.') continue;
File subfolder = new File(folder, list[i]);
File entry = new File(subfolder, list[i] + ".pde");
// if a .pde file of the same prefix as the folder exists..
if (entry.exists()) {
sketches.add(entry.getAbsolutePath());
} else if (subfolder.isDirectory()) { // only follow if a dir
addSketches(sketches, subfolder);
}
}
}
}

View File

@ -219,6 +219,10 @@
33AF61B30965C54B00B514A9 /* WTreeParser.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE520965BD110016AC38 /* WTreeParser.java */; }; 33AF61B30965C54B00B514A9 /* WTreeParser.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE520965BD110016AC38 /* WTreeParser.java */; };
33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE630965BD110016AC38 /* JEditTextArea.java */; }; 33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE630965BD110016AC38 /* JEditTextArea.java */; };
33AF61B50965C54B00B514A9 /* Base.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE240965BD100016AC38 /* Base.java */; }; 33AF61B50965C54B00B514A9 /* Base.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE240965BD100016AC38 /* Base.java */; };
33BEDDB109D6DC1300430D5B /* Library.java in Sources */ = {isa = PBXBuildFile; fileRef = 33BEDDAF09D6DC1300430D5B /* Library.java */; };
33BEDDB209D6DC1300430D5B /* LibraryManager.java in Sources */ = {isa = PBXBuildFile; fileRef = 33BEDDB009D6DC1300430D5B /* LibraryManager.java */; };
33BEDDD509D6E8D800430D5B /* Archiver.java in Sources */ = {isa = PBXBuildFile; fileRef = 33BEDDD309D6E8D800430D5B /* Archiver.java */; };
33BEDDD609D6E8D800430D5B /* ExportFolder.java in Sources */ = {isa = PBXBuildFile; fileRef = 33BEDDD409D6E8D800430D5B /* ExportFolder.java */; };
33CF03B209662CB700F2C9A9 /* arduino.icns in Resources */ = {isa = PBXBuildFile; fileRef = 33CF03B009662CA800F2C9A9 /* arduino.icns */; }; 33CF03B209662CB700F2C9A9 /* arduino.icns in Resources */ = {isa = PBXBuildFile; fileRef = 33CF03B009662CA800F2C9A9 /* arduino.icns */; };
33CF03CC09662DC000F2C9A9 /* mrj.jar in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33AF620C0965D67900B514A9 /* mrj.jar */; settings = {JAVA_ARCHIVE_SUBDIR = ../shared/lib; }; }; 33CF03CC09662DC000F2C9A9 /* mrj.jar in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33AF620C0965D67900B514A9 /* mrj.jar */; settings = {JAVA_ARCHIVE_SUBDIR = ../shared/lib; }; };
33CF03CD09662DC000F2C9A9 /* RXTXcomm.jar in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33AF620F0965D67A00B514A9 /* RXTXcomm.jar */; settings = {JAVA_ARCHIVE_SUBDIR = ../shared/lib; }; }; 33CF03CD09662DC000F2C9A9 /* RXTXcomm.jar in CopyFiles */ = {isa = PBXBuildFile; fileRef = 33AF620F0965D67A00B514A9 /* RXTXcomm.jar */; settings = {JAVA_ARCHIVE_SUBDIR = ../shared/lib; }; };
@ -371,6 +375,10 @@
33AF620D0965D67900B514A9 /* oro.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = oro.jar; sourceTree = "<group>"; }; 33AF620D0965D67900B514A9 /* oro.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = oro.jar; sourceTree = "<group>"; };
33AF620E0965D67A00B514A9 /* registry.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = registry.jar; sourceTree = "<group>"; }; 33AF620E0965D67A00B514A9 /* registry.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = registry.jar; sourceTree = "<group>"; };
33AF620F0965D67A00B514A9 /* RXTXcomm.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = RXTXcomm.jar; sourceTree = "<group>"; }; 33AF620F0965D67A00B514A9 /* RXTXcomm.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = RXTXcomm.jar; sourceTree = "<group>"; };
33BEDDAF09D6DC1300430D5B /* Library.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Library.java; sourceTree = "<group>"; };
33BEDDB009D6DC1300430D5B /* LibraryManager.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = LibraryManager.java; sourceTree = "<group>"; };
33BEDDD309D6E8D800430D5B /* Archiver.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = Archiver.java; sourceTree = "<group>"; };
33BEDDD409D6E8D800430D5B /* ExportFolder.java */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.java; path = ExportFolder.java; sourceTree = "<group>"; };
33CF03B009662CA800F2C9A9 /* arduino.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = arduino.icns; path = dist/arduino.icns; sourceTree = "<group>"; }; 33CF03B009662CA800F2C9A9 /* arduino.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = arduino.icns; path = dist/arduino.icns; sourceTree = "<group>"; };
33DD8FB6096AC8DA0013AF8F /* Arduino.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Arduino.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33DD8FB6096AC8DA0013AF8F /* Arduino.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Arduino.app; sourceTree = BUILT_PRODUCTS_DIR; };
33FF01DC0965BD160016AC38 /* examples.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = examples.zip; sourceTree = "<group>"; }; 33FF01DC0965BD160016AC38 /* examples.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = examples.zip; sourceTree = "<group>"; };
@ -738,6 +746,8 @@
33FFFE220965BD100016AC38 /* app */ = { 33FFFE220965BD100016AC38 /* app */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
33BEDDAF09D6DC1300430D5B /* Library.java */,
33BEDDB009D6DC1300430D5B /* LibraryManager.java */,
33FFFE240965BD100016AC38 /* Base.java */, 33FFFE240965BD100016AC38 /* Base.java */,
33FFFE260965BD100016AC38 /* Compiler.java */, 33FFFE260965BD100016AC38 /* Compiler.java */,
33FFFE270965BD100016AC38 /* Editor.java */, 33FFFE270965BD100016AC38 /* Editor.java */,
@ -847,6 +857,8 @@
33FFFE710965BD110016AC38 /* tools */ = { 33FFFE710965BD110016AC38 /* tools */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
33BEDDD309D6E8D800430D5B /* Archiver.java */,
33BEDDD409D6E8D800430D5B /* ExportFolder.java */,
33FFFE720965BD110016AC38 /* AutoFormat.java */, 33FFFE720965BD110016AC38 /* AutoFormat.java */,
); );
path = tools; path = tools;
@ -1126,6 +1138,10 @@
33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */, 33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */,
33AF61B50965C54B00B514A9 /* Base.java in Sources */, 33AF61B50965C54B00B514A9 /* Base.java in Sources */,
332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */, 332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */,
33BEDDB109D6DC1300430D5B /* Library.java in Sources */,
33BEDDB209D6DC1300430D5B /* LibraryManager.java in Sources */,
33BEDDD509D6E8D800430D5B /* Archiver.java in Sources */,
33BEDDD609D6E8D800430D5B /* ExportFolder.java in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -53,8 +53,13 @@ PWM now working on pin 11 (in addition to pins 9 and 10).
Slowed PWM frequency (on all three PWM pins) to 1KHz. Slowed PWM frequency (on all three PWM pins) to 1KHz.
Now give an error if compiled sketch is too big. Now give an error if compiled sketch is too big.
Fixed abs(), min(), max(), and constrain() macros. Fixed abs(), min(), max(), and constrain() macros.
Added menu items to the IDE to burn bootloader.
Now display binary sketch size on upload, and give error if too big.
Added C++ serial library.
Resynced with Processing/Wiring IDE code (improved auto-format, faster logging
to serial monitor console, other bug fixes)
0003 0003 - 2006.01.16
API Changes API Changes
Reversed the analog input pins to correspond to newer boards. This means Reversed the analog input pins to correspond to newer boards. This means