diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java
index 21d0df712..5f3507159 100644
--- a/app/src/processing/app/Base.java
+++ b/app/src/processing/app/Base.java
@@ -198,9 +198,19 @@ public class Base {
}
log("about to create base..."); //$NON-NLS-1$
- Base base = new Base(args);
- // Prevent more than one copy of the PDE from running.
- SingleInstance.startServer(base);
+ try {
+ Base base = new Base(args);
+ // Prevent more than one copy of the PDE from running.
+ SingleInstance.startServer(base);
+
+ } catch (Exception e) {
+ // Catch-all to hopefully pick up some of the weirdness we've been
+ // running into lately.
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ Base.showError("We're off on the wrong foot",
+ "An error occurred during startup.\n" + sw, e);
+ }
log("done creating base..."); //$NON-NLS-1$
}
}
@@ -324,7 +334,7 @@ public class Base {
}
- public Base(String[] args) {
+ public Base(String[] args) throws Exception {
// // Get the sketchbook path, and make sure it's set properly
// determineSketchbookFolder();
@@ -338,7 +348,7 @@ public class Base {
// removeDir(contrib.getFolder());
// }
// }
- ContributionManager.deleteFlagged();
+ ContributionManager.cleanup();
buildCoreModes();
rebuildContribModes();
@@ -354,7 +364,7 @@ public class Base {
} else {
for (Mode m : getModeList()) {
if (m.getIdentifier().equals(lastModeIdentifier)) {
- log("Setting next mode to " + lastModeIdentifier); //$NON-NLS-1$
+ logf("Setting next mode to {0}.", lastModeIdentifier); //$NON-NLS-1$
nextMode = m;
}
}
@@ -2584,18 +2594,21 @@ public class Base {
/**
- * Remove a File object (a file or directory) from the system by placing it
- * in the Trash or Recycle Bin (if available) or simply deleting it (if not).
+ * Delete a file or directory in a platform-specific manner. Removes a File
+ * object (a file or directory) from the system by placing it in the Trash
+ * or Recycle Bin (if available) or simply deleting it (if not).
*
* When the file/folder is on another file system, it may simply be removed
* immediately, without additional warning. So only use this if you want to,
- * you know, "remove" the subject in question.
+ * you know, "delete" the subject in question.
+ *
+ * NOTE: Not yet tested nor ready for prime-time.
*
- * @param file the victim
+ * @param file the victim (a directory or individual file)
* @return true if all ends well
* @throws IOException what went wrong
*/
- static public boolean removeFile(File file) throws IOException {
+ static public boolean platformDelete(File file) throws IOException {
return platform.deleteFile(file);
}
diff --git a/app/src/processing/app/contrib/AvailableContribution.java b/app/src/processing/app/contrib/AvailableContribution.java
index 046c49678..b4cb57cd4 100644
--- a/app/src/processing/app/contrib/AvailableContribution.java
+++ b/app/src/processing/app/contrib/AvailableContribution.java
@@ -128,19 +128,25 @@ class AvailableContribution extends Contribution {
// backup old if needed, then move things into place and reload.
installedContrib =
newContrib.copyAndLoad(editor, confirmReplace, status);
+ if (newContrib != null && type.requiresRestart()) {
+ installedContrib.setRestartFlag();
+ //status.setMessage("Restart Processing to finish the installation.");
+ }
// 3. Delete the newContrib, do a garbage collection, hope and pray
// that Java will unlock the temp folder on Windows now
newContrib = null;
System.gc();
- // we'll even give it a second to finish up ... because file ops are
- // just that flaky on Windows.
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ if (Base.isWindows()) {
+ // we'll even give it a second to finish up ... because file ops are
+ // just that flaky on Windows.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
// 4. Okay, now actually delete that temp folder
diff --git a/app/src/processing/app/contrib/Contribution.java b/app/src/processing/app/contrib/Contribution.java
index e09098add..0bc88268b 100644
--- a/app/src/processing/app/contrib/Contribution.java
+++ b/app/src/processing/app/contrib/Contribution.java
@@ -133,21 +133,26 @@ abstract public class Contribution {
abstract public boolean isInstalled();
- /**
- * Returns true if the type of contribution requires the PDE to restart
- * when being added or removed.
- */
- public boolean requiresRestart() {
- return getType() == ContributionType.TOOL || getType() == ContributionType.MODE;
- }
+// /**
+// * Returns true if the type of contribution requires the PDE to restart
+// * when being added or removed.
+// */
+// public boolean requiresRestart() {
+// return getType() == ContributionType.TOOL || getType() == ContributionType.MODE;
+// }
- /** Overridden by InstalledContribution. */
- boolean isDeletionFlagged() {
+ boolean isRestartFlagged() {
return false;
}
+ /** Overridden by LocalContribution. */
+ boolean isDeletionFlagged() {
+ return false;
+ }
+
+
/**
* @return the list of categories that this contribution is part of
* (e.g. "Typography / Geometry"). "Unknown" if the category null.
diff --git a/app/src/processing/app/contrib/ContributionListPanel.java b/app/src/processing/app/contrib/ContributionListPanel.java
index e25537cf7..2fc5922fa 100644
--- a/app/src/processing/app/contrib/ContributionListPanel.java
+++ b/app/src/processing/app/contrib/ContributionListPanel.java
@@ -36,14 +36,11 @@ import processing.app.Base;
// The "Scrollable" implementation and its methods here take care of preventing
// the scrolling area from running exceptionally slowly. Not sure why they're
-// necessary in the first place, however; seems like odd behavior.
+// necessary in the first place, however; seems like odd behavior.
+// It also allows the description text in the panels to wrap properly.
public class ContributionListPanel extends JPanel implements Scrollable, ContributionChangeListener {
- static public final String DELETION_MESSAGE =
- "This tool has been flagged for deletion. " +
- "Restart Proessing to finalize the removal process.";
-
static public final String INSTALL_FAILURE_TITLE = "Install Failed";
static public final String MALFORMED_URL_MESSAGE =
diff --git a/app/src/processing/app/contrib/ContributionManager.java b/app/src/processing/app/contrib/ContributionManager.java
index 7659a1dfc..fdc5c9b39 100644
--- a/app/src/processing/app/contrib/ContributionManager.java
+++ b/app/src/processing/app/contrib/ContributionManager.java
@@ -202,15 +202,21 @@ public class ContributionManager {
}
- /** Called by Base to clean up entries previously marked for deletion. */
- static public void deleteFlagged() {
+ /**
+ * Called by Base to clean up entries previously marked for deletion
+ * and remove any "requires restart" flags.
+ */
+ static public void cleanup() throws Exception {
deleteFlagged(Base.getSketchbookLibrariesFolder());
deleteFlagged(Base.getSketchbookModesFolder());
deleteFlagged(Base.getSketchbookToolsFolder());
+
+ clearRestartFlags(Base.getSketchbookModesFolder());
+ clearRestartFlags(Base.getSketchbookToolsFolder());
}
- static private void deleteFlagged(File root) {
+ static private void deleteFlagged(File root) throws Exception {
File[] markedForDeletion = root.listFiles(new FileFilter() {
public boolean accept(File folder) {
return (folder.isDirectory() &&
@@ -221,4 +227,16 @@ public class ContributionManager {
Base.removeDir(folder);
}
}
+
+
+ static private void clearRestartFlags(File root) throws Exception {
+ File[] folderList = root.listFiles(new FileFilter() {
+ public boolean accept(File folder) {
+ return folder.isDirectory();
+ }
+ });
+ for (File folder : folderList) {
+ LocalContribution.clearRestartFlags(folder);
+ }
+ }
}
diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java
index 19e5eb3b4..52987fe61 100644
--- a/app/src/processing/app/contrib/ContributionManagerDialog.java
+++ b/app/src/processing/app/contrib/ContributionManagerDialog.java
@@ -274,11 +274,15 @@ public class ContributionManagerDialog {
// }
Collections.sort(categories);
// categories.add(0, ContributionManagerDialog.ANY_CATEGORY);
+ boolean categoriesFound = false;
categoryChooser.addItem(ContributionManagerDialog.ANY_CATEGORY);
for (String s : categories) {
categoryChooser.addItem(s);
+ if (!s.equals("Unknown")) {
+ categoriesFound = true;
+ }
}
- categoryChooser.setEnabled(categories.size() != 0);
+ categoryChooser.setEnabled(categoriesFound);
}
}
@@ -318,7 +322,18 @@ public class ContributionManagerDialog {
protected void updateContributionListing() {
if (editor != null) {
- ArrayList libraries = new ArrayList(editor.getMode().contribLibraries);
+ ArrayList contributions = new ArrayList();
+
+ ArrayList libraries =
+ new ArrayList(editor.getMode().contribLibraries);
+ contributions.addAll(libraries);
+
+ ArrayList tools = editor.contribTools;
+ contributions.addAll(tools);
+
+ ArrayList modes = editor.getBase().getModeContribs();
+ contributions.addAll(modes);
+
// ArrayList compilations = LibraryCompilation.list(libraries);
//
// // Remove libraries from the list that are part of a compilations
@@ -332,11 +347,6 @@ public class ContributionManagerDialog {
// }
// }
- ArrayList contributions = new ArrayList();
- contributions.addAll(editor.contribTools);
- contributions.addAll(libraries);
-// contributions.addAll(compilations);
-
contribListing.updateInstalledList(contributions);
}
}
diff --git a/app/src/processing/app/contrib/ContributionPanel.java b/app/src/processing/app/contrib/ContributionPanel.java
index 9f0ff9a60..09ba24faf 100644
--- a/app/src/processing/app/contrib/ContributionPanel.java
+++ b/app/src/processing/app/contrib/ContributionPanel.java
@@ -44,6 +44,12 @@ import processing.app.Base;
* Panel that expands and gives a brief overview of a library when clicked.
*/
class ContributionPanel extends JPanel {
+ static public final String REMOVE_RESTART_MESSAGE =
+ "Please restart Processing to finish removing this item.";
+
+ static public final String INSTALL_RESTART_MESSAGE =
+ "Please restart Processing to finish installing this item.";
+
private final ContributionListPanel listPanel;
private final ContributionListing contribListing = ContributionListing.getInstance();
@@ -95,6 +101,7 @@ class ContributionPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
if (contrib instanceof AvailableContribution) {
installContribution((AvailableContribution) contrib);
+ contribListing.replaceContribution(contrib, contrib);
}
}
};
@@ -103,7 +110,7 @@ class ContributionPanel extends JPanel {
public void actionPerformed(ActionEvent e) {
if (contrib instanceof LocalContribution) {
LocalContribution installed = (LocalContribution) contrib;
- installed.unsetDeletionFlag();
+ installed.setDeletionFlag(false);
contribListing.replaceContribution(contrib, contrib); // ??
}
}
@@ -336,9 +343,11 @@ class ContributionPanel extends JPanel {
}
description.append("
");
- boolean isFlagged = contrib.isDeletionFlagged();
- if (isFlagged) {
- description.append(ContributionListPanel.DELETION_MESSAGE);
+ //System.out.println("checking restart flag for " + contrib + " " + contrib.getName() + " and it's " + contrib.isRestartFlagged());
+ if (contrib.isDeletionFlagged()) {
+ description.append(REMOVE_RESTART_MESSAGE);
+ } else if (contrib.isRestartFlagged()) {
+ description.append(INSTALL_RESTART_MESSAGE);
} else {
String sentence = contrib.getSentence();
if (sentence == null || sentence.isEmpty()) {
@@ -357,11 +366,14 @@ class ContributionPanel extends JPanel {
if (contribListing.hasUpdates(contrib)) {
StringBuilder versionText = new StringBuilder();
versionText.append("");
- if (isFlagged) {
- versionText.append("To finish an update, reinstall this contribution after the restart.");
+ if (contrib.isDeletionFlagged()) {
+ // Already marked for deletion, see requiresRestart() notes below.
+ versionText.append("To finish an update, reinstall this contribution after restarting.");
} else {
versionText.append("New version available!");
- if (contrib.requiresRestart()) {
+ if (contrib.getType().requiresRestart()) {
+ // If a contribution can't be reinstalled in-place, the user may need
+ // to remove the current version, restart Processing, then install.
versionText.append(" To update, first remove the current version.");
}
}
@@ -374,7 +386,7 @@ class ContributionPanel extends JPanel {
}
updateButton.setEnabled(true);
- if (contrib != null && !contrib.requiresRestart()) {
+ if (contrib != null && !contrib.getType().requiresRestart()) {
updateButton.setVisible(isSelected() && contribListing.hasUpdates(contrib));
}
@@ -382,7 +394,7 @@ class ContributionPanel extends JPanel {
installRemoveButton.removeActionListener(removeActionListener);
installRemoveButton.removeActionListener(undoActionListener);
- if (isFlagged) {
+ if (contrib.isDeletionFlagged()) {
installRemoveButton.addActionListener(undoActionListener);
installRemoveButton.setText("Undo");
} else if (contrib.isInstalled()) {
@@ -449,7 +461,8 @@ class ContributionPanel extends JPanel {
} catch (MalformedURLException e) {
Base.showWarning(ContributionListPanel.INSTALL_FAILURE_TITLE,
ContributionListPanel.MALFORMED_URL_MESSAGE, e);
- installRemoveButton.setEnabled(true);
+ // not sure why we'd re-enable the button if it had an error...
+// installRemoveButton.setEnabled(true);
}
}
@@ -487,7 +500,7 @@ class ContributionPanel extends JPanel {
// now a hyperlink, it will be opened as the mouse is released.
enableHyperlinks = alreadySelected;
- if (contrib != null && !contrib.requiresRestart()) {
+ if (contrib != null && !contrib.getType().requiresRestart()) {
updateButton.setVisible(isSelected() && contribListing.hasUpdates(contrib));
}
installRemoveButton.setVisible(isSelected() || installRemoveButton.getText().equals("Remove"));
diff --git a/app/src/processing/app/contrib/ContributionType.java b/app/src/processing/app/contrib/ContributionType.java
index a2a943665..8b882ee59 100644
--- a/app/src/processing/app/contrib/ContributionType.java
+++ b/app/src/processing/app/contrib/ContributionType.java
@@ -163,6 +163,15 @@ public enum ContributionType {
}
+ /**
+ * Returns true if the type of contribution requires the PDE to restart
+ * when being added or removed.
+ */
+ boolean requiresRestart() {
+ return this == ContributionType.TOOL || this == ContributionType.MODE;
+ }
+
+
LocalContribution load(Base base, File folder) {
switch (this) {
case LIBRARY:
@@ -193,15 +202,20 @@ public enum ContributionType {
return contribs;
}
+
+ File getBackupFolder() {
+ return new File(getSketchbookFolder(), "old");
+ }
+
File createBackupFolder(StatusPanel status) {
- File backupFolder = new File(getSketchbookFolder(), "old");
- if (backupFolder.isDirectory()) {
- status.setErrorMessage("First remove the folder named \"old\" from the " +
- getFolderName() + " folder in the sketchbook.");
- return null;
- }
- if (!backupFolder.mkdirs()) {
+ File backupFolder = getBackupFolder();
+// if (backupFolder.isDirectory()) {
+// status.setErrorMessage("First remove the folder named \"old\" from the " +
+// getFolderName() + " folder in the sketchbook.");
+// return null;
+// }
+ if (!backupFolder.exists() && !backupFolder.mkdirs()) {
status.setErrorMessage("Could not create a backup folder in the " +
"sketchbook " + toString() + " folder.");
return null;
diff --git a/app/src/processing/app/contrib/LocalContribution.java b/app/src/processing/app/contrib/LocalContribution.java
index 20595a7ba..cc494b613 100644
--- a/app/src/processing/app/contrib/LocalContribution.java
+++ b/app/src/processing/app/contrib/LocalContribution.java
@@ -38,14 +38,15 @@ import processing.app.*;
* be installed.
*/
public abstract class LocalContribution extends Contribution {
- static public final String DELETION_FLAG = "flagged_for_deletion";
+ static public final String DELETION_FLAG = "marked_for_deletion";
+ static public final String RESTART_FLAG = "requires_restart";
protected String id; // 1 (unique id for this library)
protected int latestVersion; // 103
protected File folder;
protected HashMap properties;
protected ClassLoader loader;
-
+
public LocalContribution(File folder) {
this.folder = folder;
@@ -198,7 +199,7 @@ public abstract class LocalContribution extends Contribution {
if ((oldContrib.getFolder().exists() && oldContrib.getFolder().equals(contribFolder)) ||
(oldContrib.getId() != null && oldContrib.getId().equals(getId()))) {
- if (oldContrib.requiresRestart()) {
+ if (oldContrib.getType().requiresRestart()) {
// XXX: We can't replace stuff, soooooo.... do something different
if (!oldContrib.backup(editor, false, status)) {
return null;
@@ -213,7 +214,7 @@ public abstract class LocalContribution extends Contribution {
"A pre-existing copy of the \"" + oldContrib.getName() + "\" library
"+
"has been found in your sketchbook. Clicking “Yes”
"+
"will move the existing library to a backup folder
" +
- " in libraries/old before replacing it.");
+ "in libraries/old before replacing it.");
if (result != JOptionPane.YES_OPTION || !oldContrib.backup(editor, true, status)) {
return null;
}
@@ -275,15 +276,15 @@ public abstract class LocalContribution extends Contribution {
* should instead be copied, leaving the original in place
*/
boolean backup(Editor editor, boolean deleteOriginal, StatusPanel status) {
-
- boolean success = false;
File backupFolder = getType().createBackupFolder(status);
+ boolean success = false;
if (backupFolder != null) {
String libFolderName = getFolder().getName();
String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
final String backupName = prefix + " " + libFolderName;
- File backupSubFolder = ContributionManager.getUniqueName(backupFolder, backupName);
+ File backupSubFolder =
+ ContributionManager.getUniqueName(backupFolder, backupName);
if (deleteOriginal) {
success = getFolder().renameTo(backupSubFolder);
@@ -325,9 +326,9 @@ public abstract class LocalContribution extends Contribution {
pm.startTask("Removing", ProgressMonitor.UNKNOWN);
boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove");
- if (requiresRestart()) {
+ if (getType().requiresRestart()) {
if (!doBackup || (doBackup && backup(editor, false, status))) {
- if (setDeletionFlag()) {
+ if (setDeletionFlag(true)) {
contribListing.replaceContribution(this, this);
}
}
@@ -370,33 +371,6 @@ public abstract class LocalContribution extends Contribution {
return folder != null;
}
-
- boolean setDeletionFlag() {
- // Only returns false if the file already exists, so we can
- // ignore the return value.
- try {
- new File(getFolder(), DELETION_FLAG).createNewFile();
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
-
- boolean unsetDeletionFlag() {
- return new File(getFolder(), DELETION_FLAG).delete();
- }
-
-
- boolean isDeletionFlagged() {
- return isDeletionFlagged(getFolder());
- }
-
-
- static boolean isDeletionFlagged(File folder) {
- return new File(folder, DELETION_FLAG).exists();
- }
-
// public String getCategory() {
// return category;
@@ -464,8 +438,77 @@ public abstract class LocalContribution extends Contribution {
return null;
}
*/
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ boolean setDeletionFlag(boolean flag) {
+ return setFlag(DELETION_FLAG, flag);
+ }
+
+
+ boolean isDeletionFlagged() {
+ return isDeletionFlagged(getFolder());
+ }
+ static boolean isDeletionFlagged(File folder) {
+ return isFlagged(folder, DELETION_FLAG);
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ boolean setRestartFlag() {
+ //System.out.println("setting restart flag for " + folder);
+ return setFlag(RESTART_FLAG, true);
+ }
+
+
+ @Override
+ boolean isRestartFlagged() {
+ //System.out.println("checking for restart inside LocalContribution for " + getName());
+ return isFlagged(getFolder(), RESTART_FLAG);
+ }
+
+
+ static void clearRestartFlags(File folder) {
+ File restartFlag = new File(folder, RESTART_FLAG);
+ if (restartFlag.exists()) {
+ restartFlag.delete();
+ }
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
+ private boolean setFlag(String flagFilename, boolean flag) {
+ if (flag) {
+ // Only returns false if the file already exists, so we can
+ // ignore the return value.
+ try {
+ new File(getFolder(), flagFilename).createNewFile();
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ } else {
+ return new File(getFolder(), flagFilename).delete();
+ }
+ }
+
+
+ static private boolean isFlagged(File folder, String flagFilename) {
+ return new File(folder, flagFilename).exists();
+ }
+
+
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+
+
/**
*
* @param base name of the class, with or without the package
diff --git a/todo.txt b/todo.txt
index 60018df58..5b6f5d020 100644
--- a/todo.txt
+++ b/todo.txt
@@ -26,11 +26,8 @@ X UnsatisfiedLinkError causes huge message...
X error report cleanups haven't been fixed yet
X reported by Dan
X this should be better now
+X add exception wrapper for startup
X Add methods to move files to Trash/Recycle Bin where available
-_ verify that the OS X version uses the real call
-_ and doesn't just look for .Trash
-_ getCoreLibrary() is breaking OpenGL
-_ "new Library()" constructor needs to go back to private
_ remove ability to export cross-platform apps
_ add ability to embed the current JRE
@@ -55,15 +52,27 @@ X restrict library categories to the ones in the document
X if it's not correct, shows up as 'other'
X catch Error (not just Exception) objects during load
X handles UnsupportedClassVersionError and others
-_ we shouldn't use .properties for modes et al
+X argh.. the 'old' folder is really poorly done
+X attempt to install multiple will cause havoc (fail because 'old' exists)
+o remove flagging for deletion
+o half-installed mode causes a lot of trouble
+o maybe it's reading from tmp folders?
+o https://github.com/processing/processing/issues/1875
+X can't fix, no response
+X remove "Compilations" category for libraries
+X modes shouldn't have categories?
+X was counting "Unknown" as a category
+X modes and tools require restart (per ContributionType class)
+X but no message is provided anywhere?
+X mode install requires restart *and* still doesn't show as installed
+X even though it gets added to the modes menu properly after the restart
+X https://github.com/processing/processing/issues/1782
+
+_ we shouldn't use .properties extension for modes, et al
_ because a .properties file is iso8859-1
-_ remove "Compilations" category for libraries
_ make note that .properties file *must* be utf-8
_ if not it'll make things gross (andre sier flob library)
-_ argh.. the 'old' folder is really poorly done
-_ attempt to install multiple will cause havoc (fail because 'old' exists)
-_ modes and tools require restart (per ContributionType class)
-_ but no message is provided anywhere?
+
_ why wasn't Library moved to LibraryContribution?
_ or that LibraryContribution needs to be a wrapper around it?
_ send info on 'check for updates' so we know about libs/modes/etc?
@@ -71,12 +80,7 @@ _ how to disclose to users?
_ only send for items that are part of the public list
_ otherwise we're sending private libraries/installs
_ although this won't pick up old libraries not on the new system
-_ half-installed mode causes a lot of trouble
-_ maybe it's reading from tmp folders?
-_ https://github.com/processing/processing/issues/1875
-_ mode install requires restart *and* still doesn't show as installed
-_ even though it gets added to the modes menu properly after the restart
-_ https://github.com/processing/processing/issues/1782
+
_ classpath conflicts..
_ getPackageList.. from Library... maybe others?
_ really need to make sure that a weird core.jar isn't being imported
@@ -95,7 +99,6 @@ _ "Update 4 items" as a button name
high
_ MovieMaker needs to be compiling as 1.6
-_ add .bat file to lib on windows so that we can get better debugging info
_ move old Google Code SVN back to processing.org
_ then cull out the old branches/tags from the Github repo
_ proxy server requirement causes problems
@@ -109,6 +112,14 @@ _ move this into Android mode?
_ "String index out of range" error
_ https://github.com/processing/processing/issues/1940
+medium
+_ change to using platformDelete() instead of Base.removeDir() where possible
+_ verify that the OS X version uses the real call
+_ and doesn't just look for .Trash
+_ getCoreLibrary() is breaking OpenGL
+_ "new Library()" constructor needs to go back to private
+_ add .bat file to lib on windows so that we can get better debugging info
+
_ appbundler fixes/changes
_ icon location uses path, even when embedded
_ add indents to the Info.plist output file