1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

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);
}
}
}
}