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.
*/
public class Base {
static final int VERSION = 1;
static final int VERSION = 3;
static final String VERSION_NAME = "0004 Alpha";
static public int platform;
// platform IDs for platform
// platform IDs for PApplet.platform
static final int WINDOWS = 1;
static final int MACOS9 = 2;
static final int MACOSX = 3;
static final int LINUX = 4;
static final int OTHER = 0;
// moved from PApplet
// in preperation of detaching the IDE from the
// Arduino core classes
/**
// 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;
/**
* "1.3" or "1.1" or whatever (just the first three chars)
*/
public static final String javaVersionName =
System.getProperty("java.version").substring(0,3);
/**
* Version of Java that's in use, whether 1.1 or 1.3 or whatever,
* stored as a float.
* <P>
* Note that because this is stored as a float, the values may
* not be <EM>exactly</EM> 1.3 or 1.4. Instead, make sure you're
* comparing against 1.3f or 1.4f, which will have the same amount
* of error (i.e. 1.40000001). This could just be a double, but
* since Processing only uses floats, it's safer to do this,
* because there's no good way to specify a double with the preproc.
*/
public static final float javaVersion =
new Float(javaVersionName).floatValue();
/**
* Current platform in use, one of the
* PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
*/
static public int platform;
/**
* Current platform in use.
* <P>
* Equivalent to System.getProperty("os.name"), just used internally.
*/
static public String platformName = System.getProperty("os.name");
static public String platformName =
System.getProperty("os.name");
static {
// 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[]) {
// make sure that this is running on java 1.4
@ -179,6 +195,9 @@ public class Base {
e.printStackTrace();
}
// use native popups so they don't look so crappy on osx
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
// build the editor object
editor = new Editor();
@ -214,7 +233,6 @@ public class Base {
* returns true if running on windows.
*/
static public boolean isWindows() {
return platform == WINDOWS;
}
@ -223,7 +241,6 @@ public class Base {
* true if running on linux.
*/
static public boolean isLinux() {
return platform == LINUX;
}
@ -363,26 +380,40 @@ public class Base {
}
static public File getBuildFolder() {
String buildPath = Preferences.get("build.path");
if (buildPath != null) return new File(buildPath);
static File buildFolder;
File folder = new File(getTempFolder(), "build");
if (!folder.exists()) folder.mkdirs();
return folder;
static public File getBuildFolder() {
if (buildFolder == null) {
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
* 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 {
File ignored = File.createTempFile("ignored", null);
String tempPath = ignored.getParent();
ignored.delete();
return new File(tempPath);
File folder = File.createTempFile(name, null);
//String tempPath = ignored.getParent();
//return new File(tempPath);
folder.delete();
folder.mkdirs();
return folder;
} catch (Exception e) {
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,
* builds a URL and passes it to openURL.
@ -858,7 +938,9 @@ public class Base {
static public void removeDir(File dir) {
if (dir.exists()) {
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)
*/
@ -954,7 +1076,7 @@ public class Base {
return null;
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// STRINGS

View File

@ -76,7 +76,9 @@ public class Compiler implements MessageConsumer {
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" :
userdir + "tools/avr/bin/avr-gcc"),
"-c", // compile, don't link
@ -86,11 +88,19 @@ public class Compiler implements MessageConsumer {
"-w", // surpress all warnings
"-mmcu=" + Preferences.get("build.mcu"),
"-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++" :
userdir + "tools/avr/bin/avr-g++"),
"-c", // compile, don't link
@ -101,46 +111,33 @@ public class Compiler implements MessageConsumer {
"-fno-exceptions",
"-mmcu=" + Preferences.get("build.mcu"),
"-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" :
userdir + "tools/avr/bin/avr-gcc"),
" ",
"-mmcu=" + Preferences.get("build.mcu"),
"-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[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-objcopy" :
userdir + "tools/avr/bin/avr-objcopy"),
@ -295,8 +292,8 @@ public class Compiler implements MessageConsumer {
Process process;
boolean compiling = true;
for(int i = 0; i < fileCount; i++) {
baseCommandCompiler[8] = sourceNames[i];
baseCommandCompiler[9] = "-o"+ objectNames[i];
baseCommandCompiler[baseCommandCompiler.length - 2] = sourceNames[i];
baseCommandCompiler[baseCommandCompiler.length - 1] = "-o"+ objectNames[i];
//System.arraycopy(baseCommandCompiler.length
//for(int j = 0; j < baseCommandCompiler.length; j++) {
// System.out.println(baseCommandCompiler[j]);
@ -325,8 +322,8 @@ public class Compiler implements MessageConsumer {
}
for(int i = 0; i < fileCountCPP; i++) {
baseCommandCompilerCPP[9] = sourceNamesCPP[i];
baseCommandCompilerCPP[10] = "-o"+ objectNamesCPP[i];
baseCommandCompilerCPP[baseCommandCompilerCPP.length - 2] = sourceNamesCPP[i];
baseCommandCompilerCPP[baseCommandCompilerCPP.length - 1] = "-o"+ objectNamesCPP[i];
//for(int j = 0; j < baseCommandCompilerCPP.length; 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_WIDTH = 27; //Preferences.GRID_SIZE;
static final int BUTTON_HEIGHT = 32; //Preferences.GRID_SIZE;
static final int BUTTON_GAP = 15; //BUTTON_WIDTH / 2;
/// height, width of the toolbar buttons
static final int BUTTON_WIDTH = 27;
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 STOP = 1;
@ -59,7 +61,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
static final int ACTIVE = 2;
Editor editor;
boolean disableRun;
//boolean disableRun;
//Label status;
Image offscreen;
@ -72,7 +74,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
Image rollover[];
Image active[];
int currentRollover;
int currentSelection;
//int currentSelection;
JPopupMenu popup;
@ -112,7 +114,7 @@ public class EditorButtons extends JComponent implements MouseInputListener {
// see EditorStatus.java for details.
//bgcolor = Preferences.getColor("buttons.bgcolor");
bgcolor = new Color(0x04, 0x4F, 0x6F);
status = "";
statusFont = Preferences.getFont("buttons.status.font");
@ -234,10 +236,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
if (sel == -1) return;
if (state[sel] != ACTIVE) {
if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
setState(sel, ROLLOVER, true);
currentRollover = sel;
}
//if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
setState(sel, ROLLOVER, true);
currentRollover = sel;
//}
}
}
@ -284,6 +286,10 @@ public class EditorButtons extends JComponent implements MouseInputListener {
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) {
setState(OPEN, INACTIVE, true);
}
@ -295,27 +301,78 @@ public class EditorButtons extends JComponent implements MouseInputListener {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
final int x = e.getX();
final int y = e.getY();
int sel = findSelection(x, y);
///if (sel == -1) return false;
if (sel == -1) return;
currentRollover = -1;
currentSelection = sel;
if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
setState(sel, ACTIVE, true);
}
//int currentSelection = sel;
//if (!(disableRun && ((sel == RUN) || (sel == STOP)))) {
// 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) {
//popup = new JPopupMenu();
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);
}
//editor.sketchbook.rebuildPopup(popup);
popup.show(this, x, y);
}
//activate(OPEN);
//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) {
/*
switch (currentSelection) {
case RUN:
if (!disableRun) {
@ -344,14 +402,47 @@ public class EditorButtons extends JComponent implements MouseInputListener {
case SERIAL: editor.handleSerial(); break;
}
currentSelection = -1;
*/
}
public void disableRun(boolean what) {
disableRun = what;
//public void disableRun(boolean what) {
//disableRun = what;
//}
/*
public void run() {
if (inactive == null) return;
clear();
setState(RUN, ACTIVE, true);
}
*/
public void running(boolean yesno) {
setState(RUN, yesno ? ACTIVE : INACTIVE, true);
}
/**
* 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) {
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) {
//status.setText(msg + " "); // don't mind the hack
status = msg;

View File

@ -28,7 +28,7 @@ import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
/**
* Message console that sits below the editing area.
@ -41,7 +41,7 @@ public class EditorConsole extends JScrollPane {
Editor editor;
JTextPane consoleTextPane;
StyledDocument consoleDoc;
BufferedStyledDocument consoleDoc;
MutableAttributeSet stdStyle;
MutableAttributeSet errStyle;
@ -51,6 +51,10 @@ public class EditorConsole extends JScrollPane {
//int maxCharCount;
int maxLineCount;
static File errFile;
static File outFile;
static File tempFolder;
static PrintStream systemOut;
static PrintStream systemErr;
@ -66,9 +70,9 @@ public class EditorConsole extends JScrollPane {
maxLineCount = Preferences.getInteger("console.length");
consoleTextPane = new JTextPane();
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
consoleTextPane = new JTextPane(consoleDoc);
consoleTextPane.setEditable(false);
consoleDoc = consoleTextPane.getStyledDocument();
// necessary?
MutableAttributeSet standard = new SimpleAttributeSet();
@ -115,15 +119,20 @@ public class EditorConsole extends JScrollPane {
systemOut = System.out;
systemErr = System.err;
tempFolder = Base.createTempFolder("console");
try {
String outFileName = Preferences.get("console.output.file");
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");
if (errFileName != null) {
stderrFile = new FileOutputStream(outFileName);
errFile = new File(tempFolder, errFileName);
stderrFile = new FileOutputStream(errFile);
//errFile.deleteOnExit();
}
} catch (IOException e) {
Base.showWarning("Console Error",
@ -151,6 +160,52 @@ public class EditorConsole extends JScrollPane {
if (Base.isMacOS()) {
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) {
if (err) {
systemErr.print(what);
//systemErr.print("CE" + what);
} else {
systemOut.print(what);
//systemOut.print("CO" + what);
}
if (advance) {
@ -204,66 +257,13 @@ public class EditorConsole extends JScrollPane {
* and eventually leads to EditorConsole.appendText(), which directly
* updates the Swing text components, causing deadlock.
* <P>
* A quick hack from Francis Li (who found this to be a problem)
* wraps the contents of appendText() into a Runnable and uses
* 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.
* Updates are buffered to the console and displayed at regular
* intervals on Swing's event-dispatching thread. (patch by David Mellis)
*/
synchronized private void appendText(String txt, boolean e) {
final String text = txt;
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?
}
}
});
consoleDoc.appendString(txt, e ? errStyle : stdStyle);
}
public void clear() {
try {
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;
if (sketch != null) {
for (int i = 0; i < sketch.hiddenCount; i++) {
item = new JMenuItem(sketch.hidden[i].name);
item.setActionCommand(sketch.hidden[i].name);
item = new JMenuItem(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);
unhide.add(item);
}
@ -360,7 +362,8 @@ public class EditorHeader extends JComponent {
}
};
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);
menu.add(item);
}

View File

@ -35,13 +35,25 @@ import javax.swing.event.*;
/**
* 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 {
Editor editor;
JEditTextArea textarea;
boolean externalEditor;
boolean expandTabs;
boolean tabsExpand;
boolean tabsIndent;
int tabSize;
String tabString;
boolean autoIndent;
@ -61,8 +73,9 @@ public class EditorListener {
public void applyPreferences() {
expandTabs = Preferences.getBoolean("editor.tabs.expand");
int tabSize = Preferences.getInteger("editor.tabs.size");
tabsExpand = Preferences.getBoolean("editor.tabs.expand");
//tabsIndent = Preferences.getBoolean("editor.tabs.indent");
tabSize = Preferences.getInteger("editor.tabs.size");
tabString = Editor.EMPTY.substring(0, tabSize);
autoIndent = Preferences.getBoolean("editor.indent");
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) {
// don't do things if the textarea isn't editable
if (externalEditor) return false;
@ -92,21 +111,148 @@ public class EditorListener {
}
// 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) ||
(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) {
case 9: // expand tabs
if (expandTabs) {
//tc.replaceSelection(tabString);
if (tabsExpand) {
textarea.setSelectedText(tabString);
event.consume();
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;
@ -115,13 +261,18 @@ public class EditorListener {
if (autoIndent) {
char contents[] = textarea.getText().toCharArray();
// this is the position of the caret, if the textarea
// only used a single kind of line ending
// this is the previous character
// (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;
// 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,
// and count how many weirdo windows line endings there are,
// which would be throwing off the caret position number
/*
int offset = 0;
int realIndex = origIndex;
for (int i = 0; i < realIndex-1; i++) {
@ -130,38 +281,140 @@ public class EditorListener {
realIndex++;
}
}
// back up until \r \r\n or \n.. @#($* cross platform
//System.out.println(origIndex + " offset = " + offset);
origIndex += offset; // ARGH!#(* WINDOWS#@($*
*/
int index = origIndex;
int spaceCount = 0;
boolean finished = false;
while ((index != -1) && (!finished)) {
if ((contents[index] == 10) ||
(contents[index] == 13)) {
finished = true;
index++; // maybe ?
} else {
index--; // new
int spaceCount = calcSpaceCount(origIndex, contents);
//int origCount = spaceCount;
// now before inserting this many spaces, walk forward from
// the caret position, so that the number of spaces aren't
// just being duplicated again
int index = origIndex + 1;
int extraCount = 0;
while ((index < contents.length) &&
(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) &&
(contents[index++] == ' ')) {
spaceCount++;
}
*/
// seems that \r is being inserted anyway
// so no need to insert the platform's line separator
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
//tc.replaceSelection(insertion);
textarea.setSelectedText(insertion);
// microsoft vm version:
//tc.setCaretPosition(oldCarrot + insertion.length() - 1);
// sun vm version:
// tc.setCaretPosition(oldCarrot + insertion.length());
// number of spaces found on this line
//int newSpaceCount = Math.max(0, spaceCount - tabSize);
// number of spaces on this current line
//int spaceCount = calcSpaces(caretIndex, contents);
//System.out.println("spaces is " + spaceCount);
//String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
//int differential = newSpaceCount - spaceCount;
//System.out.println("diff is " + differential);
//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();
return true;
}
@ -169,4 +422,143 @@ public class EditorListener {
}
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) {
// answer was in response to "save changes?"
unprompt();
editor.handleSave();
editor.handleSave(true);
editor.checkModified2();
} 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
implements ActionListener, KeyListener {
public class FindReplace extends JFrame implements ActionListener {
static final int BIG = 13;
static final int SMALL = 6;
@ -41,16 +52,17 @@ public class FindReplace extends JFrame
JTextField findField;
JTextField replaceField;
static String findString;
static String replaceString;
JButton replaceButton;
JButton replaceAllButton;
JButton findButton;
JCheckBox ignoreCaseBox;
boolean ignoreCase;
KeyStroke windowClose;
static boolean ignoreCase = true;
/// true when there's something selected in the editor
boolean found;
@ -74,6 +86,27 @@ public class FindReplace extends JFrame
pain.add(replaceField = new JTextField(20));
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
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,
d1.width, d1.height);
ignoreCase = true;
//ignoreCase = true;
ignoreCaseBox = new JCheckBox("Ignore Case");
ignoreCaseBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@ -110,12 +143,8 @@ public class FindReplace extends JFrame
}
pain.add(buttons);
// 0069 TEMPORARILY DISABLED!
//replaceAllButton.setEnabled(false);
// to fix ugliness.. normally macosx java 1.3 puts an
// ugly white border around this object, so turn it off.
//if (Base.platform == Base.MACOSX) {
if (Base.isMacOS()) {
buttons.setBorder(null);
}
@ -146,7 +175,7 @@ public class FindReplace extends JFrame
replaceButton.setEnabled(false);
// so that typing will go straight to this field
findField.requestFocus();
//findField.requestFocus();
// make the find button the blinky default
getRootPane().setDefaultButton(findButton);
@ -161,48 +190,62 @@ public class FindReplace extends JFrame
(screen.height - high) / 2, wide, high);
// add key listener to trap esc and ctrl/cmd-w
findField.addKeyListener(this);
replaceField.addKeyListener(this);
addKeyListener(this);
/*
KeyListener listener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (Base.isCloseWindowEvent(e)) hide();
}
};
findField.addKeyListener(listener);
replaceField.addKeyListener(listener);
addKeyListener(listener);
*/
ActionListener disposer = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//hide();
handleClose();
}
};
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
handleClose();
}
});
Base.registerWindowCloseKeys(getRootPane(), disposer);
/*
// hack to to get first field to focus properly on osx
// though this still doesn't seem to work
addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
//System.out.println("activating");
findField.requestFocus();
findField.selectAll();
//boolean ok = findField.requestFocusInWindow();
//System.out.println("got " + ok);
//findField.selectAll();
}
});
*/
}
/**
* Handle window closing commands for ctrl/cmd-W or hitting ESC.
*/
public void keyPressed(KeyEvent e) {
if (windowClose == null) {
int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
windowClose = KeyStroke.getKeyStroke('W', modifiers);
}
if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) ||
(KeyStroke.getKeyStrokeForEvent(e).equals(windowClose))) {
hide();
//} else {
//System.out.println("event " + e);
}
public void handleClose() {
//System.out.println("handling close now");
findString = findField.getText();
replaceString = replaceField.getText();
// this object should eventually become dereferenced
hide();
}
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
/*
public void show() {
findField.requestFocusInWindow();
super.show();
findField.selectAll();
findField.requestFocus();
//findField.selectAll();
//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() {
if (!found) return; // don't replace if nothing found
@ -284,15 +328,17 @@ public class FindReplace extends JFrame
editor.textarea.setSelectedText(replaceField.getText());
//editor.setSketchModified(true);
//editor.sketch.setCurrentModified(true);
editor.sketch.setModified();
editor.sketch.setModified(true);
// don't allow a double replace
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() {
// move to the beginning
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.undo.*;
//import processing.core.PApplet;
/**
@ -50,7 +51,7 @@ import javax.swing.undo.*;
* properties files are iso8859-1, which is highly likely to
* be a problem when trying to save sketch folders and locations.
*/
public class Preferences extends JComponent {
public class Preferences {
// what to call the feller
@ -72,16 +73,32 @@ public class Preferences extends JComponent {
static final String PROMPT_OK = "OK";
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
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_BETWEEN = 10;
@ -89,14 +106,12 @@ public class Preferences extends JComponent {
// gui elements
//JFrame frame;
JDialog frame;
JDialog dialog;
int wide, high;
JTextField sketchbookLocationField;
JCheckBox sketchPromptBox;
JCheckBox sketchCleanBox;
//JCheckBox exportLibraryBox;
JCheckBox externalEditorBox;
JCheckBox checkUpdatesBox;
@ -111,7 +126,6 @@ public class Preferences extends JComponent {
static Hashtable table = new Hashtable();;
static File preferencesFile;
//boolean firstTime; // first time this feller has been run
static public void init() {
@ -152,9 +166,6 @@ public class Preferences extends JComponent {
// 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);
if (!preferencesFile.exists()) {
@ -181,14 +192,12 @@ public class Preferences extends JComponent {
public Preferences() {
// setup frame for the prefs
// setup dialog for the prefs
//frame = new JFrame("Preferences");
frame = new JDialog(editor, "Preferences", true);
//frame.setResizable(false);
dialog = new JDialog(editor, "Preferences", true);
dialog.setResizable(false);
//Container pain = this;
Container pain = frame.getContentPane();
Container pain = dialog.getContentPane();
pain.setLayout(null);
int top = GUI_BIG;
@ -284,20 +293,6 @@ public class Preferences extends JComponent {
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
externalEditorBox = new JCheckBox("Use external editor");
@ -320,21 +315,6 @@ public class Preferences extends JComponent {
// 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");
pain.add(label);
@ -362,9 +342,6 @@ public class Preferences extends JComponent {
// [ 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.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@ -376,9 +353,6 @@ public class Preferences extends JComponent {
d2 = button.getPreferredSize();
BUTTON_HEIGHT = d2.height;
// smoosh up to the line before
//top -= BUTTON_HEIGHT;
h = right - (BUTTON_WIDTH + GUI_SMALL + BUTTON_WIDTH);
button.setBounds(h, top, BUTTON_WIDTH, BUTTON_HEIGHT);
h += BUTTON_WIDTH + GUI_SMALL;
@ -398,32 +372,39 @@ public class Preferences extends JComponent {
// finish up
wide = right + GUI_BIG;
high = top + GUI_SMALL; //GUI_BIG;
setSize(wide, high);
high = top + GUI_SMALL;
//setSize(wide, high);
// closing the window is same as hitting cancel button
frame.addWindowListener(new WindowAdapter() {
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
disposeFrame();
}
});
Container content = frame.getContentPane();
content.setLayout(new BorderLayout());
content.add(this, BorderLayout.CENTER);
frame.pack();
ActionListener disposer = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
disposeFrame();
}
};
Base.registerWindowCloseKeys(dialog.getRootPane(), disposer);
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screen.width - wide) / 2,
dialog.setLocation((screen.width - wide) / 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.
addKeyListener(new KeyAdapter() {
pain.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
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() {
return new Dimension(wide, high);
}
@ -447,7 +448,7 @@ public class Preferences extends JComponent {
* Close the window after an OK or Cancel.
*/
public void disposeFrame() {
frame.dispose();
dialog.dispose();
}
@ -487,7 +488,7 @@ public class Preferences extends JComponent {
externalEditorBox.setSelected(getBoolean("editor.external"));
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 -*- */
/*
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) 2001-04 Massachusetts Institute of Technology
@ -19,8 +19,6 @@
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
$Id$
*/
package processing.app;
@ -67,7 +65,12 @@ public class Sketch {
public File codeFolder;
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;
int codeCount;
@ -104,6 +107,8 @@ public class Sketch {
name = mainFilename.substring(0, mainFilename.length() - 4);
} else if (mainFilename.endsWith(".c")) {
name = mainFilename.substring(0, mainFilename.length() - 2);
} else if (mainFilename.endsWith(".h")) {
name = mainFilename.substring(0, mainFilename.length() - 2);
} else if (mainFilename.endsWith(".cpp")) {
name = mainFilename.substring(0, mainFilename.length() - 4);
}
@ -157,9 +162,11 @@ public class Sketch {
for (int i = 0; i < list.length; i++) {
if (list[i].endsWith(".pde")) 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(".pde.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++;
}
@ -180,13 +187,19 @@ public class Sketch {
code[codeCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 2),
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")) {
code[codeCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 4),
new File(folder, list[i]),
JAVA);
CPP);
} else if (list[i].endsWith(".pde.x")) {
hidden[hiddenCounter++] =
@ -198,12 +211,17 @@ public class Sketch {
hidden[hiddenCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 4),
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")) {
hidden[hiddenCounter++] =
new SketchCode(list[i].substring(0, list[i].length() - 6),
new File(folder, list[i]),
JAVA);
CPP);
}
}
@ -314,8 +332,7 @@ public class Sketch {
renamingCode = true;
String prompt = (current == code[0]) ?
"New name for sketch:" : "New name for file:";
String oldName =
(current.flavor == PDE) ? current.name : current.name + ".cpp";
String oldName = current.name + flavorExtensionsShown[current.flavor];
editor.status.edit(prompt, oldName);
}
@ -348,6 +365,7 @@ public class Sketch {
}
if (newName.trim().equals(".c") ||
newName.trim().equals(".h") ||
newName.trim().equals(".pde") ||
newName.trim().equals(".cpp")) {
return;
@ -363,23 +381,28 @@ public class Sketch {
newName = newName.substring(0, newName.length() - 4);
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
if (renamingCode && (code[0] == current)) {
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" +
"\"real\" programming environment)", null);
return;
}
newFilename = newName;
if(newName.endsWith(".c"))
if(newName.endsWith(".c")) {
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);
newFlavor = JAVA;
newFlavor = CPP;
}
} else {
newFilename = newName + ".pde";
newFlavor = PDE;
@ -538,7 +561,7 @@ public class Sketch {
sortCode();
// set the new guy as current
setCurrent(newName);
setCurrent(newName + flavorExtensionsShown[newFlavor]);
// update the tabs
//editor.header.repaint();
@ -572,7 +595,8 @@ public class Sketch {
Object[] options = { "OK", "Cancel" };
String prompt = (current == code[0]) ?
"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,
prompt,
"Delete",
@ -684,9 +708,14 @@ public class Sketch {
public void unhideCode(String what) {
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++) {
if (hidden[i].name.equals(what)) {
if (hidden[i].name.equals(name) &&
Sketch.flavorExtensionsShown[hidden[i].flavor].equals(extension)) {
//unhideIndex = i;
unhideCode = hidden[i];
@ -730,8 +759,8 @@ public class Sketch {
/**
* Sets the modified value for the code in the frontmost tab.
*/
public void setModified() {
current.modified = true;
public void setModified(boolean state) {
current.modified = state;
calcModified();
}
@ -996,6 +1025,26 @@ public class Sketch {
// it move instead of copy, they can do it by hand
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;
boolean addingCode = false;
@ -1012,6 +1061,7 @@ public class Sketch {
} else if (filename.toLowerCase().endsWith(".pde") ||
filename.toLowerCase().endsWith(".c") ||
filename.toLowerCase().endsWith(".h") ||
filename.toLowerCase().endsWith(".cpp")) {
destFile = new File(this.folder, filename);
addingCode = true;
@ -1028,7 +1078,7 @@ public class Sketch {
"This file has already been copied to the\n" +
"location where you're trying to add it.\n" +
"I ain't not doin nuthin'.", null);
return;
return false;
}
// in case the user is "adding" the code in an attempt
@ -1036,10 +1086,12 @@ public class Sketch {
if (!sourceFile.equals(destFile)) {
try {
Base.copyFile(sourceFile, destFile);
} catch (IOException e) {
Base.showWarning("Error adding file",
"Could not add '" + filename +
"' to the sketch.", e);
return false;
}
}
@ -1050,9 +1102,15 @@ public class Sketch {
if (newName.toLowerCase().endsWith(".pde")) {
newName = newName.substring(0, newName.length() - 4);
newFlavor = PDE;
} else {
} else if (newName.toLowerCase().endsWith(".c")) {
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
@ -1062,6 +1120,7 @@ public class Sketch {
setCurrent(newName);
editor.header.repaint();
}
return true;
}
@ -1145,8 +1204,15 @@ public class Sketch {
* based on a name (used by codeNew and codeRename).
*/
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++) {
if (findName.equals(code[i].name)) {
if (name.equals(code[i].name) &&
Sketch.flavorExtensionsShown[code[i].flavor].equals(extension)) {
setCurrent(i);
return;
}
@ -1264,6 +1330,20 @@ public class Sketch {
*/
protected String build(Target target, String buildPath, String suggestedClassName)
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
ensureExistence();
@ -1316,7 +1396,7 @@ public class Sketch {
// check to see if multiple files that include a .java file
externalRuntime = false;
for (int i = 0; i < codeCount; i++) {
if (code[i].flavor == JAVA) {
if (code[i].flavor == C || code[i].flavor == CPP) {
externalRuntime = true;
break;
}
@ -1382,7 +1462,6 @@ public class Sketch {
//System.out.println();
} else {
//code[0].preprocName = className + "." + Preferences.get("build.extension");
code[0].preprocName = className + ".cpp";
}
@ -1408,6 +1487,7 @@ public class Sketch {
}
errorLine -= code[errorFile].preprocOffset;
errorLine -= preprocessor.prototypeCount;
errorLine -= preprocessor.headerCount;
throw new RunnerException(re.getMessage(), errorFile,
errorLine, re.getColumn());
@ -1449,6 +1529,7 @@ public class Sketch {
}
errorLine -= code[errorFile].preprocOffset;
errorLine -= preprocessor.prototypeCount;
errorLine -= preprocessor.headerCount;
throw new RunnerException(tsre.getMessage(),
errorFile, errorLine, errorColumn);
@ -1507,13 +1588,12 @@ public class Sketch {
// 3. then loop over the code[] and save each .java file
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
// just write the the contents of 'program' to a .java file
// into the build directory. uses byte stream and reader/writer
// shtuff so that unicode bunk is properly handled
//String filename = code[i].name + "." + Preferences.get("build.extension");
String filename = code[i].name + ".cpp";
String filename = code[i].name + flavorExtensionsReal[code[i].flavor];
try {
Base.saveFile(code[i].program, new File(buildPath, filename));
} catch (IOException e) {
@ -1538,7 +1618,7 @@ public class Sketch {
} catch (RunnerException re) {
throw new RunnerException(re.getMessage(),
re.file,
re.line - preprocessor.prototypeCount,
re.line - preprocessor.prototypeCount - preprocessor.headerCount,
re.column);
} catch (Exception ex) {
// TODO better method for handling this?

View File

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

View File

@ -74,6 +74,9 @@ public class PdePreprocessor {
// stores number of built user-defined function prototypes
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)
* so grab them here on construction.
@ -236,24 +239,22 @@ public class PdePreprocessor {
String returntype, functioname, parameterlist, prototype;
java.util.LinkedList prototypes = new java.util.LinkedList();
//System.out.println("prototypes:");
//if (Preferences.get("build.extension").equals("cpp")) {
while(matcher.contains(input, pattern)){
result = matcher.getMatch();
//System.out.println(result);
returntype = result.group(1).toString();
functioname = result.group(2).toString();
parameterlist = result.group(3).toString().replace('\n', ' ');
prototype = returntype + " " + functioname + "(" + parameterlist + ");";
if(0 == functioname.compareTo("setup")){
continue;
}
if(0 == functioname.compareTo("loop")){
continue;
}
prototypes.add(prototype);
//System.out.println(prototype);
while(matcher.contains(input, pattern)){
result = matcher.getMatch();
//System.out.println(result);
returntype = result.group(1).toString();
functioname = result.group(2).toString();
parameterlist = result.group(3).toString().replace('\n', ' ');
prototype = returntype + " " + functioname + "(" + parameterlist + ");";
if(0 == functioname.compareTo("setup")){
continue;
}
//}
if(0 == functioname.compareTo("loop")){
continue;
}
prototypes.add(prototype);
//System.out.println(prototype);
}
// store # of prototypes so that line number reporting can be adjusted
prototypeCount = prototypes.size();
@ -263,6 +264,7 @@ public class PdePreprocessor {
// through so that the line numbers when the compiler reports errors
// match those that will be highlighted in the PDE IDE
//
//System.out.println(program);
WLexer lexer = new WLexer(programReader);
//lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken");
lexer.setTokenObjectClass("processing.app.preproc.CToken");
@ -329,7 +331,6 @@ public class PdePreprocessor {
// output the code
//
WEmitter emitter = new WEmitter(lexer.getPreprocessorInfoChannel());
//File streamFile = new File(buildPath, name + "." + Preferences.get("build.extension"));
File streamFile = new File(buildPath, name + ".cpp");
PrintStream stream = new PrintStream(new FileOutputStream(streamFile));
@ -381,6 +382,16 @@ public class PdePreprocessor {
*/
void writeHeader(PrintStream out, String className, java.util.LinkedList prototypes) {
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
while(0 < prototypes.size()){

View File

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

View File

@ -475,6 +475,42 @@ public class TextAreaPainter extends JComponent implements TabExpander
Token currentLineTokens;
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 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 */; };
33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */ = {isa = PBXBuildFile; fileRef = 33FFFE630965BD110016AC38 /* JEditTextArea.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 */; };
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; }; };
@ -371,6 +375,10 @@
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>"; };
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>"; };
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>"; };
@ -738,6 +746,8 @@
33FFFE220965BD100016AC38 /* app */ = {
isa = PBXGroup;
children = (
33BEDDAF09D6DC1300430D5B /* Library.java */,
33BEDDB009D6DC1300430D5B /* LibraryManager.java */,
33FFFE240965BD100016AC38 /* Base.java */,
33FFFE260965BD100016AC38 /* Compiler.java */,
33FFFE270965BD100016AC38 /* Editor.java */,
@ -847,6 +857,8 @@
33FFFE710965BD110016AC38 /* tools */ = {
isa = PBXGroup;
children = (
33BEDDD309D6E8D800430D5B /* Archiver.java */,
33BEDDD409D6E8D800430D5B /* ExportFolder.java */,
33FFFE720965BD110016AC38 /* AutoFormat.java */,
);
path = tools;
@ -1126,6 +1138,10 @@
33AF61B40965C54B00B514A9 /* JEditTextArea.java in Sources */,
33AF61B50965C54B00B514A9 /* Base.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;
};

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.
Now give an error if compiled sketch is too big.
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
Reversed the analog input pins to correspond to newer boards. This means