1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-08-07 00:04:36 +03:00

Merging r327:r331 of the branches/processing-sync into the trunk. This adds the Processing core, and some new features including printing, copy for discourse, better auto-format, improved keyboard shortcuts, etc.

This commit is contained in:
David A. Mellis
2007-09-25 14:04:01 +00:00
parent 413b439974
commit 616d65d32a
40 changed files with 31946 additions and 779 deletions

View File

@@ -42,6 +42,7 @@ import javax.swing.undo.*;
import com.apple.mrj.*;
import com.ice.jni.registry.*;
import processing.core.*;
/**
@@ -52,21 +53,8 @@ import com.ice.jni.registry.*;
* files and images, etc) that comes from that.
*/
public class Base {
static final int VERSION = 3;
static final int VERSION = 10;
static final String VERSION_NAME = "0010 Alpha";
// platform IDs for PApplet.platform
static final int WINDOWS = 1;
static final int MACOS9 = 2;
static final int MACOSX = 3;
static final int LINUX = 4;
static final int OTHER = 0;
// used by split, all the standard whitespace chars
// (uncludes unicode nbsp, that little bostage)
static final String WHITESPACE = " \t\n\r\f\u00A0";
/**
* Path of filename opened on the command line,
@@ -76,79 +64,18 @@ public class Base {
Editor editor;
/**
* "1.3" or "1.1" or whatever (just the first three chars)
*/
public static final String javaVersionName =
System.getProperty("java.version").substring(0,3);
/**
* Version of Java that's in use, whether 1.1 or 1.3 or whatever,
* stored as a float.
* <P>
* Note that because this is stored as a float, the values may
* not be <EM>exactly</EM> 1.3 or 1.4. Instead, make sure you're
* comparing against 1.3f or 1.4f, which will have the same amount
* of error (i.e. 1.40000001). This could just be a double, but
* since Processing only uses floats, it's safer to do this,
* because there's no good way to specify a double with the preproc.
*/
public static final float javaVersion =
new Float(javaVersionName).floatValue();
/**
* Current platform in use, one of the
* PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
*/
static public int platform;
/**
* Current platform in use.
* <P>
* Equivalent to System.getProperty("os.name"), just used internally.
*/
static public String platformName =
System.getProperty("os.name");
static {
// figure out which operating system
// this has to be first, since editor needs to know
if (platformName.toLowerCase().indexOf("mac") != -1) {
// can only check this property if running on a mac
// on a pc it throws a security exception and kills the applet
// (but on the mac it does just fine)
if (System.getProperty("mrj.version") != null) { // running on a mac
platform = (platformName.equals("Mac OS X")) ?
MACOSX : MACOS9;
}
} else {
String osname = System.getProperty("os.name");
if (osname.indexOf("Windows") != -1) {
platform = WINDOWS;
} else if (osname.equals("Linux")) { // true for the ibm vm
platform = LINUX;
} else {
platform = OTHER;
}
}
}
static public void main(String args[]) {
// make sure that this is running on java 1.4
//if (PApplet.javaVersion < 1.4f) {
if (PApplet.javaVersion < 1.4f) {
//System.err.println("no way man");
// Base.showError("Need to install Java 1.4",
// "This version of Arduino requires \n" +
// "Java 1.4 or later to run properly.\n" +
// "Please visit java.com to upgrade.", null);
// }
Base.showError("Need to install Java 1.4",
"This version of Processing requires \n" +
"Java 1.4 or later to run properly.\n" +
"Please visit java.com to upgrade.", null);
}
// grab any opened file from the command line
@@ -183,14 +110,34 @@ public class Base {
// set the look and feel before opening the window
try {
if (Base.isLinux()) {
// linux is by default (motif?) even uglier than metal
// actually, i'm using native menus, so they're ugly and
// motif-looking. ick. need to fix this.
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
if (Base.isMacOS()) {
// Use the Quaqua L & F on OS X to make JFileChooser less awful
UIManager.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
// undo quaqua trying to fix the margins, since we've already
// hacked that in, bit by bit, over the years
UIManager.put("Component.visualMargin", new Insets(1, 1, 1, 1));
} else if (Base.isLinux()) {
// Linux is by default even uglier than metal (Motif?).
// Actually, i'm using native menus, so they're even uglier
// and Motif-looking (Lesstif?). Ick. Need to fix this.
//String lfname = UIManager.getCrossPlatformLookAndFeelClassName();
//UIManager.setLookAndFeel(lfname);
// For 0120, trying out the gtk+ look and feel as the default.
// This is available in Java 1.4.2 and later, and it can't possibly
// be any worse than Metal. (Ocean might also work, but that's for
// Java 1.5, and we aren't going there yet)
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} else {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
//} catch (ClassNotFoundException cnfe) {
// just default to the native look and feel for this platform
// i.e. appears that some linux systems don't have the gtk l&f
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
@@ -228,7 +175,7 @@ public class Base {
* specifically a Mac OS X machine because it doesn't un on OS 9 anymore.
*/
static public boolean isMacOS() {
return platform == MACOSX;
return PApplet.platform == PConstants.MACOSX;
}
@@ -236,7 +183,7 @@ public class Base {
* returns true if running on windows.
*/
static public boolean isWindows() {
return platform == WINDOWS;
return PApplet.platform == PConstants.WINDOWS;
}
@@ -244,7 +191,7 @@ public class Base {
* true if running on linux.
*/
static public boolean isLinux() {
return platform == LINUX;
return PApplet.platform == PConstants.LINUX;
}
@@ -472,8 +419,9 @@ public class Base {
sketchbookFolder = new File(documentsFolder, "Arduino");
} catch (Exception e) {
showError("sketch folder problem",
"Could not locate default sketch folder location.", e);
//showError("Could not find folder",
// "Could not locate the Documents folder.", e);
sketchbookFolder = promptSketchbookLocation();
}
} else if (isWindows()) {
@@ -502,11 +450,15 @@ public class Base {
sketchbookFolder = new File(personalPath, "Arduino");
} catch (Exception e) {
showError("Problem getting documents folder",
"Error getting the Arduino sketchbook folder.", e);
//showError("Problem getting folder",
// "Could not locate the Documents folder.", e);
sketchbookFolder = promptSketchbookLocation();
}
} else {
sketchbookFolder = promptSketchbookLocation();
/*
// on linux (or elsewhere?) prompt the user for the location
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Select the folder where " +
@@ -523,6 +475,7 @@ public class Base {
} else {
System.exit(0);
}
*/
}
// create the folder if it doesn't exist already
@@ -551,6 +504,68 @@ public class Base {
}
/**
* Check for a new sketchbook location.
*/
static protected File promptSketchbookLocation() {
File folder = null;
folder = new File(System.getProperty("user.home"), "sketchbook");
if (!folder.exists()) {
folder.mkdirs();
return folder;
}
folder = Base.selectFolder("Select (or create new) folder for sketches...",
null, null);
if (folder == null) {
System.exit(0);
}
return folder;
}
/**
* Implementation for choosing directories that handles both the
* Mac OS X hack to allow the native AWT file dialog, or uses
* the JFileChooser on other platforms. Mac AWT trick obtained from
* <A HREF="http://lists.apple.com/archives/java-dev/2003/Jul/msg00243.html">this post</A>
* on the OS X Java dev archive which explains the cryptic note in
* Apple's Java 1.4 release docs about the special System property.
*/
static public File selectFolder(String prompt, File folder, Frame frame) {
if (Base.isMacOS()) {
if (frame == null) frame = new Frame(); //.pack();
FileDialog fd = new FileDialog(frame, prompt, FileDialog.LOAD);
if (folder != null) {
fd.setDirectory(folder.getParent());
//fd.setFile(folder.getName());
}
System.setProperty("apple.awt.fileDialogForDirectories", "true");
fd.show();
System.setProperty("apple.awt.fileDialogForDirectories", "false");
if (fd.getFile() == null) {
return null;
}
return new File(fd.getDirectory(), fd.getFile());
} else {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle(prompt);
if (folder != null) {
fc.setSelectedFile(folder);
}
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returned = fc.showOpenDialog(new JDialog());
if (returned == JFileChooser.APPROVE_OPTION) {
return fc.getSelectedFile();
}
}
return null;
}
static public String cleanKey(String what) {
// jnireg seems to be reading the chars as bytes
// so maybe be as simple as & 0xff and then running through decoder
@@ -631,20 +646,44 @@ public class Base {
// .................................................................
/**
* Given the reference filename from the keywords list,
* builds a URL and passes it to openURL.
*/
static public void showReference(String referenceFile) {
String currentDir = System.getProperty("user.dir");
openURL(currentDir + File.separator +
"reference" + File.separator +
referenceFile + ".html");
openURL(Base.getContents("reference" + File.separator + referenceFile));
}
static public void showReference() {
showReference("index.html");
}
static public void showEnvironment() {
showReference("Guide_Environment.html");
}
static public void showTroubleshooting() {
showReference("Guide_Troubleshooting.html");
}
/**
* Opens the local copy of the FAQ that's included
* with the Processing download.
*/
static public void showFAQ() {
showReference("faq.html");
}
// .................................................................
/**
* Implements the cross-platform headache of opening URLs
* TODO This code should be replaced by PApplet.link(),
* however that's not a static method (because it requires
* an AppletContext when used as an applet), so it's mildly
* trickier than just removing this method.
*/
static public void openURL(String url) {
//System.out.println("opening url " + url);
@@ -707,11 +746,19 @@ public class Base {
} else if (Base.isLinux()) {
// how's mozilla sound to ya, laddie?
//Runtime.getRuntime().exec(new String[] { "mozilla", url });
String browser = Preferences.get("browser");
Runtime.getRuntime().exec(new String[] { browser, url });
//String browser = Preferences.get("browser");
//Runtime.getRuntime().exec(new String[] { browser, url });
String launcher = Preferences.get("launcher.linux");
if (launcher != null) {
Runtime.getRuntime().exec(new String[] { launcher, url });
}
} else {
System.err.println("unspecified platform");
String launcher = Preferences.get("launcher");
if (launcher != null) {
Runtime.getRuntime().exec(new String[] { launcher, url });
} else {
System.err.println("Unspecified platform, no launcher available.");
}
}
} catch (IOException e) {
@@ -721,6 +768,36 @@ public class Base {
}
static boolean openFolderAvailable() {
if (Base.isWindows() || Base.isMacOS()) return true;
if (Base.isLinux()) {
// Assume that this is set to something valid
if (Preferences.get("launcher.linux") != null) {
return true;
}
// Attempt to use gnome-open
try {
Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
int result = p.waitFor();
// Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
Preferences.set("launcher.linux", "gnome-open");
return true;
} catch (Exception e) { }
// Attempt with kde-open
try {
Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
int result = p.waitFor();
Preferences.set("launcher.linux", "kde-open");
return true;
} catch (Exception e) { }
}
return false;
}
/**
* Implements the other cross-platform headache of opening
* a folder in the machine's native file browser.
@@ -742,6 +819,11 @@ public class Base {
} else if (Base.isMacOS()) {
openURL(folder); // handles char replacement, etc
} else if (Base.isLinux()) {
String launcher = Preferences.get("launcher.linux");
if (launcher != null) {
Runtime.getRuntime().exec(new String[] { launcher, folder });
}
}
} catch (IOException e) {
e.printStackTrace();
@@ -780,7 +862,7 @@ public class Base {
* for errors that allow P5 to continue running.
*/
static public void showError(String title, String message,
Exception e) {
Throwable e) {
if (title == null) title = "Error";
JOptionPane.showMessageDialog(new Frame(), message, title,
JOptionPane.ERROR_MESSAGE);
@@ -793,23 +875,29 @@ public class Base {
// ...................................................................
static public String getContents(String what) {
String basePath = System.getProperty("user.dir");
/*
// do this later, when moving to .app package
if (PApplet.platform == PConstants.MACOSX) {
basePath = System.getProperty("processing.contents");
}
*/
return basePath + File.separator + what;
}
static public String getLibContents(String what) {
return getContents("lib" + File.separator + what);
}
static public Image getImage(String name, Component who) {
Image image = null;
Toolkit tk = Toolkit.getDefaultToolkit();
//if ((Base.platform == Base.MACOSX) ||
//(Base.platform == Base.MACOS9)) {
image = tk.getImage("lib/" + name);
//} else {
//image = tk.getImage(who.getClass().getResource(name));
//}
//image = tk.getImage("lib/" + name);
//URL url = PdeApplet.class.getResource(name);
//image = tk.getImage(url);
//}
//MediaTracker tracker = new MediaTracker(applet);
MediaTracker tracker = new MediaTracker(who); //frame);
image = tk.getImage(getLibContents(name));
MediaTracker tracker = new MediaTracker(who);
tracker.addImage(image, 0);
try {
tracker.waitForAll();
@@ -819,17 +907,7 @@ public class Base {
static public InputStream getStream(String filename) throws IOException {
//if (Base.platform == Base.MACOSX) {
// macos doesn't seem to think that files in the lib folder
// are part of the resources, unlike windows or linux.
// actually, this is only the case when running as a .app,
// since it works fine from run.sh, but not Arduino.app
return new FileInputStream("lib/" + filename);
//}
// all other, more reasonable operating systems
//return cls.getResource(filename).openStream();
//return Base.class.getResource(filename).openStream();
return new FileInputStream(getLibContents(filename));
}
@@ -965,7 +1043,7 @@ public class Base {
if (!Preferences.getBoolean("compiler.save_build_files")) {
if (!dead.delete()) {
// temporarily disabled
//System.err.println("couldn't delete " + dead);
System.err.println("Could not delete " + dead);
}
}
} else {
@@ -1040,197 +1118,4 @@ public class Base {
}
}
}
/**
* Equivalent to the one in PApplet, but static (die() is removed)
*/
static public String[] loadStrings(File file) {
try {
FileInputStream input = new FileInputStream(file);
BufferedReader reader =
new BufferedReader(new InputStreamReader(input));
String lines[] = new String[100];
int lineCount = 0;
String line = null;
while ((line = reader.readLine()) != null) {
if (lineCount == lines.length) {
String temp[] = new String[lineCount << 1];
System.arraycopy(lines, 0, temp, 0, lineCount);
lines = temp;
}
lines[lineCount++] = line;
}
reader.close();
if (lineCount == lines.length) {
return lines;
}
// resize array to appropraite amount for these lines
String output[] = new String[lineCount];
System.arraycopy(lines, 0, output, 0, lineCount);
return output;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//////////////////////////////////////////////////////////////
// STRINGS
/**
* Remove whitespace characters from the beginning and ending
* of a String. Works like String.trim() but includes the
* unicode nbsp character as well.
*/
static public String trim(String str) {
return str.replace('\u00A0', ' ').trim();
/*
int left = 0;
int right = str.length() - 1;
while ((left <= right) &&
(WHITESPACE.indexOf(str.charAt(left)) != -1)) left++;
if (left == right) return "";
while (WHITESPACE.indexOf(str.charAt(right)) != -1) --right;
return str.substring(left, right-left+1);
*/
}
/**
* Join an array of Strings together as a single String,
* separated by the whatever's passed in for the separator.
*/
static public String join(String str[], char separator) {
return join(str, String.valueOf(separator));
}
/**
* Join an array of Strings together as a single String,
* separated by the whatever's passed in for the separator.
* <P>
* To use this on numbers, first pass the array to nf() or nfs()
* to get a list of String objects, then use join on that.
* <PRE>
* e.g. String stuff[] = { "apple", "bear", "cat" };
* String list = join(stuff, ", ");
* // list is now "apple, bear, cat"</PRE>
*/
static public String join(String str[], String separator) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < str.length; i++) {
if (i != 0) buffer.append(separator);
buffer.append(str[i]);
}
return buffer.toString();
}
/**
* Split the provided String at wherever whitespace occurs.
* Multiple whitespace (extra spaces or tabs or whatever)
* between items will count as a single break.
* <P>
* The whitespace characters are "\t\n\r\f", which are the defaults
* for java.util.StringTokenizer, plus the unicode non-breaking space
* character, which is found commonly on files created by or used
* in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
* <PRE>
* i.e. split("a b") -> { "a", "b" }
* split("a b") -> { "a", "b" }
* split("a\tb") -> { "a", "b" }
* split("a \t b ") -> { "a", "b" }</PRE>
*/
static public String[] split(String what) {
return split(what, WHITESPACE);
}
/**
* Splits a string into pieces, using any of the chars in the
* String 'delim' as separator characters. For instance,
* in addition to white space, you might want to treat commas
* as a separator. The delimeter characters won't appear in
* the returned String array.
* <PRE>
* i.e. split("a, b", " ,") -> { "a", "b" }
* </PRE>
* To include all the whitespace possibilities, use the variable
* WHITESPACE, found in PConstants:
* <PRE>
* i.e. split("a | b", WHITESPACE + "|"); -> { "a", "b" }</PRE>
*/
static public String[] split(String what, String delim) {
StringTokenizer toker = new StringTokenizer(what, delim);
String pieces[] = new String[toker.countTokens()];
int index = 0;
while (toker.hasMoreTokens()) {
pieces[index++] = toker.nextToken();
}
return pieces;
}
/**
* Split a string into pieces along a specific character.
* Most commonly used to break up a String along tab characters.
* <P>
* This operates differently than the others, where the
* single delimeter is the only breaking point, and consecutive
* delimeters will produce an empty string (""). This way,
* one can split on tab characters, but maintain the column
* alignments (of say an excel file) where there are empty columns.
*/
static public String[] split(String what, char delim) {
// do this so that the exception occurs inside the user's
// program, rather than appearing to be a bug inside split()
if (what == null) return null;
//return split(what, String.valueOf(delim)); // huh
char chars[] = what.toCharArray();
int splitCount = 0; //1;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == delim) splitCount++;
}
// make sure that there is something in the input string
//if (chars.length > 0) {
// if the last char is a delimeter, get rid of it..
//if (chars[chars.length-1] == delim) splitCount--;
// on second thought, i don't agree with this, will disable
//}
if (splitCount == 0) {
String splits[] = new String[1];
splits[0] = new String(what);
return splits;
}
//int pieceCount = splitCount + 1;
String splits[] = new String[splitCount + 1];
int splitIndex = 0;
int startIndex = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == delim) {
splits[splitIndex++] =
new String(chars, startIndex, i-startIndex);
startIndex = i + 1;
}
}
//if (startIndex != chars.length) {
splits[splitIndex] =
new String(chars, startIndex, chars.length-startIndex);
//}
return splits;
}
}

View File

@@ -28,11 +28,13 @@ package processing.app;
import processing.app.syntax.*;
import processing.app.tools.*;
import processing.core.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.print.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
@@ -45,7 +47,9 @@ import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
import com.apple.mrj.*;
import com.oroinc.text.regex.*;
//import de.hunsicker.jalopy.*;
import com.apple.mrj.*;
import gnu.io.*;
@@ -78,6 +82,9 @@ public class Editor extends JFrame
boolean handleNewShift;
boolean handleNewLibrary;
PageFormat pageFormat;
PrinterJob printerJob;
EditorButtons buttons;
EditorHeader header;
EditorStatus status;
@@ -133,14 +140,12 @@ public class Editor extends JFrame
// used internally, and only briefly
CompoundEdit compoundEdit;
//static public UndoManager undo = new UndoManager(); // editor needs this guy
//
//SketchHistory history; // TODO re-enable history
Sketchbook sketchbook;
//Preferences preferences;
//FindReplace find;
FindReplace find;
//static Properties keywords; // keyword -> reference html lookup
@@ -167,9 +172,13 @@ public class Editor extends JFrame
// add listener to handle window close box hit event
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
handleQuit();
handleQuitInternal();
}
});
// don't close the window when clicked, the app will take care
// of that via the handleQuitInternal() methods
// http://dev.processing.org/bugs/show_bug.cgi?id=440
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
PdeKeywords keywords = new PdeKeywords();
sketchbook = new Sketchbook(this);
@@ -188,8 +197,14 @@ public class Editor extends JFrame
// doesn't matter when this is created, just make it happen at some point
//find = new FindReplace(Editor.this);
Container pain = getContentPane();
//Container pain = getContentPane();
//pain.setLayout(new BorderLayout());
// for rev 0120, placing things inside a JPanel because
Container contentPain = getContentPane();
contentPain.setLayout(new BorderLayout());
JPanel pain = new JPanel();
pain.setLayout(new BorderLayout());
contentPain.add(pain, BorderLayout.CENTER);
Box box = Box.createVerticalBox();
Box upper = Box.createVerticalBox();
@@ -251,6 +266,17 @@ public class Editor extends JFrame
listener = new EditorListener(this, textarea);
pain.add(box);
pain.setTransferHandler(new TransferHandler() {
public boolean canImport(JComponent dest, DataFlavor[] flavors) {
// claim that we can import everything
return true;
}
public boolean importData(JComponent src, Transferable transferable) {
DataFlavor[] flavors = transferable.getTransferDataFlavors();
/*
DropTarget dt = new DropTarget(this, new DropTargetListener() {
public void dragEnter(DropTargetDragEvent event) {
@@ -278,14 +304,17 @@ public class Editor extends JFrame
Transferable transferable = event.getTransferable();
DataFlavor flavors[] = transferable.getTransferDataFlavors();
*/
int successful = 0;
for (int i = 0; i < flavors.length; i++) {
try {
//System.out.println(flavors[i]);
//System.out.println(transferable.getTransferData(flavors[i]));
java.util.List list =
(java.util.List) transferable.getTransferData(flavors[i]);
Object stuff = transferable.getTransferData(flavors[i]);
if (!(stuff instanceof java.util.List)) continue;
java.util.List list = (java.util.List) stuff;
for (int j = 0; j < list.size(); j++) {
Object item = list.get(j);
if (item instanceof File) {
@@ -298,7 +327,7 @@ public class Editor extends JFrame
File parent = file.getParentFile();
if (name.equals(parent.getName())) {
handleOpenFile(file);
return;
return true;
}
}
@@ -310,6 +339,7 @@ public class Editor extends JFrame
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@@ -322,6 +352,7 @@ public class Editor extends JFrame
} else {
message(successful + " files added to the sketch.");
}
return true;
}
});
}
@@ -488,7 +519,9 @@ public class Editor extends JFrame
listener.applyPreferences();
// in case moved to a new location
sketchbook.rebuildMenus();
// For 0125, changing to async version (to be implemented later)
//sketchbook.rebuildMenus();
sketchbook.rebuildMenusAsync();
}
@@ -576,11 +609,19 @@ public class Editor extends JFrame
menu.addSeparator();
item = newJMenuItem("Page Setup", 'P', true);
item.setEnabled(false);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handlePageSetup();
}
});
menu.add(item);
item = newJMenuItem("Print", 'P');
item.setEnabled(false);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handlePrint();
}
});
menu.add(item);
// macosx already has its own preferences and quit menu
@@ -600,7 +641,7 @@ public class Editor extends JFrame
item = newJMenuItem("Quit", 'Q');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
handleQuit();
handleQuitInternal();
}
});
menu.add(item);
@@ -639,17 +680,9 @@ public class Editor extends JFrame
menu.addSeparator();
item = new JMenuItem("Add File...");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sketch.addFile();
}
});
menu.add(item);
menu.add(sketchbook.getImportMenu());
if (Base.isWindows() || Base.isMacOS()) {
//if (Base.isWindows() || Base.isMacOS()) {
// no way to do an 'open in file browser' on other platforms
// since there isn't any sort of standard
item = newJMenuItem("Show Sketch Folder", 'K', false);
@@ -660,8 +693,20 @@ public class Editor extends JFrame
}
});
menu.add(item);
if (!Base.openFolderAvailable()) {
item.setEnabled(false);
}
//menu.addSeparator();
item = new JMenuItem("Add File...");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sketch.addFile();
}
});
menu.add(item);
// TODO re-enable history
//history.attachMenu(menu);
return menu;
@@ -681,20 +726,39 @@ public class Editor extends JFrame
item.addActionListener(new ActionListener() {
synchronized public void actionPerformed(ActionEvent e) {
new AutoFormat(Editor.this).show();
//handleBeautify();
/*
Jalopy jalopy = new Jalopy();
jalopy.setInput(getText(), sketch.current.file.getAbsolutePath());
StringBuffer buffer = new StringBuffer();
jalopy.setOutput(buffer);
jalopy.setInspect(false);
jalopy.format();
setText(buffer.toString(), 0, 0);
if (jalopy.getState() == Jalopy.State.OK)
System.out.println("successfully formatted");
else if (jalopy.getState() == Jalopy.State.WARN)
System.out.println(" formatted with warnings");
else if (jalopy.getState() == Jalopy.State.ERROR)
System.out.println(" could not be formatted");
*/
}
});
menu.add(item);
/*item = new JMenuItem("Create Font...");
item = new JMenuItem("Copy for Discourse");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//new CreateFont().show(sketch.dataFolder);
new CreateFont(Editor.this).show();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DiscourseFormat(Editor.this).show();
}
});
}
});
menu.add(item);
*/
item = new JMenuItem("Archive Sketch");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -706,13 +770,17 @@ public class Editor extends JFrame
});
menu.add(item);
/*
item = new JMenuItem("Export Folder...");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ExportFolder(Editor.this).show();
}
});
menu.add(item);
*/
menu.addSeparator();
mcuMenu = new JMenu("Microcontroller (MCU)");
@@ -946,21 +1014,18 @@ public class Editor extends JFrame
menu.add(item);
}
item = new JMenuItem("Troubleshooting");
item = new JMenuItem("Environment");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Base.openURL(System.getProperty("user.dir") + File.separator +
"reference" + File.separator +
"Guide_Troubleshooting.html");
Base.showEnvironment();
}
});
menu.add(item);
item = new JMenuItem("Environment");
item = new JMenuItem("Troubleshooting");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Base.openURL(System.getProperty("user.dir") + File.separator +
"reference" + File.separator + "Guide_Environment.html");
Base.showTroubleshooting();
}
});
menu.add(item);
@@ -968,8 +1033,17 @@ public class Editor extends JFrame
item = new JMenuItem("Reference");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Base.openURL(System.getProperty("user.dir") + File.separator +
"reference" + File.separator + "index.html");
Base.showReference();
}
});
menu.add(item);
item = newJMenuItem("Find in Reference", 'F', true);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (textarea.isSelectionActive()) {
handleReference();
}
}
});
menu.add(item);
@@ -977,33 +1051,11 @@ public class Editor extends JFrame
item = new JMenuItem("Frequently Asked Questions");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Base.openURL(System.getProperty("user.dir") + File.separator +
"reference" + File.separator + "FAQ.html");
Base.showFAQ();
}
});
menu.add(item);
// item = newJMenuItem("Find in Reference", 'F', true);
// item.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// if (textarea.isSelectionActive()) {
// String text = textarea.getSelectedText();
// if (text.length() == 0) {
// message("First select a word to find in the reference.");
//
// } else {
// String referenceFile = PdeKeywords.getReference(text);
// if (referenceFile == null) {
// message("No reference available for \"" + text + "\"");
// } else {
// Base.showReference(referenceFile);
// }
// }
// }
// }
// });
// menu.add(item);
item = newJMenuItem("Visit www.arduino.cc", '5');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -1083,22 +1135,27 @@ public class Editor extends JFrame
item = newJMenuItem("Find...", 'F');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new FindReplace(Editor.this).show();
//find.show();
if (find == null) {
find = new FindReplace(Editor.this);
}
//new FindReplace(Editor.this).show();
find.show();
//find.setVisible(true);
}
});
menu.add(item);
// TODO find next should only be enabled after a
// search has actually taken place
item = newJMenuItem("Find Next", 'G');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO find next should only be enabled after a
// search has actually taken place
if (find != null) {
//find.find(true);
FindReplace find = new FindReplace(Editor.this); //.show();
//FindReplace find = new FindReplace(Editor.this); //.show();
find.find(true);
}
}
});
menu.add(item);
@@ -1116,9 +1173,9 @@ public class Editor extends JFrame
/**
* A software engineer, somewhere, needs to have his abstraction
* taken away. In some countries they jail people for writing the
* sort of crappy api that would require a four line helper function
* to set the command key for a menu item.
* taken away. In some countries they jail or beat people for writing
* the sort of API that would require a five line helper function
* just to set the command key for a menu item.
*/
static public JMenuItem newJMenuItem(String title,
int what, boolean shift) {
@@ -1191,7 +1248,6 @@ public class Editor extends JFrame
protected void updateRedoState() {
if (undo.canRedo()) {
//this.setEnabled(true);
redoItem.setEnabled(true);
redoItem.setText(undo.getRedoPresentationName());
putValue(Action.NAME, undo.getRedoPresentationName());
@@ -1339,10 +1395,12 @@ public class Editor extends JFrame
redoAction.updateRedoState();
}
public void beginCompoundEdit() {
compoundEdit = new CompoundEdit();
}
public void endCompoundEdit() {
compoundEdit.end();
undo.addEdit(compoundEdit);
@@ -1352,6 +1410,8 @@ public class Editor extends JFrame
}
// ...................................................................
public void handleRun(final boolean present) {
doClose();
@@ -1576,42 +1636,71 @@ public class Editor extends JFrame
String prompt = "Save changes to " + sketch.name + "? ";
if (checkModifiedMode != HANDLE_QUIT) {
// if the user is not quitting, then use the nicer
// if the user is not quitting, then use simpler nicer
// dialog that's actually inside the p5 window.
status.prompt(prompt);
} else {
// if the user selected quit, then this has to be done with
// a JOptionPane instead of internally in the editor.
// TODO this is actually just a bug to be fixed.
// macosx java kills the app even though cancel might get hit
// so the cancel button is (temporarily) left off
// this may be treated differently in macosx java 1.4,
// but 1.4 isn't currently stable enough to use.
// turns out windows has the same problem (sometimes)
// disable cancel for now until a fix can be found.
Object[] options = { "Yes", "No" };
int result = JOptionPane.showOptionDialog(this,
prompt,
"Quit",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);
if (!Base.isMacOS() || PApplet.javaVersion < 1.5f) {
int result =
JOptionPane.showConfirmDialog(this, prompt, "Quit",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
handleSave(true);
checkModified2();
} else if (result == JOptionPane.NO_OPTION) {
checkModified2(); // though this may just quit
checkModified2();
}
// cancel is ignored altogether
} else if (result == JOptionPane.CANCEL_OPTION) {
// ignored
} else {
// This code is disabled unless Java 1.5 is being used on Mac OS X
// because of a Java bug that prevents the initial value of the
// dialog from being set properly (at least on my MacBook Pro).
// The bug causes the "Don't Save" option to be the highlighted,
// blinking, default. This sucks. But I'll tell you what doesn't
// suck--workarounds for the Mac and Apple's snobby attitude about it!
// adapted from the quaqua guide
// http://www.randelshofer.ch/quaqua/guide/joptionpane.html
JOptionPane pane =
new JOptionPane("<html> " +
"<head> <style type=\"text/css\">"+
"b { font: 13pt \"Lucida Grande\" }"+
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
"</style> </head>" +
"<b>Do you want to save changes to this sketch<BR>" +
" before closing?</b>" +
"<p>If you don't save, your changes will be lost.",
JOptionPane.QUESTION_MESSAGE);
String[] options = new String[] {
"Save", "Cancel", "Don't Save"
};
pane.setOptions(options);
// highlight the safest option ala apple hig
pane.setInitialValue(options[0]);
// on macosx, setting the destructive property places this option
// away from the others at the lefthand side
pane.putClientProperty("Quaqua.OptionPane.destructiveOption",
new Integer(2));
JDialog dialog = pane.createDialog(this, null);
dialog.show();
Object result = pane.getValue();
if (result == options[0]) { // save (and quit)
handleSave(true);
checkModified2();
} else if (result == options[2]) { // don't save (still quit)
checkModified2();
}
}
}
}
@@ -1739,9 +1828,15 @@ public class Editor extends JFrame
* Open a sketch from a particular path, but don't check to save changes.
* Used by Sketch.saveAs() to re-open a sketch after the "Save As"
*/
public void handleOpenUnchecked(String path) {
public void handleOpenUnchecked(String path, int codeIndex,
int selStart, int selStop, int scrollPos) {
doClose();
handleOpen2(path);
sketch.setCurrent(codeIndex);
textarea.select(selStart, selStop);
//textarea.updateScrollBars();
textarea.setScrollPosition(scrollPos);
}
@@ -1761,7 +1856,8 @@ public class Editor extends JFrame
if (!oldPath.equals(newPath)) {
if (Base.calcFolderSize(sketch.folder) == 0) {
Base.removeDir(sketch.folder);
sketchbook.rebuildMenus();
//sketchbook.rebuildMenus();
sketchbook.rebuildMenusAsync();
}
}
} catch (Exception e) { } // oh well
@@ -1893,7 +1989,11 @@ public class Editor extends JFrame
message(EMPTY);
}
// rebuild sketch menu in case a save-as was forced
sketchbook.rebuildMenus();
// Disabling this for 0125, instead rebuild the menu inside
// the Save As method of the Sketch object, since that's the
// only one who knows whether something was renamed.
//sketchbook.rebuildMenus();
//sketchbook.rebuildMenusAsync();
} catch (Exception e) {
// show the error as a message in the window
@@ -1918,7 +2018,10 @@ public class Editor extends JFrame
try {
if (sketch.saveAs()) {
message("Done Saving.");
sketchbook.rebuildMenus();
// Disabling this for 0125, instead rebuild the menu inside
// the Save As method of the Sketch object, since that's the
// only one who knows whether something was renamed.
//sketchbook.rebuildMenusAsync();
} else {
message("Save Cancelled.");
}
@@ -2007,6 +2110,7 @@ public class Editor extends JFrame
null,
options,
options[0]);
if (result == JOptionPane.OK_OPTION) {
handleSave(true);
@@ -2021,13 +2125,57 @@ public class Editor extends JFrame
return true;
}
public void handlePageSetup() {
//printerJob = null;
if (printerJob == null) {
printerJob = PrinterJob.getPrinterJob();
}
if (pageFormat == null) {
pageFormat = printerJob.defaultPage();
}
pageFormat = printerJob.pageDialog(pageFormat);
//System.out.println("page format is " + pageFormat);
}
public void handlePrint() {
message("Printing...");
//printerJob = null;
if (printerJob == null) {
printerJob = PrinterJob.getPrinterJob();
}
if (pageFormat != null) {
//System.out.println("setting page format " + pageFormat);
printerJob.setPrintable(textarea.getPainter(), pageFormat);
} else {
printerJob.setPrintable(textarea.getPainter());
}
// set the name of the job to the code name
printerJob.setJobName(sketch.current.name);
if (printerJob.printDialog()) {
try {
printerJob.print();
message("Done printing.");
} catch (PrinterException pe) {
error("Error while printing.");
pe.printStackTrace();
}
} else {
message("Printing canceled.");
}
//printerJob = null; // clear this out?
}
/**
* Quit, but first ask user if it's ok. Also store preferences
* to disk just in case they want to quit. Final exit() happens
* in Editor since it has the callback from EditorStatus.
*/
public void handleQuit() {
public void handleQuitInternal() {
// doStop() isn't sufficient with external vm & quit
// instead use doClose() which will kill the external vm
doClose();
@@ -2036,6 +2184,27 @@ public class Editor extends JFrame
}
/**
* Method for the MRJQuitHandler, needs to be dealt with differently
* than the regular handler because OS X has an annoying implementation
* <A HREF="http://developer.apple.com/qa/qa2001/qa1187.html">quirk</A>
* that requires an exception to be thrown in order to properly cancel
* a quit message.
*/
public void handleQuit() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
handleQuitInternal();
}
});
// Throw IllegalStateException so new thread can execute.
// If showing dialog on this thread in 10.2, we would throw
// upon JOptionPane.NO_OPTION
throw new IllegalStateException("Quit Pending User Confirmation");
}
/**
* Actually do the quit action.
*/
@@ -2050,6 +2219,26 @@ public class Editor extends JFrame
System.exit(0);
}
protected void handleReference() {
String text = textarea.getSelectedText().trim();
if (text.length() == 0) {
message("First select a word to find in the reference.");
} else {
String referenceFile = PdeKeywords.getReference(text);
//System.out.println("reference file is " + referenceFile);
if (referenceFile == null) {
message("No reference available for \"" + text + "\"");
} else {
Base.showReference(referenceFile + ".html");
}
}
}
protected void handleBurnBootloader(final String target, final boolean parallel) {
if(debugging)
doStop();
@@ -2083,6 +2272,7 @@ public class Editor extends JFrame
}});
}
public void highlightLine(int lnum) {
if (lnum < 0) {
textarea.select(0, 0);
@@ -2169,7 +2359,7 @@ public class Editor extends JFrame
public void error(RunnerException e) {
//System.out.println("ERORROOROROR 2");
//System.out.println("file and line is " + e.file + " " + e.line);
if (e.file >= 0) sketch.setCurrent(e.file);
if (e.line >= 0) highlightLine(e.line);
@@ -2205,7 +2395,7 @@ public class Editor extends JFrame
* Returns the edit popup menu.
*/
class TextAreaPopup extends JPopupMenu {
String currentDir = System.getProperty("user.dir");
//String currentDir = System.getProperty("user.dir");
String referenceFile = null;
JMenuItem cutItem, copyItem;
@@ -2251,13 +2441,14 @@ public class Editor extends JFrame
this.addSeparator();
// referenceItem = new JMenuItem("Find in Reference");
// referenceItem.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// Base.showReference(referenceFile);
// }
// });
// this.add(referenceItem);
referenceItem = new JMenuItem("Find in Reference");
referenceItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Base.showReference(referenceFile + ".html");
handleReference(); //textarea.getSelectedText());
}
});
this.add(referenceItem);
}
// if no text is selected, disable copy and cut menu items
@@ -2266,14 +2457,14 @@ public class Editor extends JFrame
cutItem.setEnabled(true);
copyItem.setEnabled(true);
//referenceFile = PdeKeywords.getReference(textarea.getSelectedText());
//if (referenceFile != null) {
//referenceItem.setEnabled(true);
//}
String sel = textarea.getSelectedText().trim();
referenceFile = PdeKeywords.getReference(sel);
referenceItem.setEnabled(referenceFile != null);
} else {
cutItem.setEnabled(false);
copyItem.setEnabled(false);
//referenceItem.setEnabled(false);
referenceItem.setEnabled(false);
}
super.show(component, x, y);
}

View File

@@ -241,6 +241,7 @@ public class EditorHeader extends JComponent {
public void rebuildMenu() {
//System.out.println("rebuilding");
if (menu != null) {
menu.removeAll();
@@ -248,6 +249,9 @@ public class EditorHeader extends JComponent {
menu = new JMenu();
popup = menu.getPopupMenu();
add(popup);
popup.setLightWeightPopupEnabled(true);
/*
popup.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuCanceled(PopupMenuEvent e) {
// on redraw, the isVisible() will get checked.
@@ -259,6 +263,7 @@ public class EditorHeader extends JComponent {
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
});
*/
}
JMenuItem item;
@@ -352,6 +357,43 @@ public class EditorHeader extends JComponent {
}
menu.add(unhide);
menu.addSeparator();
// KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep
int ctrlAlt = ActionEvent.ALT_MASK |
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
//item = Editor.newJMenuItem("Previous Tab", '[', true);
item = new JMenuItem("Previous Tab");
//int shortcut = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
KeyStroke ctrlAltLeft = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAlt);
item.setAccelerator(ctrlAltLeft);
//int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
//KeyStroke tabby = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, modifiers);
// this didn't want to work consistently
/*
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
editor.sketch.prevCode();
}
});
*/
menu.add(item);
//item = Editor.newJMenuItem("Next Tab", ']', true);
item = new JMenuItem("Next Tab");
KeyStroke ctrlAltRight = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAlt);
item.setAccelerator(ctrlAltRight);
/*
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
editor.sketch.nextCode();
}
});
*/
menu.add(item);
if (sketch != null) {
menu.addSeparator();

View File

@@ -60,6 +60,10 @@ public class EditorListener {
int selectionStart, selectionEnd;
int position;
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
static final int CTRL_ALT = ActionEvent.ALT_MASK |
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
public EditorListener(Editor editor, JEditTextArea textarea) {
this.editor = editor;
@@ -105,6 +109,16 @@ public class EditorListener {
//System.out.println(c + " " + code + " " + event);
//System.out.println();
if ((event.getModifiers() & CTRL_ALT) == CTRL_ALT) {
if (code == KeyEvent.VK_LEFT) {
editor.sketch.prevCode();
return true;
} else if (code == KeyEvent.VK_RIGHT) {
editor.sketch.nextCode();
return true;
}
}
if ((event.getModifiers() & KeyEvent.META_MASK) != 0) {
//event.consume(); // does nothing
return false;
@@ -195,8 +209,8 @@ public class EditorListener {
switch ((int) c) {
case 9: // expand tabs
if (tabsExpand) {
case 9:
if (tabsExpand) { // expand tabs
textarea.setSelectedText(tabString);
event.consume();
return true;
@@ -286,12 +300,40 @@ public class EditorListener {
origIndex += offset; // ARGH!#(* WINDOWS#@($*
*/
// if the previous thing is a brace (whether prev line or
// up farther) then the correct indent is the number of spaces
// on that line + 'indent'.
// if the previous line is not a brace, then just use the
// identical indentation to the previous line
// calculate the amount of indent on the previous line
// this will be used *only if the prev line is not an indent*
int spaceCount = calcSpaceCount(origIndex, contents);
//int origCount = spaceCount;
// If the last character was a left curly brace, then indent.
// For 0122, walk backwards a bit to make sure that the there
// isn't a curly brace several spaces (or lines) back. Also
// moved this before calculating extraCount, since it'll affect
// that as well.
int index2 = origIndex;
while ((index2 >= 0) &&
Character.isWhitespace(contents[index2])) {
index2--;
}
if (index2 != -1) {
// still won't catch a case where prev stuff is a comment
if (contents[index2] == '{') {
// intermediate lines be damned,
// use the indent for this line instead
spaceCount = calcSpaceCount(index2, contents);
spaceCount += tabSize;
}
}
//System.out.println("spaceCount should be " + spaceCount);
// now before inserting this many spaces, walk forward from
// the caret position, so that the number of spaces aren't
// just being duplicated again
// the caret position and count the number of spaces,
// so that the number of spaces aren't duplicated again
int index = origIndex + 1;
int extraCount = 0;
while ((index < contents.length) &&
@@ -300,23 +342,58 @@ public class EditorListener {
extraCount++;
index++;
}
int braceCount = 0;
while ((index < contents.length) && (contents[index] != '\n')) {
if (contents[index] == '}') {
braceCount++;
}
index++;
}
// hitting return on a line with spaces *after* the caret
// can cause trouble. for simplicity's sake, just ignore this case.
//if (spaceCount < 0) spaceCount = origCount;
// can cause trouble. for 0099, was ignoring the case, but this is
// annoying, so in 0122 we're trying to fix that.
/*
if (spaceCount - extraCount > 0) {
spaceCount -= extraCount;
}
*/
spaceCount -= extraCount;
//if (spaceCount < 0) spaceCount = 0;
//System.out.println("extraCount is " + extraCount);
// if the last character was a left curly brace, then indent
if (origIndex != -1) {
if (contents[origIndex] == '{') {
spaceCount += tabSize;
}
}
// now, check to see if the current line contains a } and if so,
// outdent again by indent
//if (braceCount > 0) {
//spaceCount -= 2;
//}
if (spaceCount < 0) {
// for rev 0122, actually delete extra space
//textarea.setSelectionStart(origIndex + 1);
textarea.setSelectionEnd(textarea.getSelectionEnd() - spaceCount);
textarea.setSelectedText("\n");
} else {
String insertion = "\n" + Editor.EMPTY.substring(0, spaceCount);
textarea.setSelectedText(insertion);
}
// not gonna bother handling more than one brace
if (braceCount > 0) {
int sel = textarea.getSelectionStart();
// sel - tabSize will be -1 if start/end parens on the same line
// http://dev.processing.org/bugs/show_bug.cgi?id=484
if (sel - tabSize >= 0) {
textarea.select(sel - tabSize, sel);
String s = Editor.EMPTY.substring(0, tabSize);
// if these are spaces that we can delete
if (textarea.getSelectedText().equals(s)) {
textarea.setSelectedText("");
} else {
textarea.select(sel, sel);
}
}
}
// mark this event as already handled
event.consume();
@@ -424,6 +501,34 @@ public class EditorListener {
}
/** Cmd-Shift or Ctrl-Shift depending on the platform */
//static final int CMD_SHIFT = ActionEvent.SHIFT_MASK |
// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
/** ctrl-alt on windows and linux, cmd-alt on mac os x */
//static final int CTRL_ALT = ActionEvent.ALT_MASK |
// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
/*
public boolean keyTyped(KeyEvent event) {
char c = event.getKeyChar();
int code = event.getKeyCode();
if ((event.getModifiers() & CMD_ALT) == CMD_ALT) {
if (code == KeyEvent.VK_LEFT) {
//if (c == '[') {
editor.sketch.prevCode();
return true;
} else if (code == KeyEvent.VK_RIGHT) {
//} else if (c == ']') {
editor.sketch.nextCode();
return true;
}
}
return false;
}
*/
/**
* Return the index for the first character on this line.
*/

View File

@@ -57,6 +57,7 @@ public class FindReplace extends JFrame implements ActionListener {
JButton replaceButton;
JButton replaceAllButton;
JButton replaceFindButton;
JButton findButton;
JCheckBox ignoreCaseBox;
@@ -132,12 +133,14 @@ public class FindReplace extends JFrame implements ActionListener {
// ordering is different on mac versus pc
if (Base.isMacOS()) {
buttons.add(replaceButton = new JButton("Replace"));
buttons.add(replaceAllButton = new JButton("Replace All"));
buttons.add(replaceButton = new JButton("Replace"));
buttons.add(replaceFindButton = new JButton("Replace & Find"));
buttons.add(findButton = new JButton("Find"));
} else {
buttons.add(findButton = new JButton("Find"));
buttons.add(replaceFindButton = new JButton("Replace & Find"));
buttons.add(replaceButton = new JButton("Replace"));
buttons.add(replaceAllButton = new JButton("Replace All"));
}
@@ -169,10 +172,12 @@ public class FindReplace extends JFrame implements ActionListener {
replaceButton.addActionListener(this);
replaceAllButton.addActionListener(this);
replaceFindButton.addActionListener(this);
findButton.addActionListener(this);
// you mustn't replace what you haven't found, my son
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
// so that typing will go straight to this field
//findField.requestFocus();
@@ -189,44 +194,28 @@ public class FindReplace extends JFrame implements ActionListener {
setBounds((screen.width - wide) / 2,
(screen.height - high) / 2, wide, high);
// add key listener to trap esc and ctrl/cmd-w
/*
KeyListener listener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (Base.isCloseWindowEvent(e)) hide();
}
};
findField.addKeyListener(listener);
replaceField.addKeyListener(listener);
addKeyListener(listener);
*/
ActionListener disposer = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//hide();
handleClose();
}
};
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
handleClose();
}
});
Base.registerWindowCloseKeys(getRootPane(), disposer);
Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
//hide();
handleClose();
}
});
/*
// hack to to get first field to focus properly on osx
// though this still doesn't seem to work
addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
//System.out.println("activating");
//boolean ok = findField.requestFocusInWindow();
boolean ok = findField.requestFocusInWindow();
//System.out.println("got " + ok);
//findField.selectAll();
findField.selectAll();
}
});
*/
}
@@ -256,6 +245,10 @@ public class FindReplace extends JFrame implements ActionListener {
if (source == findButton) {
find(true);
} else if (source == replaceFindButton) {
replace();
find(true);
} else if (source == replaceButton) {
replace();
@@ -276,6 +269,7 @@ public class FindReplace extends JFrame implements ActionListener {
found = false;
String search = findField.getText();
//System.out.println("finding for " + search + " " + findString);
// this will catch "find next" being called when no search yet
if (search.length() == 0) return;
@@ -299,12 +293,14 @@ public class FindReplace extends JFrame implements ActionListener {
if (nextIndex == -1) {
found = false;
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
//Toolkit.getDefaultToolkit().beep();
return;
}
}
found = true;
replaceButton.setEnabled(true);
replaceFindButton.setEnabled(true);
editor.textarea.select(nextIndex, nextIndex + search.length());
}
@@ -322,6 +318,7 @@ public class FindReplace extends JFrame implements ActionListener {
if (sel.equals(replaceField.getText())) {
found = false;
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
return;
}
@@ -332,6 +329,7 @@ public class FindReplace extends JFrame implements ActionListener {
// don't allow a double replace
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
}

View File

@@ -31,6 +31,8 @@ import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import processing.core.*;
/*
* Provides information about and builds a library
*/
@@ -552,7 +554,7 @@ public class Library implements MessageConsumer{
continue;
}
String pieces[] = Base.split(line, '\t');
String pieces[] = PApplet.split(line, '\t');
if (pieces.length >= 2) {
String keyword = pieces[0].trim();

View File

@@ -41,7 +41,12 @@ import javax.swing.filechooser.*;
import javax.swing.text.*;
import javax.swing.undo.*;
//import processing.core.PApplet;
import processing.core.PApplet;
// TODO change this to use the Java Preferences API
// http://www.onjava.com/pub/a/onjava/synd/2001/10/17/j2se.html
// http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter10/Preferences.html
/**
@@ -50,6 +55,10 @@ import javax.swing.undo.*;
* This class no longer uses the Properties class, since
* properties files are iso8859-1, which is highly likely to
* be a problem when trying to save sketch folders and locations.
* <p>
* This is very poorly put together, that the prefs panel and the
* actual prefs i/o is part of the same code. But there hasn't yet
* been a compelling reason to bother with the separation.
*/
public class Preferences {
@@ -88,9 +97,12 @@ public class Preferences {
* inside a static block.
*/
static public int BUTTON_HEIGHT = 24;
/*
// remove this for 0121, because quaqua takes care of it
static {
if (Base.isMacOS()) BUTTON_HEIGHT = 29;
}
*/
// value for the size bars, buttons, etc
@@ -107,15 +119,18 @@ public class Preferences {
// gui elements
JDialog dialog;
//JDialog dialog;
JFrame dialog;
int wide, high;
JTextField sketchbookLocationField;
JCheckBox exportSeparateBox;
JCheckBox sketchPromptBox;
JCheckBox sketchCleanBox;
JCheckBox externalEditorBox;
JCheckBox memoryOverrideBox;
JTextField memoryField;
JCheckBox checkUpdatesBox;
JTextField fontSizeField;
@@ -145,7 +160,7 @@ public class Preferences {
// check for platform-specific properties in the defaults
String platformExtension = "." +
platforms[Base.platform];
platforms[processing.core.PApplet.platform];
int extensionLength = platformExtension.length();
Enumeration e = table.keys(); //properties.propertyNames();
@@ -195,7 +210,8 @@ public class Preferences {
// setup dialog for the prefs
dialog = new JDialog(editor, "Preferences", true);
//dialog = new JDialog(editor, "Preferences", true);
dialog = new JFrame("Preferences");
dialog.setResizable(false);
Container pain = dialog.getContentPane();
@@ -249,6 +265,7 @@ public class Preferences {
button = new JButton(PROMPT_BROWSE);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
/*
JFileChooser fc = new JFileChooser();
fc.setSelectedFile(new File(sketchbookLocationField.getText()));
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
@@ -258,6 +275,13 @@ public class Preferences {
File file = fc.getSelectedFile();
sketchbookLocationField.setText(file.getAbsolutePath());
}
*/
File dflt = new File(sketchbookLocationField.getText());
File file =
Base.selectFolder("Select new sketchbook location", dflt, dialog);
if (file != null) {
sketchbookLocationField.setText(file.getAbsolutePath());
}
}
});
pain.add(button);
@@ -286,6 +310,8 @@ public class Preferences {
box.add(label);
fontSizeField = new JTextField(4);
box.add(fontSizeField);
label = new JLabel(" (requires restart of Arduino)");
box.add(label);
pain.add(box);
d = box.getPreferredSize();
box.setBounds(left, top, d.width, d.height);
@@ -468,9 +494,9 @@ public class Preferences {
String newSizeText = fontSizeField.getText();
try {
int newSize = Integer.parseInt(newSizeText.trim());
String pieces[] = Base.split(get("editor.font"), ',');
String pieces[] = PApplet.split(get("editor.font"), ',');
pieces[2] = String.valueOf(newSize);
set("editor.font", Base.join(pieces, ','));
set("editor.font", PApplet.join(pieces, ','));
} catch (Exception e) {
System.err.println("ignoring invalid font size " + newSizeText);

View File

@@ -23,7 +23,7 @@
package processing.app;
//import processing.core.*;
import processing.core.*;
import java.awt.*;
import java.awt.event.*;
@@ -40,7 +40,7 @@ import com.oroinc.text.regex.*;
*/
public class Runner implements MessageConsumer {
//PApplet applet;
PApplet applet;
RunnerException exception;
Window window;
PrintStream leechErr;
@@ -497,6 +497,7 @@ java.lang.NullPointerException
}
if (codeIndex != -1) {
//System.out.println("got line num " + lineNumber);
// in case this was a tab that got embedded into the main .java
lineNumber -= sketch.code[codeIndex].preprocOffset;

View File

@@ -24,7 +24,7 @@
package processing.app;
import processing.app.preproc.*;
//import processing.core.*;
import processing.core.*;
import java.awt.*;
import java.io.*;
@@ -73,6 +73,7 @@ public class Sketch {
static final String flavorExtensionsShown[] = new String[] { "", ".cpp", ".c", ".h" };
public SketchCode current;
int currentIndex;
int codeCount;
SketchCode code[];
@@ -225,7 +226,11 @@ public class Sketch {
}
}
// remove any entries that didn't load properly
// some of the hidden files may be bad too, so use hiddenCounter
// added for rev 0121, fixes bug found by axel
hiddenCount = hiddenCounter;
// remove any entries that didn't load properly from codeCount
int index = 0;
while (index < codeCount) {
if ((code[index] == null) ||
@@ -330,7 +335,7 @@ public class Sketch {
// ask for new name of file (internal to window)
// TODO maybe just popup a text area?
renamingCode = true;
String prompt = (current == code[0]) ?
String prompt = (currentIndex == 0) ?
"New name for sketch:" : "New name for file:";
String oldName = current.name + flavorExtensionsShown[current.flavor];
editor.status.edit(prompt, oldName);
@@ -436,7 +441,7 @@ public class Sketch {
}
if (renamingCode) {
if (current == code[0]) {
if (currentIndex == 0) {
// get the new folder name/location
File newFolder = new File(folder.getParentFile(), newName);
if (newFolder.exists()) {
@@ -494,43 +499,17 @@ public class Sketch {
// having saved everything and renamed the folder and the main .pde,
// use the editor to re-open the sketch to re-init state
// (unfortunately this will kill positions for carets etc)
editor.handleOpenUnchecked(mainFilename);
/*
// backtrack and don't rename the sketch folder
success = newFolder.renameTo(folder);
if (!success) {
String msg =
"Started renaming sketch and then ran into\n" +
"nasty trouble. Try to salvage with Copy & Paste\n" +
"or attempt a \"Save As\" to see if that works.";
Base.showWarning("Serious Error", msg, null);
}
return;
}
*/
/*
// set the sketch name... used by the pde and whatnot.
// the name is only set in the sketch constructor,
// so it's important here
name = newName;
code[0].name = newName;
code[0].file = mainFile;
code[0].program = editor.getText();
code[0].save();
folder = newFolder;
editor.handleOpenUnchecked(mainFilename,
currentIndex,
editor.textarea.getSelectionStart(),
editor.textarea.getSelectionEnd(),
editor.textarea.getScrollPosition());
// get the changes into the sketchbook menu
// (re-enabled in 0115 to fix bug #332)
editor.sketchbook.rebuildMenus();
// reload the sketch
load();
*/
} else {
} else { // else if something besides code[0]
if (!current.file.renameTo(newFile)) {
Base.showWarning("Error",
"Could not rename \"" + current.file.getName() +
@@ -593,7 +572,7 @@ public class Sketch {
// confirm deletion with user, yes/no
Object[] options = { "OK", "Cancel" };
String prompt = (current == code[0]) ?
String prompt = (currentIndex == 0) ?
"Are you sure you want to delete this sketch?" :
"Are you sure you want to delete \"" + current.name +
flavorExtensionsShown[current.flavor] + "\"?";
@@ -606,7 +585,7 @@ public class Sketch {
options,
options[0]);
if (result == JOptionPane.YES_OPTION) {
if (current == code[0]) {
if (currentIndex == 0) {
// need to unset all the modified flags, otherwise tries
// to do a save on the handleNew()
@@ -672,7 +651,7 @@ public class Sketch {
// don't allow hide of the main code
// TODO maybe gray out the menu on setCurrent(0)
if (current == code[0]) {
if (currentIndex == 0) {
Base.showMessage("Can't do that",
"You cannot hide the main " +
".pde file from a sketch\n");
@@ -933,57 +912,14 @@ public class Sketch {
File newFile = new File(newFolder, newName + ".pde");
code[0].saveAs(newFile);
editor.handleOpenUnchecked(newFile.getPath());
editor.handleOpenUnchecked(newFile.getPath(),
currentIndex,
editor.textarea.getSelectionStart(),
editor.textarea.getSelectionEnd(),
editor.textarea.getScrollPosition());
/*
// copy the entire contents of the sketch folder
Base.copyDir(folder, newFolder);
// change the references to the dir location in SketchCode files
for (int i = 0; i < codeCount; i++) {
code[i].file = new File(newFolder, code[i].file.getName());
}
for (int i = 0; i < hiddenCount; i++) {
hidden[i].file = new File(newFolder, hidden[i].file.getName());
}
// remove the old sketch file from the new dir
code[0].file.delete();
// name for the new main .pde file
code[0].file = new File(newFolder, newName + ".pde");
code[0].name = newName;
// write the contents to the renamed file
// (this may be resaved if the code is modified)
code[0].modified = true;
//code[0].save();
//System.out.println("modified is " + modified);
// change the other paths
String oldName = name;
name = newName;
File oldFolder = folder;
folder = newFolder;
dataFolder = new File(folder, "data");
codeFolder = new File(folder, "code");
// remove the 'applet', 'application', 'library' folders
// from the copied version.
// otherwise their .class and .jar files can cause conflicts.
Base.removeDir(new File(folder, "applet"));
Base.removeDir(new File(folder, "application"));
//Base.removeDir(new File(folder, "library"));
// do a "save"
// this will take care of the unsaved changes in each of the tabs
save();
// get the changes into the sketchbook menu
//sketchbook.rebuildMenu();
// done inside Editor instead
// update the tabs for the name change
editor.header.repaint();
*/
// Name changed, rebuild the sketch menus
editor.sketchbook.rebuildMenusAsync();
// let Editor know that the save was successful
return true;
@@ -1168,8 +1104,8 @@ public class Sketch {
* </OL>
*/
public void setCurrent(int which) {
if (current == code[which]) {
//System.out.println("already current, ignoring");
// if current is null, then this is the first setCurrent(0)
if ((currentIndex == which) && (current != null)) {
return;
}
@@ -1182,6 +1118,7 @@ public class Sketch {
}
current = code[which];
currentIndex = which;
editor.setCode(current);
//editor.setDocument(current.document,
// current.selectionStart, current.selectionStop,
@@ -1286,6 +1223,9 @@ public class Sketch {
//handleOpen(sketch);
//history.lastRecorded = historySaved;
// set current to null so that the tab gets updated
// http://dev.processing.org/bugs/show_bug.cgi?id=515
current = null;
// nuke previous files and settings, just get things loaded
load();
}
@@ -1746,7 +1686,12 @@ public class Sketch {
// make sure the user didn't hide the sketch folder
ensureExistence();
current.program = editor.getText();
// fix for issue posted on the board. make sure that the code
// is reloaded when exporting and an external editor is being used.
if (Preferences.getBoolean("editor.external")) {
// nuke previous files and settings
load();
}
zipFileContents = new Hashtable();
@@ -1773,6 +1718,7 @@ public class Sketch {
/* int wide = PApplet.DEFAULT_WIDTH;
int high = PApplet.DEFAULT_HEIGHT;
String renderer = "";
PatternMatcher matcher = new Perl5Matcher();
PatternCompiler compiler = new Perl5Compiler();
@@ -1785,20 +1731,26 @@ public class Sketch {
// modified for 83 to match size(XXX, ddd so that it'll
// properly handle size(200, 200) and size(200, 200, P3D)
String sizing =
"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+)";
// match the renderer string as well
"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+),?\\s*([^\\)]*)\\s*\\)";
// match just the width and height
//"[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+)(.*)\\)";
Pattern pattern = compiler.compile(sizing);
// adds a space at the beginning, in case size() is the very
// first thing in the program (very common), since the regexp
// needs to check for things in front of it.
PatternMatcherInput input =
new PatternMatcherInput(" " + code[0].program);
new PatternMatcherInput(" " + scrubComments(code[0].program));
if (matcher.contains(input, pattern)) {
MatchResult result = matcher.getMatch();
try {
wide = Integer.parseInt(result.group(1).toString());
high = Integer.parseInt(result.group(2).toString());
renderer = result.group(3).toString(); //.trim();
} catch (NumberFormatException e) {
// found a reference to size, but it didn't
// seem to contain numbers
@@ -1865,45 +1817,6 @@ public class Sketch {
if (is == null) {
is = Base.getStream("applet.html");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
if (line.indexOf("@@") != -1) {
StringBuffer sb = new StringBuffer(line);
int index = 0;
while ((index = sb.indexOf("@@sketch@@")) != -1) {
sb.replace(index, index + "@@sketch@@".length(),
name);
}
while ((index = sb.indexOf("@@source@@")) != -1) {
sb.replace(index, index + "@@source@@".length(),
sources.toString());
}
while ((index = sb.indexOf("@@archive@@")) != -1) {
sb.replace(index, index + "@@archive@@".length(),
name + ".jar");
}
while ((index = sb.indexOf("@@width@@")) != -1) {
sb.replace(index, index + "@@width@@".length(),
String.valueOf(wide));
}
while ((index = sb.indexOf("@@height@@")) != -1) {
sb.replace(index, index + "@@height@@".length(),
String.valueOf(high));
}
while ((index = sb.indexOf("@@description@@")) != -1) {
sb.replace(index, index + "@@description@@".length(),
description);
}
line = sb.toString();
}
ps.println(line);
}
reader.close();
ps.flush();
ps.close();
// copy the loading gif to the applet
String LOADING_IMAGE = "loading.gif";
@@ -1929,13 +1842,13 @@ public class Sketch {
new FileOutputStream(new File(appletFolder, name + ".jar"));
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
ZipEntry entry;
archives.append(name + ".jar");
// add the manifest file
addManifest(zos);
// add the contents of the code folder to the jar
// unpacks all jar files
//File codeFolder = new File(folder, "code");
// unpacks all jar files, unless multi jar files selected in prefs
if (codeFolder.exists()) {
String includes = Compiler.contentsToClassPath(codeFolder);
packClassPathIntoZipFile(includes, zos);
@@ -1980,7 +1893,18 @@ public class Sketch {
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
exportFile.getName().toLowerCase().endsWith(".jar")) {
if (separateJar) {
String exportFilename = exportFile.getName();
Base.copyFile(exportFile, new File(appletFolder, exportFilename));
if (renderer.equals("OPENGL") &&
exportFilename.indexOf("natives") != -1) {
// don't add these to the archives list
} else {
archives.append("," + exportFilename);
}
} else {
packClassPathIntoZipFile(exportFile.getAbsolutePath(), zos);
}
} else { // just copy the file over.. prolly a .dll or something
Base.copyFile(exportFile,
@@ -1991,6 +1915,7 @@ public class Sketch {
*/
/* String bagelJar = "lib/core.jar";
packClassPathIntoZipFile(bagelJar, zos);
}
// files to include from data directory
// TODO this needs to be recursive
@@ -2049,6 +1974,53 @@ public class Sketch {
}
static public String scrubComments(String what) {
char p[] = what.toCharArray();
int index = 0;
while (index < p.length) {
// for any double slash comments, ignore until the end of the line
if ((p[index] == '/') &&
(index < p.length - 1) &&
(p[index+1] == '/')) {
p[index++] = ' ';
p[index++] = ' ';
while ((index < p.length) &&
(p[index] != '\n')) {
p[index++] = ' ';
}
// check to see if this is the start of a new multiline comment.
// if it is, then make sure it's actually terminated somewhere.
} else if ((p[index] == '/') &&
(index < p.length - 1) &&
(p[index+1] == '*')) {
p[index++] = ' ';
p[index++] = ' ';
boolean endOfRainbow = false;
while (index < p.length - 1) {
if ((p[index] == '*') && (p[index+1] == '/')) {
p[index++] = ' ';
p[index++] = ' ';
endOfRainbow = true;
break;
} else {
index++;
}
}
if (!endOfRainbow) {
throw new RuntimeException("Missing the */ from the end of a " +
"/* comment */");
}
} else { // any old character, move along
index++;
}
}
return new String(p);
}
/**
* Export to application.
* <PRE>
@@ -2135,7 +2107,6 @@ public class Sketch {
for (int i = 0; i < pieces.length; i++) {
if (pieces[i].length() == 0) continue;
//System.out.println("checking piece " + pieces[i]);
// is it a jar file or directory?
if (pieces[i].toLowerCase().endsWith(".jar") ||
@@ -2299,4 +2270,16 @@ public class Sketch {
public String getMainFilePath() {
return code[0].file.getAbsolutePath();
}
public void prevCode() {
int prev = currentIndex - 1;
if (prev < 0) prev = codeCount-1;
setCurrent(prev);
}
public void nextCode() {
setCurrent((currentIndex + 1) % codeCount);
}
}

View File

@@ -130,6 +130,7 @@ public class Sketchbook {
//System.out.println("resetting sketchbook path");
File sketchbookFolder = Base.getDefaultSketchbookFolder();
//System.out.println("default is " + sketchbookFolder);
Preferences.set("sketchbook.path",
sketchbookFolder.getAbsolutePath());
@@ -170,11 +171,8 @@ public class Sketchbook {
if (noPrompt) prompt = false;
if (prompt) {
//if (!startup) {
// prompt for the filename and location for the new sketch
FileDialog fd = new FileDialog(editor, //new Frame(),
//"Create new sketch named",
FileDialog fd = new FileDialog(editor,
"Create sketch folder named:",
FileDialog.SAVE);
fd.setDirectory(getSketchbookPath());
@@ -228,7 +226,7 @@ public class Sketchbook {
}
// make a note of a newly added sketch in the sketchbook menu
rebuildMenus();
rebuildMenusAsync();
// now open it up
//handleOpen(newbieName, newbieFile, newbieDir);
@@ -257,10 +255,25 @@ public class Sketchbook {
/**
* Java classes are pretty limited about what you can use
* for their naming. This helper function replaces everything
* but A-Z, a-z, and 0-9 with underscores. Also disallows
* starting the sketch name with a digit.
* Return true if the name is valid for a Processing sketch.
*/
static public boolean isSanitary(String name) {
return sanitizedName(name).equals(name);
}
/**
* Produce a sanitized name that fits our standards for likely to work.
* <p/>
* Java classes have a wider range of names that are technically allowed
* (supposedly any Unicode name) than what we support. The reason for
* going more narrow is to avoid situations with text encodings and
* converting during the process of moving files between operating
* systems, i.e. uploading from a Windows machine to a Linux server,
* or reading a FAT32 partition in OS X and using a thumb drive.
* <p/>
* This helper function replaces everything but A-Z, a-z, and 0-9 with
* underscores. Also disallows starting the sketch name with a digit.
*/
static public String sanitizedName(String origName) {
char c[] = origName.toCharArray();
@@ -280,7 +293,12 @@ public class Sketchbook {
buffer.append('_');
}
}
// let's not be ridiculous about the length of filenames
// let's not be ridiculous about the length of filenames.
// in fact, Mac OS 9 can handle 255 chars, though it can't really
// deal with filenames longer than 31 chars in the Finder.
// but limiting to that for sketches would mean setting the
// upper-bound on the character limit here to 25 characters
// (to handle the base name + ".class")
if (buffer.length() > 63) {
buffer.setLength(63);
}
@@ -290,12 +308,12 @@ public class Sketchbook {
public String handleOpen() {
// swing's file choosers are ass ugly, so we use the
// native (awt peered) dialogs instead
// native (awt peered) dialogs where possible
FileDialog fd = new FileDialog(editor, //new Frame(),
"Open a Processing sketch...",
FileDialog.LOAD);
//fd.setDirectory(Preferences.get("sketchbook.path"));
fd.setDirectory(getSketchbookPath());
//fd.setDirectory(getSketchbookPath());
// only show .pde files as eligible bachelors
// TODO this doesn't seem to ever be used. AWESOME.
@@ -324,6 +342,23 @@ public class Sketchbook {
}
/**
* Asynchronous version of menu rebuild to be used on 'new' and 'save',
* to prevent the interface from locking up until the menus are done.
*/
public void rebuildMenusAsync() {
// disabling the async option for actual release, this hasn't been tested
/*
SwingUtilities.invokeLater(new Runnable() {
public void run() {
rebuildMenus();
}
});
*/
rebuildMenus();
}
/**
* Rebuild the menu full of sketches based on the
* contents of the sketchbook.
@@ -333,6 +368,7 @@ public class Sketchbook {
* the menu will disappear from its original location.
*/
public void rebuildMenus() {
//EditorConsole.systemOut.println("rebuilding menus");
try {
// rebuild file/open and the toolbar popup menus
buildMenu(openMenu);
@@ -359,6 +395,7 @@ public class Sketchbook {
"sketchbook menu. Things might get a little\n" +
"kooky around here.", e);
}
//EditorConsole.systemOut.println("done rebuilding menus");
}
@@ -444,25 +481,8 @@ public class Sketchbook {
if (list == null) return false;
// alphabetize list, since it's not always alpha order
// use cheapie bubble-style sort which should be fine
// since not a tone of files, and things will mostly be sorted
// or may be completely sorted already by the os
for (int i = 0; i < list.length; i++) {
int who = i;
for (int j = i+1; j < list.length; j++) {
if (list[j].compareToIgnoreCase(list[who]) < 0) {
who = j; // this guy is earlier in the alphabet
}
}
if (who != i) { // swap with someone if changes made
String temp = list[who];
list[who] = list[i];
list[i] = temp;
}
}
//SketchbookMenuListener listener =
//new SketchbookMenuListener(folder.getAbsolutePath());
// replaced hella slow bubble sort with this feller for 0093
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -477,18 +497,23 @@ public class Sketchbook {
list[i].equals("CVS")) continue;
File subfolder = new File(folder, list[i]);
File lib = new File(subfolder, "library");
if (!subfolder.isDirectory()) continue;
File entry = new File(subfolder, list[i] + ".pde");
// if a .pde file of the same prefix as the folder exists..
if (entry.exists()) {
String sanityCheck = sanitizedName(list[i]);
if (!sanityCheck.equals(list[i])) {
//String sanityCheck = sanitizedName(list[i]);
//if (!sanityCheck.equals(list[i])) {
if (!Sketchbook.isSanitary(list[i])) {
if (!builtOnce) {
String mess =
String complaining =
"The sketch \"" + list[i] + "\" cannot be used.\n" +
"Sketch names must contain only basic letters and numbers.\n" +
"(ascii only and no spaces, and it cannot start with a number)";
Base.showMessage("Ignoring bad sketch name", mess);
"Sketch names must contain only basic letters and numbers\n" +
"(ASCII-only with no spaces, " +
"and it cannot start with a number).\n" +
"To get rid of this message, remove the sketch from\n" +
entry.getAbsolutePath();
Base.showMessage("Ignoring sketch with bad name", complaining);
}
continue;
}
@@ -499,7 +524,8 @@ public class Sketchbook {
menu.add(item);
ifound = true;
} else { // might contain other dirs, get recursive
} else {
// not a sketch folder, but maybe a subfolder containing sketches
JMenu submenu = new JMenu(list[i]);
// needs to be separate var
// otherwise would set ifound to false
@@ -523,22 +549,8 @@ public class Sketchbook {
if (list == null) return false;
// alphabetize list, since it's not always alpha order
// use cheapie bubble-style sort which should be fine
// since not a tone of files, and things will mostly be sorted
// or may be completely sorted already by the os
for (int i = 0; i < list.length; i++) {
int who = i;
for (int j = i+1; j < list.length; j++) {
if (list[j].compareToIgnoreCase(list[who]) < 0) {
who = j; // this guy is earlier in the alphabet
}
}
if (who != i) { // swap with someone if changes made
String temp = list[who];
list[who] = list[i];
list[i] = temp;
}
}
// replaced hella slow bubble sort with this feller for 0093
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -591,6 +603,8 @@ public class Sketchbook {
String packages[] =
Compiler.packageListFromClassPath(libraryClassPath);
for (int k = 0; k < packages.length; k++) {
//System.out.println(packages[k] + " -> " + exported);
//String already = (String) importToLibraryTable.get(packages[k]);
importToLibraryTable.put(packages[k], exported);
}
*/
@@ -600,11 +614,10 @@ public class Sketchbook {
menu.add(item);
ifound = true;
} else { // might contain other dirs, get recursive
} else { // not a library, but is still a folder, so recurse
JMenu submenu = new JMenu(list[i]);
// needs to be separate var
// otherwise would set ifound to false
boolean found = addLibraries(submenu, subfolder); //, false);
// needs to be separate var, otherwise would set ifound to false
boolean found = addLibraries(submenu, subfolder);
if (found) {
menu.add(submenu);
ifound = true;

View File

@@ -30,7 +30,7 @@
package processing.app.preproc;
import processing.app.*;
//import processing.core.*;
import processing.core.*;
import java.io.*;
@@ -99,6 +99,7 @@ public class PdePreprocessor {
/**
* preprocesses a pde file and write out a java file
* @param pretty true if should also space out/indent lines
* @return the classname of the exported Java
*/
//public String write(String program, String buildPath, String name,
@@ -109,10 +110,19 @@ public class PdePreprocessor {
throws java.lang.Exception {
// if the program ends with no CR or LF an OutOfMemoryError will happen.
// not gonna track down the bug now, so here's a hack for it:
if ((program.length() > 0) &&
program.charAt(program.length()-1) != '\n') {
// bug filed at http://dev.processing.org/bugs/show_bug.cgi?id=5
//if ((program.length() > 0) &&
//program.charAt(program.length()-1) != '\n') {
program += "\n";
}
//}
// if the program ends with an unterminated multiline comment,
// an OutOfMemoryError or NullPointerException will happen.
// again, not gonna bother tracking this down, but here's a hack.
// http://dev.processing.org/bugs/show_bug.cgi?id=16
Sketch.scrubComments(program);
// this returns the scrubbed version, but more important for this
// function, it'll check to see if there are errors with the comments.
if (Preferences.getBoolean("preproc.substitute_unicode")) {
// check for non-ascii chars (these will be/must be in unicode format)
@@ -193,26 +203,6 @@ public class PdePreprocessor {
extraImports = new String[imports.size()];
imports.copyInto(extraImports);
// if using opengl, add it to the special imports
/*
if (Preferences.get("renderer").equals("opengl")) {
extraImports = new String[imports.size() + 1];
imports.copyInto(extraImports);
extraImports[extraImports.length - 1] = "processing.opengl.*";
}
*/
/*
if (codeFolderPackages != null) {
extraImports = new String[importsCount + codeFolderPackages.length];
imports.copyInto(extraImports);
for (int i = 0; i < codeFolderPackages.length; i++) {
extraImports[importsCount + i] = codeFolderPackages[i] + ".*";
}
codeFolderImports = null;
}
*/
if (codeFolderPackages != null) {
codeFolderImports = new String[codeFolderPackages.length];
for (int i = 0; i < codeFolderPackages.length; i++) {

View File

@@ -136,9 +136,10 @@ public abstract class InputHandler extends KeyAdapter
{
String name = (String)en.nextElement();
ActionListener _listener = getAction(name);
if(_listener == listener)
if(_listener == listener) {
return name;
}
}
return null;
}
@@ -180,7 +181,6 @@ public abstract class InputHandler extends KeyAdapter
/**
* Grabs the next key typed event and invokes the specified
* action with the key as a the action command.
* @param action The action
*/
public void grabNextKeyStroke(ActionListener listener)
{
@@ -743,19 +743,32 @@ public abstract class InputHandler extends KeyAdapter
{
JEditTextArea textArea = getTextArea(evt);
int caret = textArea.getCaretPosition();
if(caret == textArea.getDocumentLength())
{
if (textArea.getSelectionStart() !=
textArea.getSelectionEnd()) {
// just move to the end of the selection
textArea.select(caret, caret);
} else {
// beep at the user for being annoying
textArea.getToolkit().beep();
return;
}
if(select)
textArea.select(textArea.getMarkPosition(),
caret + 1);
else
} else if (select) {
textArea.select(textArea.getMarkPosition(), caret+1);
} else {
int start = textArea.getSelectionStart();
int end = textArea.getSelectionEnd();
if (start != end) {
textArea.select(end, end);
} else {
textArea.setCaretPosition(caret + 1);
}
}
}
}
public static class next_line implements ActionListener
{
@@ -774,7 +787,13 @@ public abstract class InputHandler extends KeyAdapter
if(line == textArea.getLineCount() - 1)
{
textArea.getToolkit().beep();
//textArea.getToolkit().beep();
int doc = textArea.getDocumentLength();
if (select) {
textArea.select(textArea.getMarkPosition(), doc);
} else {
textArea.setCaretPosition(doc);
}
return;
}
@@ -901,13 +920,19 @@ public abstract class InputHandler extends KeyAdapter
return;
}
if(select)
textArea.select(textArea.getMarkPosition(),
caret - 1);
else
if (select) {
textArea.select(textArea.getMarkPosition(), caret-1);
} else {
int start = textArea.getSelectionStart();
int end = textArea.getSelectionEnd();
if (start != end) {
textArea.select(start, start);
} else {
textArea.setCaretPosition(caret - 1);
}
}
}
}
public static class prev_line implements ActionListener
{
@@ -926,7 +951,14 @@ public abstract class InputHandler extends KeyAdapter
if(line == 0)
{
textArea.getToolkit().beep();
if (select) {
if (textArea.getSelectionStart() != 0) {
textArea.select(textArea.getMarkPosition(), 0);
}
} else {
textArea.setCaretPosition(0);
}
//textArea.getToolkit().beep();
return;
}

View File

@@ -888,22 +888,20 @@ public class JEditTextArea extends JComponent
*/
public void setText(String text)
{
try
{
try {
document.beginCompoundEdit();
document.remove(0,document.getLength());
document.insertString(0,text,null);
}
catch(BadLocationException bl)
{
} catch (BadLocationException bl) {
bl.printStackTrace();
}
finally
{
} finally {
document.endCompoundEdit();
}
}
/**
* Returns the specified substring of the document.
* @param start The start offset
@@ -1502,7 +1500,7 @@ public class JEditTextArea extends JComponent
/**
* Sets if the selection should be rectangular.
* @param overwrite True if the selection should be rectangular,
* @param rectSelect True if the selection should be rectangular,
* false otherwise.
*/
public final void setSelectionRectangular(boolean rectSelect)
@@ -1644,6 +1642,7 @@ public class JEditTextArea extends JComponent
switch(evt.getID()) {
case KeyEvent.KEY_TYPED:
//if ((editorListener != null) && !editorListener.keyTyped(evt)) {
inputHandler.keyTyped(evt);
break;
case KeyEvent.KEY_PRESSED:
@@ -2145,21 +2144,52 @@ public class JEditTextArea extends JComponent
bl.printStackTrace();
}
// Ok, it's not a bracket... select the word
String lineText = getLineText(line);
char ch = lineText.charAt(Math.max(0,offset - 1));
String noWordSep = (String)document.getProperty("noWordSep");
if(noWordSep == null)
noWordSep = "";
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = (!Character
.isLetterOrDigit(ch)
&& noWordSep.indexOf(ch) == -1);
// Ok, it's not a bracket... select the word
String lineText = getLineText(line);
int wordStart = 0;
int wordEnd = lineText.length();
char ch = lineText.charAt(Math.max(0,offset - 1));
// special case for whitespace (fry 0122, bug #348)
// this is really nasty.. turns out that double-clicking any non-letter
// or digit char gets lumped together.. sooo, this quickly gets messy,
// because really it needs to check whether the chars are of the same
// type.. so a double space or double - might be grouped together,
// but what about a +=1? do + and - get grouped but not the 1? blech,
// coming back to this later. it's not a difficult fix, just a
// time-consuming one to track down all the proper cases.
/*
if (ch == ' ') {
//System.out.println("yeehaa");
for(int i = offset - 1; i >= 0; i--) {
if (lineText.charAt(i) == ' ') {
wordStart = i;
} else {
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
if (lineText.charAt(i) == ' ') {
wordEnd = i + 1;
} else {
break;
}
}
} else {
*/
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
&& noWordSep.indexOf(ch) == -1);
for(int i = offset - 1; i >= 0; i--) {
ch = lineText.charAt(i);
@@ -2170,18 +2200,15 @@ public class JEditTextArea extends JComponent
}
}
int wordEnd = lineText.length();
for(int i = offset; i < lineText.length(); i++)
{
for(int i = offset; i < lineText.length(); i++) {
ch = lineText.charAt(i);
if(selectNoLetter ^ (!Character
.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1))
{
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordEnd = i;
break;
}
}
//}
int lineStart = getLineStartOffset(line);
select(lineStart + wordStart,lineStart + wordEnd);

View File

@@ -76,7 +76,7 @@ public class KeywordMap
/**
* Adds a key-value mapping.
* @param keyword The key
* @Param id The value
* @param id The value
*/
public void add(String keyword, byte id)
{

View File

@@ -76,7 +76,7 @@ public class PdeKeywords extends CTokenMarker {
}
}
String pieces[] = Base.split(line, '\t');
String pieces[] = processing.core.PApplet.split(line, '\t');
if (pieces.length >= 2) {
//int tab = line.indexOf('\t');
// any line with no tab is ignored

View File

@@ -2,9 +2,9 @@
/*
PdeTextAreaDefaults - grabs font/color settings for the editor
Part of the Processing project - http://Proce55ing.net
Part of the Processing project - http://processing.org
Except where noted, code is written by Ben Fry
Copyright (c) 2004-06 Ben Fry and Casey Reas
Copyright (c) 2001-03 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
@@ -32,41 +32,65 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
public PdeTextAreaDefaults() {
inputHandler = new DefaultInputHandler();
inputHandler.addDefaultKeyBindings();
//inputHandler.addDefaultKeyBindings(); // 0122
// use option on mac for things that are ctrl on windows/linux
String mod = Base.isMacOS() ? "A" : "C";
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
// right now, ctrl-up/down is select up/down, but mod should be
// used instead, because the mac expects it to be option(alt)
inputHandler.addKeyBinding("BACK_SPACE", InputHandler.BACKSPACE);
inputHandler.addKeyBinding("C+BACK_SPACE", InputHandler.BACKSPACE_WORD);
inputHandler.addKeyBinding("DELETE", InputHandler.DELETE);
inputHandler.addKeyBinding("C+DELETE", InputHandler.DELETE_WORD);
inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
//inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.BACKSPACE);
// for 0122, shift-backspace is delete
inputHandler.addKeyBinding("S+BACK_SPACE", InputHandler.DELETE);
inputHandler.addKeyBinding("S+DELETE", InputHandler.DELETE);
// the following two were changing for 0122 for better mac/pc compatability
inputHandler.addKeyBinding(mod+"+BACK_SPACE", InputHandler.BACKSPACE_WORD);
inputHandler.addKeyBinding(mod+"+DELETE", InputHandler.DELETE_WORD);
// handled by listener, don't bother here
//inputHandler.addKeyBinding("ENTER", InputHandler.INSERT_BREAK);
//inputHandler.addKeyBinding("TAB", InputHandler.INSERT_TAB);
inputHandler.addKeyBinding("INSERT", InputHandler.OVERWRITE);
inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
// disabling for 0122, not sure what this does
//inputHandler.addKeyBinding("C+\\", InputHandler.TOGGLE_RECT);
// beginning and ending of the current line
// for 0122, these have been changed for better compatability
// HOME and END now mean the beginning/end of the document
if (Base.isMacOS()) {
inputHandler.addKeyBinding("HOME", InputHandler.DOCUMENT_HOME);
inputHandler.addKeyBinding("END", InputHandler.DOCUMENT_END);
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_DOC_HOME);
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_DOC_END);
} else {
// for 0123 added the proper windows defaults
inputHandler.addKeyBinding("HOME", InputHandler.HOME);
inputHandler.addKeyBinding("END", InputHandler.END);
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_HOME);
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_END);
inputHandler.addKeyBinding("C+HOME", InputHandler.DOCUMENT_HOME);
inputHandler.addKeyBinding("C+END", InputHandler.DOCUMENT_END);
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_DOC_HOME);
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_DOC_END);
}
if (Base.isMacOS()) {
inputHandler.addKeyBinding("M+LEFT", InputHandler.HOME);
inputHandler.addKeyBinding("M+RIGHT", InputHandler.END);
inputHandler.addKeyBinding("MS+LEFT", InputHandler.SELECT_HOME); // 0122
inputHandler.addKeyBinding("MS+RIGHT", InputHandler.SELECT_END); // 0122
} else {
inputHandler.addKeyBinding("C+LEFT", InputHandler.HOME); // 0122
inputHandler.addKeyBinding("C+RIGHT", InputHandler.END); // 0122
inputHandler.addKeyBinding("CS+HOME", InputHandler.SELECT_HOME); // 0122
inputHandler.addKeyBinding("CS+END", InputHandler.SELECT_END); // 0122
}
inputHandler.addKeyBinding("S+HOME", InputHandler.SELECT_HOME);
inputHandler.addKeyBinding("S+END", InputHandler.SELECT_END);
inputHandler.addKeyBinding(mod + "+HOME", InputHandler.DOCUMENT_HOME);
inputHandler.addKeyBinding(mod + "+END", InputHandler.DOCUMENT_END);
inputHandler.addKeyBinding(mod + "S+HOME", InputHandler.SELECT_DOC_HOME);
inputHandler.addKeyBinding(mod + "S+END", InputHandler.SELECT_DOC_END);
inputHandler.addKeyBinding("PAGE_UP", InputHandler.PREV_PAGE);
inputHandler.addKeyBinding("PAGE_DOWN", InputHandler.NEXT_PAGE);
inputHandler.addKeyBinding("S+PAGE_UP", InputHandler.SELECT_PREV_PAGE);
@@ -80,6 +104,7 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
inputHandler.addKeyBinding("S+RIGHT", InputHandler.SELECT_NEXT_CHAR);
inputHandler.addKeyBinding(mod + "+RIGHT", InputHandler.NEXT_WORD);
inputHandler.addKeyBinding(mod + "S+RIGHT", InputHandler.SELECT_NEXT_WORD);
inputHandler.addKeyBinding("UP", InputHandler.PREV_LINE);
inputHandler.addKeyBinding(mod + "+UP", InputHandler.PREV_LINE); // p5
inputHandler.addKeyBinding("S+UP", InputHandler.SELECT_PREV_LINE);
@@ -87,6 +112,11 @@ public class PdeTextAreaDefaults extends TextAreaDefaults {
inputHandler.addKeyBinding(mod + "+DOWN", InputHandler.NEXT_LINE); // p5
inputHandler.addKeyBinding("S+DOWN", InputHandler.SELECT_NEXT_LINE);
inputHandler.addKeyBinding("MS+UP", InputHandler.SELECT_DOC_HOME);
inputHandler.addKeyBinding("CS+UP", InputHandler.SELECT_DOC_HOME);
inputHandler.addKeyBinding("MS+DOWN", InputHandler.SELECT_DOC_END);
inputHandler.addKeyBinding("CS+DOWN", InputHandler.SELECT_DOC_END);
inputHandler.addKeyBinding(mod + "+ENTER", InputHandler.REPEAT);
document = new SyntaxDocument();

View File

@@ -18,6 +18,7 @@ import javax.swing.text.*;
import javax.swing.JComponent;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.print.*;
/**
* The text area repaint manager. It performs double buffering and paints
@@ -25,8 +26,12 @@ import java.awt.*;
* @author Slava Pestov
* @version $Id$
*/
public class TextAreaPainter extends JComponent implements TabExpander
public class TextAreaPainter extends JComponent
implements TabExpander, Printable
{
/** True if inside printing, will handle disabling the highlight */
boolean printing;
/**
* Creates a new repaint manager. This should be not be called
* directly.
@@ -405,6 +410,32 @@ public class TextAreaPainter extends JComponent implements TabExpander
}
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
int lineHeight = fm.getHeight();
int linesPerPage = (int) (pageFormat.getImageableHeight() / lineHeight);
int lineCount = textArea.getLineCount();
int lastPage = lineCount / linesPerPage;
if (pageIndex > lastPage) {
return NO_SUCH_PAGE;
} else {
Graphics2D g2d = (Graphics2D)g;
TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();
int firstLine = pageIndex*linesPerPage;
g2d.translate(Math.max(54, pageFormat.getImageableX()),
pageFormat.getImageableY() - firstLine*lineHeight);
printing = true;
for (int line = firstLine; line < firstLine + linesPerPage; line++) {
paintLine(g2d, tokenMarker, line, 0);
}
printing = false;
return PAGE_EXISTS;
}
}
/**
* Marks a line as needing a repaint.
* @param line The line to invalidate
@@ -600,6 +631,7 @@ public class TextAreaPainter extends JComponent implements TabExpander
protected void paintHighlight(Graphics gfx, int line, int y)
{
if (!printing) {
if (line >= textArea.getSelectionStartLine()
&& line <= textArea.getSelectionEndLine())
paintLineHighlight(gfx,line,y);
@@ -613,6 +645,7 @@ public class TextAreaPainter extends JComponent implements TabExpander
if (line == textArea.getCaretLine())
paintCaret(gfx,line,y);
}
}
protected void paintLineHighlight(Graphics gfx, int line, int y)
{

View File

@@ -25,6 +25,7 @@ package processing.app.tools;
import processing.app.*;
import java.awt.FileDialog;
import java.io.*;
import java.text.*;
import java.util.*;
@@ -35,7 +36,7 @@ public class Archiver {
Editor editor;
// someday these will be settable
boolean useDate = true; //false;
boolean useDate;
int digits = 3;
NumberFormat numberFormat;
@@ -79,6 +80,9 @@ public class Archiver {
String namely = null;
int index = 0;
do {
// only use the date if the sketch name isn't the default name
useDate = !name.startsWith("sketch_");
if (useDate) {
String purty = dateFormat.format(new Date());
String stamp = purty + ((char) ('a' + index));
@@ -93,6 +97,20 @@ public class Archiver {
index++;
} while (newbie.exists());
// open up a prompt for where to save this fella
FileDialog fd =
new FileDialog(editor, "Archive sketch as:", FileDialog.SAVE);
fd.setDirectory(parent.getAbsolutePath());
fd.setFile(newbie.getName());
fd.show();
String directory = fd.getDirectory();
String filename = fd.getFile();
// only write the file if not canceled
if (filename != null) {
newbie = new File(directory, filename);
try {
//System.out.println(newbie);
FileOutputStream zipOutputFile = new FileOutputStream(newbie);
@@ -110,6 +128,9 @@ public class Archiver {
} catch (IOException e) {
e.printStackTrace();
}
} else {
editor.message("Archive sketch canceled.");
}
}

View File

@@ -24,7 +24,7 @@
package processing.app.tools;
import processing.app.*;
//import processing.core.*;
import processing.core.*;
import java.io.*;
import java.util.StringTokenizer;
@@ -915,26 +915,25 @@ public class AutoFormat {
if (formattedText.equals(originalText)) {
editor.message("No changes necessary for Auto Format.");
} else {
// replace with new bootiful text
// selectionEnd hopefully at least in the neighborhood
editor.setText(formattedText, selectionEnd, selectionEnd);
editor.sketch.setModified(true);
} else if (paren != 0) {
// warn user if there are too many parens in either direction
if (paren != 0) {
editor.error("Warning: Too many " +
editor.error("Auto Format Canceled: Too many " +
((paren < 0) ? "right" : "left") +
" parentheses.");
} else if (c_level != 0) { // check braces only if parens are ok
editor.error("Warning: Too many " +
editor.error("Auto Format Canceled: Too many " +
((c_level < 0) ? "right" : "left") +
" curly braces.");
} else {
// replace with new bootiful text
// selectionEnd hopefully at least in the neighborhood
editor.setText(formattedText, selectionEnd, selectionEnd);
editor.sketch.setModified(true);
// mark as finished
editor.message("Auto Format finished.");
}
}
} catch (Exception e) {
editor.error(e);

View File

@@ -0,0 +1,313 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2005-06 Ignacio Manuel Gonz<6E>lez Moreta
Copyright (c) 2006 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.tools;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.Segment;
import processing.app.*;
import processing.app.syntax.*;
import processing.core.PApplet;
/**
* Format for Discourse Tool
* <p/>
* Original code by <A HREF="http://usuarios.iponet.es/imoreta">owd</A>.
* Revised and updated for revision 0108 by Ben Fry (10 March 2006).
* This code will later be removed but is included with release 0108+
* while features for the "Tools" menu are in testing.
* <p/>
* Updated for 0122 to simply copy the code directly to the clipboard,
* rather than opening a new window.
* <p/>
* Notes from the original source:
* Discourse.java This is a dirty-mix source.
* NOTE that: No macs and no keyboard. Unreliable source.
* Only format processing code using fontMetrics.
* It works under my windows XP + PentiumIV + Processing 0091.
*/
public class DiscourseFormat {
//static final String WINDOW_TITLE = "Format for Discourse by owd";
// p5 icon for the window
//static Image icon;
Editor editor;
//JEditTextArea textarea;
// JTextArea of the actual Editor
JEditTextArea parent;
//JFrame frame;
/**
* Creates a new window with the formated (YaBB tags) sketchcode
* from the actual Processing Tab ready to send to the processing discourse
* web (copy & paste)
*/
public DiscourseFormat(Editor editor) {
this.editor = editor;
this.parent = editor.textarea;
/*
textarea = new JEditTextArea(new PdeTextAreaDefaults());
textarea.setRightClickPopup(new DiscourseTextAreaPopup());
textarea.setTokenMarker(new PdeKeywords());
textarea.setHorizontalOffset(6);
textarea.setEditable(false);
// Create and set up the window.
frame = new JFrame(WINDOW_TITLE);
frame.setSize(500, 500);
// set the window icon
try {
icon = Base.getImage("icon.gif", frame);
frame.setIconImage(icon);
} catch (Exception e) { } // fail silently, no big whup
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Container pain = frame.getContentPane();
pain.setLayout(new BorderLayout());
pain.add(textarea, BorderLayout.CENTER);
frame.setResizable(true);
frame.pack();
frame.setLocation(100, 100);
//frame.setVisible(true);
*/
}
public void show() {
// Format and render sketchcode
// [code] tag cancels other tags, using [quote]
StringBuffer cf = new StringBuffer("[quote] \n \n");
// Line by line
for (int i = 0; i < parent.getLineCount(); i++) {
cf.append(formatCode(i));
}
cf.append("\n [/quote]");
/*
// Send the text to the textarea
textarea.setText(cf.toString());
textarea.select(0, 0);
frame.show();
*/
StringSelection formatted = new StringSelection(cf.toString());
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(formatted, new ClipboardOwner() {
public void lostOwnership(Clipboard clipboard, Transferable contents) {
// i don't care about ownership
}
});
editor.message("Discourse-formatted code has been " +
"copied to the clipboard.");
}
// A terrible headache...
public String formatCode(int line) {
StringBuffer cf = new StringBuffer();
// Segment
Segment lineSegment = new Segment();
TextAreaPainter painter = parent.getPainter();
TokenMarker tokenMarker = parent.getTokenMarker();
// Use painter's cached info for speed
FontMetrics fm = painter.getFontMetrics();
// get line text from parent textarea
parent.getLineText(line, lineSegment);
char[] segmentArray = lineSegment.array;
int limit = lineSegment.getEndIndex();
int segmentOffset = lineSegment.offset;
int segmentCount = lineSegment.count;
int width = 0; //parent.getHorizontalOffset();
int x = 0; //parent.getHorizontalOffset();
// If syntax coloring is disabled, do simple translation
if (tokenMarker == null) {
for (int j = 0; j < segmentCount; j++) {
char c = segmentArray[j + segmentOffset];
cf = cf.append(c); //concat(character(c));
int charWidth;
if (c == '\t') {
charWidth = (int) painter.nextTabStop(width, j) - width;
} else {
charWidth = fm.charWidth(c);
}
width += charWidth;
}
} else {
// If syntax coloring is enabled, we have to do this
// because tokens can vary in width
Token tokens;
if ((painter.getCurrentLineIndex() == line) &&
(painter.getCurrentLineTokens() != null)) {
tokens = painter.getCurrentLineTokens();
} else {
painter.setCurrentLineIndex(line);
//painter.currentLineIndex = line;
painter.setCurrentLineTokens(tokenMarker.markTokens(lineSegment, line));
tokens = painter.getCurrentLineTokens();
}
int offset = 0;
Toolkit toolkit = painter.getToolkit();
Font defaultFont = painter.getFont();
SyntaxStyle[] styles = painter.getStyles();
for (;;) {
byte id = tokens.id;
if (id == Token.END) {
char c = segmentArray[segmentOffset + offset];
if (segmentOffset + offset < limit) {
cf.append(c);
} else {
cf.append('\n');
}
return cf.toString();
}
if (id == Token.NULL) {
fm = painter.getFontMetrics();
} else {
// Place open tags []
//cf.append("[color=" + color() + "]");
cf.append("[color=#");
cf.append(PApplet.hex(styles[id].getColor().getRGB() & 0xFFFFFF, 6));
cf.append("]");
if (styles[id].isBold())
cf.append("[b]");
fm = styles[id].getFontMetrics(defaultFont);
}
int length = tokens.length;
for (int j = 0; j < length; j++) {
char c = segmentArray[segmentOffset + offset + j];
cf.append(c);
// Place close tags [/]
if (j == (length - 1) && id != Token.NULL && styles[id].isBold())
cf.append("[/b]");
if (j == (length - 1) && id != Token.NULL)
cf.append("[/color]");
int charWidth;
if (c == '\t') {
charWidth = (int) painter
.nextTabStop(width, offset + j)
- width;
} else {
charWidth = fm.charWidth(c);
}
width += charWidth;
}
offset += length;
tokens = tokens.next;
}
}
return cf.toString();
}
/**
* Returns the discourse popup menu. Another features can be added: format
* selected text with a determinated tag (I'm thinking about [url]selected
* text[/url])
*/
/*
class DiscourseTextAreaPopup extends JPopupMenu {
JMenuItem copyItem;
public DiscourseTextAreaPopup() {
JMenuItem item;
copyItem = new JMenuItem("Copy");
copyItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textarea.copy();
}
});
this.add(copyItem);
item = new JMenuItem("Select All");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textarea.selectAll();
}
});
this.add(item);
}
// if no text is selected, disable copy menu item
public void show(Component component, int x, int y) {
if (textarea.isSelectionActive()) {
copyItem.setEnabled(true);
} else {
copyItem.setEnabled(false);
}
super.show(component, x, y);
}
}
*/
/*
// A false listener (use the mouse)
public class DiscourseListener {
public DiscourseListener(JEditTextArea thisTextarea) {
// I'm a... I know this gives peoblems, but all this code
// is a funny hacking experiment
thisTextarea.editorListener = parent.editorListener;
}
public boolean keyPressed(KeyEvent event) {
System.out.println("Is your mouse lone some tonight...");
return false;
}
}
*/
}

View File

@@ -99,6 +99,8 @@ public class ExportFolder {
// skip .DS_Store files, etc
if (!folder.isDirectory()) return; // false;
System.out.println(folder.getAbsolutePath());
String list[] = folder.list();
// if a bad folder or something like that, this might come back null
if (list == null) return; // false;