diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 86f716230..ad86abcb1 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -55,11 +55,9 @@ public class Base { boolean builtOnce; // these are static because they're used by Sketch - static File examplesFolder; - static String examplesPath; // canonical path (for comparison) - - static File librariesFolder; - static String librariesPath; + static private File examplesFolder; + static private File librariesFolder; + static private File toolsFolder; // maps imported packages to their library folder static Hashtable importToLibraryTable = new Hashtable(); @@ -152,10 +150,10 @@ public class Base { platform.init(this); // Get paths for the libraries and examples in the Processing folder - examplesFolder = new File(System.getProperty("user.dir"), "examples"); - examplesPath = examplesFolder.getAbsolutePath(); - librariesFolder = new File(System.getProperty("user.dir"), "libraries"); - librariesPath = librariesFolder.getAbsolutePath(); + String workingDirectory = System.getProperty("user.dir"); + examplesFolder = new File(workingDirectory, "examples"); + librariesFolder = new File(workingDirectory, "libraries"); + toolsFolder = new File(workingDirectory, "tools"); // Get the sketchbook path, and make sure it's set properly String sketchbookPath = Preferences.get("sketchbook.path"); @@ -663,7 +661,7 @@ public class Base { * Asynchronous version of menu rebuild to be used on save and rename * to prevent the interface from locking up until the menus are done. */ - public void rebuildSketchbookMenu() { + protected void rebuildSketchbookMenus() { //System.out.println("async enter"); //new Exception().printStackTrace(); SwingUtilities.invokeLater(new Runnable() { @@ -678,7 +676,7 @@ public class Base { } - public void rebuildToolbarMenu(JMenu menu) { + protected void rebuildToolbarMenu(JMenu menu) { JMenuItem item; menu.removeAll(); @@ -711,7 +709,7 @@ public class Base { } - public void rebuildSketchbookMenu(JMenu menu) { + protected void rebuildSketchbookMenu(JMenu menu) { //System.out.println("rebuilding sketchbook menu"); //new Exception().printStackTrace(); try { @@ -1074,12 +1072,32 @@ public class Base { } + static public String getExamplesPath() { + return examplesFolder.getAbsolutePath(); + } + + + static public String getLibrariesPath() { + return librariesFolder.getAbsolutePath(); + } + + + static public File getToolsFolder() { + return toolsFolder; + } + + + static public String getToolsPath() { + return toolsFolder.getAbsolutePath(); + } + + public File getSketchbookFolder() { return new File(Preferences.get("sketchbook.path")); } - - - public File getDefaultSketchbookFolder() { + + + protected File getDefaultSketchbookFolder() { File sketchbookFolder = null; try { sketchbookFolder = platform.getDefaultSketchbookFolder(); diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 56cd879db..0736c2e9d 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -34,6 +34,8 @@ import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.print.*; import java.io.*; +import java.net.*; +import java.util.*; import javax.swing.*; import javax.swing.event.*; @@ -607,9 +609,113 @@ public class Editor extends JFrame { protected JMenu buildToolsMenu() { - JMenuItem item; JMenu menu = new JMenu("Tools"); + addInternalTools(menu); + addTools(menu, Base.getToolsFolder()); + addTools(menu, base.getSketchbookFolder()); + System.out.println("done."); + + return menu; + } + + + protected void addTools(JMenu menu, File sourceFolder) { + HashMap toolItems = new HashMap(); + + File[] folders = sourceFolder.listFiles(new FileFilter() { + public boolean accept(File folder) { + if (folder.isDirectory()) { +// System.out.println("checking " + folder); + File subfolder = new File(folder, "tool"); + return subfolder.exists(); + } + return false; + } + }); + + if (folders == null || folders.length == 0) { + return; + } + + for (int i = 0; i < folders.length; i++) { + File toolDirectory = new File(folders[i], "tool"); + + try { + // add dir to classpath for .classes + //urlList.add(toolDirectory.toURL()); + + // add .jar files to classpath + File[] archives = toolDirectory.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return (name.toLowerCase().endsWith(".jar") || + name.toLowerCase().endsWith(".zip")); + } + }); + + URL[] urlList = new URL[archives.length]; + for (int j = 0; j < urlList.length; j++) { + urlList[j] = archives[j].toURL(); + } + URLClassLoader loader = new URLClassLoader(urlList); + + // Alternatively, could use manifest files with special attributes: + // http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html + // Example code for loading from a manifest file: + // http://forums.sun.com/thread.jspa?messageID=3791501 + File infoFile = new File(toolDirectory, "tool.txt"); + if (!infoFile.exists()) continue; + + String[] info = PApplet.loadStrings(infoFile); + //Main-Class: org.poo.shoe.AwesomerTool + //String className = folders[i].getName(); + String className = null; + for (int k = 0; k < info.length; k++) { + if (info[k].startsWith(";")) continue; + + String[] pieces = PApplet.splitTokens(info[k], ": "); + if (pieces.length == 2) { + if (pieces[0].equals("Main-Class")) { + className = pieces[1]; + } + } + } + // If no class name found, just move on. + if (className == null) continue; + + Class toolClass = Class.forName(className, true, loader); + final Tool tool = (Tool) toolClass.newInstance(); + + tool.init(Editor.this); + + String title = tool.getMenuTitle(); + JMenuItem item = new JMenuItem(title); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(tool); + } + }); + //menu.add(item); + toolItems.put(title, item); + + } catch (Exception e) { + e.printStackTrace(); + } + } + ArrayList toolList = new ArrayList(toolItems.keySet()); + if (toolList.size() == 0) return; + + menu.addSeparator(); + Collections.sort(toolList); + for (String title : toolList) { + menu.add((JMenuItem) toolItems.get(title)); + } + } + + + protected JMenu addInternalTools(JMenu menu) { + JMenuItem item; + item = newJMenuItem("Auto Format", 'T'); item.addActionListener(new ActionListener() { synchronized public void actionPerformed(ActionEvent e) { @@ -1634,97 +1740,109 @@ public class Editor extends JFrame { * modifications (if any) to the previous sketch need to be saved. */ protected boolean handleOpenInternal(String path) { - try { - // check to make sure that this .pde file is - // in a folder of the same name - File file = new File(path); - File parentFile = new File(file.getParent()); - String parentName = parentFile.getName(); - String pdeName = parentName + ".pde"; - File altFile = new File(file.getParent(), pdeName); + // check to make sure that this .pde file is + // in a folder of the same name + File file = new File(path); + File parentFile = new File(file.getParent()); + String parentName = parentFile.getName(); + String pdeName = parentName + ".pde"; + File altFile = new File(file.getParent(), pdeName); - if (pdeName.equals(file.getName())) { - // no beef with this guy + if (pdeName.equals(file.getName())) { + // no beef with this guy - } else if (altFile.exists()) { - // user selected a .java from the same sketch, - // but open the .pde instead - path = altFile.getAbsolutePath(); - //System.out.println("found alt file in same folder"); + } else if (altFile.exists()) { + // user selected a .java from the same sketch, + // but open the .pde instead + path = altFile.getAbsolutePath(); + //System.out.println("found alt file in same folder"); - } else if (!path.endsWith(".pde")) { - Base.showWarning("Bad file selected", - "Processing can only open its own sketches\n" + - "and other files ending in .pde", null); - return false; + } else if (!path.endsWith(".pde")) { + Base.showWarning("Bad file selected", + "Processing can only open its own sketches\n" + + "and other files ending in .pde", null); + return false; - } else { - String properParent = - file.getName().substring(0, file.getName().length() - 4); + } else { + String properParent = + file.getName().substring(0, file.getName().length() - 4); - Object[] options = { "OK", "Cancel" }; - String prompt = - "The file \"" + file.getName() + "\" needs to be inside\n" + - "a sketch folder named \"" + properParent + "\".\n" + - "Create this folder, move the file, and continue?"; + Object[] options = { "OK", "Cancel" }; + String prompt = + "The file \"" + file.getName() + "\" needs to be inside\n" + + "a sketch folder named \"" + properParent + "\".\n" + + "Create this folder, move the file, and continue?"; - int result = JOptionPane.showOptionDialog(this, - prompt, - "Moving", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0]); + int result = JOptionPane.showOptionDialog(this, + prompt, + "Moving", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[0]); - if (result == JOptionPane.YES_OPTION) { - // create properly named folder - File properFolder = new File(file.getParent(), properParent); - if (properFolder.exists()) { - Base.showWarning("Error", - "A folder named \"" + properParent + "\" " + - "already exists. Can't open sketch.", null); - return false; - } - if (!properFolder.mkdirs()) { - throw new IOException("Couldn't create sketch folder"); - } - // copy the sketch inside - File properPdeFile = new File(properFolder, file.getName()); - File origPdeFile = new File(path); - Base.copyFile(origPdeFile, properPdeFile); - - // remove the original file, so user doesn't get confused - origPdeFile.delete(); - - // update with the new path - path = properPdeFile.getAbsolutePath(); - - } else if (result == JOptionPane.NO_OPTION) { + if (result == JOptionPane.YES_OPTION) { + // create properly named folder + File properFolder = new File(file.getParent(), properParent); + if (properFolder.exists()) { + Base.showWarning("Error", + "A folder named \"" + properParent + "\" " + + "already exists. Can't open sketch.", null); return false; } + if (!properFolder.mkdirs()) { + //throw new IOException("Couldn't create sketch folder"); + Base.showWarning("Error", + "Could not create the sketch folder.", null); + return false; + } + // copy the sketch inside + File properPdeFile = new File(properFolder, file.getName()); + File origPdeFile = new File(path); + try { + Base.copyFile(origPdeFile, properPdeFile); + } catch (IOException e) { + Base.showWarning("Error", "Could not copy to a proper location.", e); + return false; + } + + // remove the original file, so user doesn't get confused + origPdeFile.delete(); + + // update with the new path + path = properPdeFile.getAbsolutePath(); + + } else if (result == JOptionPane.NO_OPTION) { + return false; } + } + try { sketch = new Sketch(this, path); - header.rebuild(); - // Set the title of the window to "sketch_070752a - Processing 0126" - setTitle(sketch.getName() + " | " + WINDOW_TITLE); - // Disable untitled setting from previous document, if any - untitled = false; - - // Store information on who's open and running - // (in case there's a crash or something that can't be recovered) - base.storeSketches(); - Preferences.save(); - - // opening was successful - return true; - - } catch (Exception e) { - e.printStackTrace(); - statusError(e); + } catch (IOException e) { + Base.showWarning("Error", "Could not create the sketch.", e); return false; } + header.rebuild(); + // Set the title of the window to "sketch_070752a - Processing 0126" + setTitle(sketch.getName() + " | " + WINDOW_TITLE); + // Disable untitled setting from previous document, if any + untitled = false; + + // Store information on who's open and running + // (in case there's a crash or something that can't be recovered) + base.storeSketches(); + Preferences.save(); + + // opening was successful + return true; + +// } catch (Exception e) { +// e.printStackTrace(); +// statusError(e); +// return false; +// } } diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 471bf3fd3..7434e3542 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -177,8 +177,8 @@ public class Sketch { code = new SketchCode[list.length]; //codeCount]; hidden = new SketchCode[list.length]; //hiddenCount]; - int codeCounter = 0; - int hiddenCounter = 0; +// int codeCounter = 0; +// int hiddenCounter = 0; String[] extensions = getExtensions(); @@ -211,10 +211,10 @@ public class Sketch { // it would be otherwise possible to sneak in nasty filenames. [0116] if (Sketch.isSanitaryName(base)) { if (hiddenX) { - hidden[hiddenCounter++] = + hidden[hiddenCount++] = new SketchCode(new File(folder, filename), extension); } else { - code[codeCounter++] = + code[codeCount++] = new SketchCode(new File(folder, filename), extension); } } @@ -222,13 +222,14 @@ public class Sketch { } } - codeCount = codeCounter; +// codeCount = codeCounter; // some of the hidden files may be bad too, so use hiddenCounter // added for rev 0121, fixes bug found by axel - hiddenCount = hiddenCounter; - - code = (SketchCode[]) PApplet.subset(0, codeCount); - hidden = (SketchCode[]) PApplet.subset(0, hiddenCount); +// hiddenCount = hiddenCounter; + +// System.out.println(codeCount + " " + hiddenCount); + code = (SketchCode[]) PApplet.subset(code, 0, codeCount); + hidden = (SketchCode[]) PApplet.subset(hidden, 0, hiddenCount); // remove any entries that didn't load properly from codeCount // int index = 0; @@ -532,7 +533,7 @@ public class Sketch { // get the changes into the sketchbook menu // (re-enabled in 0115 to fix bug #332) - editor.base.rebuildSketchbookMenu(); + editor.base.rebuildSketchbookMenus(); } else { // else if something besides code[0] if (!current.renameTo(newFile, newExtension)) { @@ -1005,7 +1006,7 @@ public class Sketch { // Name changed, rebuild the sketch menus //editor.sketchbook.rebuildMenusAsync(); - editor.base.rebuildSketchbookMenu(); + editor.base.rebuildSketchbookMenus(); // Make sure that it's not an untitled sketch setUntitled(false); @@ -2762,8 +2763,8 @@ public class Sketch { */ public boolean isReadOnly() { String apath = folder.getAbsolutePath(); - if (apath.startsWith(Base.examplesPath) || - apath.startsWith(Base.librariesPath)) { + if (apath.startsWith(Base.getExamplesPath()) || + apath.startsWith(Base.getLibrariesPath())) { return true; // canWrite() doesn't work on directories diff --git a/app/src/processing/app/tools/ColorSelector.java b/app/src/processing/app/tools/ColorSelector.java index 78e2a6edf..3f63c5164 100644 --- a/app/src/processing/app/tools/ColorSelector.java +++ b/app/src/processing/app/tools/ColorSelector.java @@ -3,7 +3,7 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2006 Ben Fry and Casey Reas + Copyright (c) 2006-08 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 @@ -40,12 +40,6 @@ import javax.swing.text.*; * colors and paste them into your program. We didn't do any sort of * auto-insert of colorMode() or fill() or stroke() code cuz we couldn't * decide on a good way to do this.. your contributions welcome). - *

- * There is currently a bug that causes the drawing area to show up - * slightly large on Windows and Linux. This is an annoyance but less - * important than me fixing some other stuff. If someone were to track - * down what's going wrong, I'd be super grateful. - * (Bug 310) */ public class ColorSelector implements DocumentListener { @@ -137,8 +131,8 @@ public class ColorSelector implements DocumentListener { public void show() { frame.setVisible(true); - // You've got to be f--ing kidding me.. why did the following line get - // deprecated in the pile of s-- that follows it? + // You've got to be f--ing kidding me.. why did the following line + // get deprecated for the pile of s-- that follows it? //frame.setCursor(Cursor.CROSSHAIR_CURSOR); frame.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); } diff --git a/app/src/processing/app/tools/Tool.java b/app/src/processing/app/tools/Tool.java new file mode 100644 index 000000000..7278452e0 --- /dev/null +++ b/app/src/processing/app/tools/Tool.java @@ -0,0 +1,44 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Tool - interface implementation for the Processing tools menu + Part of the Processing project - http://processing.org + + Copyright (c) 2008 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.tools; + +import processing.app.Editor; + + +/** + * Interface for items to be shown in the Tools menu. + */ +public interface Tool extends Runnable { + + public void init(Editor editor); + + public void run(); + + // Not doing shortcuts for now, no way to resolve between tools. + // Also would need additional modifiers for shift and alt. + //public char getShortcutKey(); + + public String getMenuTitle(); +} + diff --git a/todo.txt b/todo.txt index d8a188038..60314f592 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,59 @@ 0147 pde +X inside Sketch.java, don't hardwire the file extension types +X arduino uses .c, .cpp, .h instead of .java +X http://dev.processing.org/bugs/show_bug.cgi?id=807 + +tools +_ refactor code to use more getter/setter methods +X move the debug classes back into processing.app.debug +X this will help the library stuff +X dynamic tools menu (requires moving files around) +o this means can integrate the autoformat stuff +_ processing.mess/tools has chandler's template stuff +_ don't open more than one "create font" or "color selector" +_ http://dev.processing.org/bugs/show_bug.cgi?id=830 +o need to write converter that will handle syntax changes +o convert from alpha to 1.0 syntax +o framerate() -> frameRate() +o basically find & replace with regexps +o acts just like find/replace.. go through and do by hand +o 3 column input file +o regexp to find, to replace, human readable description +o (void\s+)loop(\s+{) -> $1draw$2 (maintain all whitespace stuff) +o "The loop() method is now called draw() as of beta" +o "angleMode no longer exists, use radians() around your angles" +o (comment out the line) +X this would only fix the minor stuff, not the important stuff +X it also has a lot of potential problems and corner cases +X just not worth the effort +X tools api +X need to support the basic set of functions that are expected +X to be used, otherwise it's gonna be total hell when we make a real api +X getEditor() +X get/setSelStart/End +X get/setSelText +X get/setText +_ setCurrentTab(int index or String filename) +_ getTabs() ? maybe these are interface to the code class +_ clean up API for JEditTextArea before exposing the object +X make dynamically loaded plugins and "tools" menu +X http://dev.processing.org/bugs/show_bug.cgi?id=124 +X tools api: +X init() -> run when p5 is first launched +o isAvailable() -> true/false whether the option should be dimmed +X skip this for now, not sending events to tools all the time +o show() and hide() -> open the window or run the tool +o is there a better name than show() since not all will be visible? +o maybe it's just a run() method launched via invokeLater()? +X can't really do show/hide from editor, make the tool handle this +o getDefaultShortcut() -> returns the default shortcut this tools wants +o store this in the data file instead +X not bothering with this for now, since can't handle overlaps +X needs to be able to get current sketch code +X look at the pretty-formatting code to see what else needs to be in api +o getMenu() -> return non-null the tool is a submenu +X no, bad idea.. don't want a zillion submenus on things +_ write basic documentation for how it's handled _ use macosx dialogs for all of the editor stuff @@ -143,6 +198,20 @@ _ set DYLD_LIBRARY_PATH to include .dylib and other framework stuff _ java.library.path will only handle .jnilib stuff _ need better error messages for broken api / library troubles _ e.g. ocd is broken in 0125 because of method signature changes +_ could have library developers update compatability note +_ so they would need to test library and say "compatible with 0110" +_ before it would automatically update or show as an update +_ tools -> get library +_ library url: [ http://blahblah.org/something ] +_ this would grab something.version, and something.zip +_ maybe something.xml that would include a bunch of background +_ tools -> update libraries +_ this would check the something.version to see if it's newer +_ document how to add libraries: put in sketchbook (not libraries folder) +_ library/download.url and library/home.url +_ if there's a reference subfolder, add that to the help menu +o and enable it for "find in reference" +X nice idea but too error-prone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @@ -857,9 +926,6 @@ _ need to set dock icon title on osx PDE / Sketch & Sketchbook -_ inside Sketch.java, don't hardwire the file extension types -_ arduino uses .c, .cpp, .h instead of .java -_ http://dev.processing.org/bugs/show_bug.cgi?id=807 _ don't reload sketch on "save as" _ this can result in loss of data (undo is lost) _ http://dev.processing.org/bugs/show_bug.cgi?id=433 @@ -919,61 +985,16 @@ _ maybe just open from a zip file, since psk doesn't help anything TOOLS / General -_ refactor code to use more getter/setter methods -_ move the debug classes back into processing.app.debug -_ this will help the library stuff -_ dynamic tools menu (requires moving files around) -_ this means can integrate the autoformat stuff -_ processing.mess/tools has chandler's template stuff -_ don't open more than one "create font" or "color selector" -_ http://dev.processing.org/bugs/show_bug.cgi?id=830 -_ need to write converter that will handle syntax changes -_ basically find & replace with regexps -_ framerate() -> frameRate() -_ convert from alpha to 1.0 syntax -_ acts just like find/replace.. go through and do by hand -_ 3 column input file -_ regexp to find, to replace, human readable description -_ (void\s+)loop(\s+{) -> $1draw$2 (maintain all whitespace stuff) -_ "The loop() method is now called draw() as of beta" -_ "angleMode no longer exists, use radians() around your angles" -_ (comment out the line) -_ tools -> shared code -_ Integrator / FloatThing / CameraStuff -- Update -_ to pull code from a local folder -_ update will update classes from shared in the current folder -_ tools api -_ need to support the basic set of functions that are expected -_ to be used, otherwise it's gonna be total hell when we make a real api -_ getEditor() -_ get/setSelStart/End -_ get/setSelText -_ get/setText -_ setCurrentTab(int index or String filename) -_ getTabs() ? maybe these are interface to the code class -_ clean up API for JEditTextArea before exposing the object -_ need method for showing prefs for the tools -_ add pref to handle date vs. increment on archive sketch -_ make dynamically loaded plugins and "tools" menu -_ http://dev.processing.org/bugs/show_bug.cgi?id=124 -_ break out beautify as its own plugin -_ tools api: -_ init() -> run when p5 is first launched -_ isAvailable() -> true/false whether the option should be dimmed -_ skip this for now, not sending events to tools all the time -_ show() -> open the window or run the tool -_ is there a better name than show() since not all will be visible? -_ maybe it's just a run() method launched via invokeLater()? -_ hide() -> hide the tool's frame -_ getDefaultShortcut() -> returns the default shortcut this tools wants -_ store this in the data file instead -_ needs to be able to get current sketch code -_ look at the pretty-formatting code to see what else needs to be in api -o getMenu() -> return non-null the tool is a submenu -o no, bad idea.. don't want a zillion submenus on things -_ need a proper means to handle command keys for tools +_ need a proper means to handle command keys for tools (?) _ http://dev.processing.org/bugs/show_bug.cgi?id=140 -_ external editor -> add a command to launch +_ need method for showing prefs for the tools +_ i.e. add pref to handle date vs. increment on archive sketch +_ tools that need prefs will show their own GUI anyway + + +TOOLS / Ideas + +_ add a command to launch an external editor _ http://dev.processing.org/bugs/show_bug.cgi?id=141 _ add tool to "Add custom html to sketch" _ that copies applet.html, @@ -984,6 +1005,15 @@ _ tool to run in appletviewer? sun.applet.Main is appletviewer _ import sketch from url (takes a zip from archive sketch) _ ftp upload sketch _ archive sketch direct to bug report +_ courseware +_ export sketch as applet when uploading +_ save sketch zip files +_ have a means to load them from "teacher" version of p5 +_ figure out how to use the +_ shared code +_ Integrator / FloatThing / CameraStuff -- Update +_ to pull code from a local folder +_ update will update classes from shared in the current folder TOOLS / Color Picker @@ -992,37 +1022,12 @@ _ pasting into color picker doesn't update the color values _ http://dev.processing.org/bugs/show_bug.cgi?id=503 -TOOLS / Courseware - -_ export sketch as applet when uploading -_ save sketch zip files, have a means to load them from "teacher" version of p5 -_ figure out how to use the - - -TOOLS / Discourse Format +TOOLS / Copy for Discourse _ occasional exception in "copy for discourse" _ http://dev.processing.org/bugs/show_bug.cgi?id=729 -TOOLS / Libraries - -_ could have library developers update compatability note -_ so they would need to test library and say "compatible with 0110" -_ before it would automatically update or show as an update -_ tools -> get library -_ library url: [ http://blahblah.org/something ] -_ this would grab something.version, and something.zip -_ maybe something.xml that would include a bunch of background -_ tools -> update libraries -_ this would check the something.version to see if it's newer -_ document how to add libraries: put in sketchbook (not libraries folder) -_ library/download.url and library/home.url -_ if there's a reference subfolder, add that to the help menu -o and enable it for "find in reference" -X nice idea but too error-prone - - TOOLS / Auto Format _ autoformat fails when there's no newline @@ -1056,7 +1061,8 @@ _ http://dev.processing.org/bugs/show_bug.cgi?id=760 _ too many right parens error when there are not _ http://dev.processing.org/bugs/show_bug.cgi?id=867 _ code without a new line at end crashes -_ +_ http://dev.processing.org/bugs/show_bug.cgi?id=880 +_ break out as its own plugin TOOLS / Create Font