mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Merge remote-tracking branch 'upstream/master' into jdiMod
Rolling back
This commit is contained in:
@@ -334,9 +334,7 @@ public class Base {
|
||||
// removeDir(contrib.getFolder());
|
||||
// }
|
||||
// }
|
||||
ContributionManager.checkDeletions(getSketchbookModesFolder());
|
||||
ContributionManager.checkDeletions(getSketchbookToolsFolder());
|
||||
|
||||
ContributionManager.deleteFlagged();
|
||||
buildCoreModes();
|
||||
rebuildContribModes();
|
||||
|
||||
@@ -362,37 +360,15 @@ public class Base {
|
||||
}
|
||||
}
|
||||
|
||||
libraryManagerFrame = new ContributionManagerDialog("Library Manager",
|
||||
new ContributionListing.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
return contrib.getType() == ContributionType.LIBRARY;
|
||||
// return contrib.getType() == Contribution.Type.LIBRARY
|
||||
// || contrib.getType() == Contribution.Type.LIBRARY_COMPILATION;
|
||||
}
|
||||
});
|
||||
toolManagerFrame = new ContributionManagerDialog("Tool Manager",
|
||||
new ContributionListing.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
return contrib.getType() == ContributionType.TOOL;
|
||||
}
|
||||
});
|
||||
modeManagerFrame = new ContributionManagerDialog("Mode Manager",
|
||||
new ContributionListing.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
return contrib.getType() == ContributionType.MODE;
|
||||
}
|
||||
});
|
||||
updateManagerFrame = new ContributionManagerDialog("Update Manager",
|
||||
new ContributionListing.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
if (contrib instanceof InstalledContribution) {
|
||||
return ContributionListing.getInstance().hasUpdates(contrib);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
libraryManagerFrame =
|
||||
new ContributionManagerDialog(ContributionType.LIBRARY);
|
||||
toolManagerFrame =
|
||||
new ContributionManagerDialog(ContributionType.TOOL);
|
||||
modeManagerFrame =
|
||||
new ContributionManagerDialog(ContributionType.MODE);
|
||||
updateManagerFrame =
|
||||
new ContributionManagerDialog(null);
|
||||
|
||||
// Make sure ThinkDifferent has library examples too
|
||||
nextMode.rebuildLibraryList();
|
||||
|
||||
@@ -2907,6 +2883,39 @@ public class Base {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public void unzip(File zipFile, File dest) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(zipFile);
|
||||
CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32());
|
||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum));
|
||||
ZipEntry next = null;
|
||||
while ((next = zis.getNextEntry()) != null) {
|
||||
File currentFile = new File(dest, next.getName());
|
||||
if (next.isDirectory()) {
|
||||
currentFile.mkdirs();
|
||||
} else {
|
||||
currentFile.createNewFile();
|
||||
unzipEntry(zis, currentFile);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static protected void unzipEntry(ZipInputStream zin, File f) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
byte[] b = new byte[512];
|
||||
int len = 0;
|
||||
while ((len = zin.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
static public void log(Object from, String message) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import processing.app.contrib.*;
|
||||
import processing.core.*;
|
||||
|
||||
|
||||
public class Library extends InstalledContribution {
|
||||
public class Library extends LocalContribution {
|
||||
static final String[] platformNames = PConstants.platformNames;
|
||||
|
||||
//protected File folder; // /path/to/shortname
|
||||
|
||||
+29
-89
@@ -29,110 +29,88 @@ import processing.app.Editor;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
class AdvertisedContribution extends Contribution {
|
||||
/**
|
||||
* A class to hold information about a Contribution that can be downloaded.
|
||||
*/
|
||||
class AvailableContribution extends Contribution {
|
||||
protected final ContributionType type; // Library, tool, etc.
|
||||
protected final String link; // Direct link to download the file
|
||||
|
||||
// protected final String category; // "Sound"
|
||||
// protected final String name; // "pdf" or "PDF Export"
|
||||
// protected final String authorList; // [Ben Fry](http://benfry.com/)
|
||||
// protected final String url; // http://processing.org
|
||||
// protected final String sentence; // Write graphics to PDF files.
|
||||
// protected final String paragraph; // <paragraph length description for site>
|
||||
// protected final int version; // 102
|
||||
// protected final String prettyVersion; // "1.0.2"
|
||||
|
||||
|
||||
public AdvertisedContribution(ContributionType type, HashMap<String, String> exports) {
|
||||
|
||||
public AvailableContribution(ContributionType type, HashMap<String, String> params) {
|
||||
this.type = type;
|
||||
name = exports.get("name");
|
||||
category = ContributionListing.getCategory(exports.get("category"));
|
||||
authorList = exports.get("authorList");
|
||||
|
||||
url = exports.get("url");
|
||||
sentence = exports.get("sentence");
|
||||
paragraph = exports.get("paragraph");
|
||||
|
||||
int v = 0;
|
||||
try {
|
||||
v = Integer.parseInt(exports.get("version"));
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
version = v;
|
||||
|
||||
prettyVersion = exports.get("prettyVersion");
|
||||
|
||||
this.link = exports.get("download");
|
||||
this.link = params.get("download");
|
||||
|
||||
category = ContributionListing.getCategory(params.get("category"));
|
||||
name = params.get("name");
|
||||
authorList = params.get("authorList");
|
||||
url = params.get("url");
|
||||
sentence = params.get("sentence");
|
||||
paragraph = params.get("paragraph");
|
||||
version = PApplet.parseInt(params.get("version"), 0);
|
||||
prettyVersion = params.get("prettyVersion");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param contribArchive
|
||||
* a zip file containing the library to install
|
||||
* @param ad
|
||||
* the advertised version of this library, if it was downloaded
|
||||
* through the Contribution Manager. This is used to check the type
|
||||
* of library being installed, and to replace the .properties file in
|
||||
* the zip
|
||||
* @param confirmReplace
|
||||
* true to open a dialog asking the user to confirm removing/moving
|
||||
* the library when a library by the same name already exists
|
||||
* @return
|
||||
*/
|
||||
public InstalledContribution install(Editor editor, File contribArchive,
|
||||
boolean confirmReplace,
|
||||
ErrorWidget statusBar) {
|
||||
|
||||
public LocalContribution install(Editor editor, File contribArchive,
|
||||
boolean confirmReplace, ErrorWidget status) {
|
||||
// Unzip the file into the modes, tools, or libraries folder inside the
|
||||
// sketchbook. Unzipping to /tmp is problematic because it may be on
|
||||
// another file system, so move/rename operations will break.
|
||||
File sketchbookContribFolder = type.getSketchbookContribFolder();
|
||||
File sketchbookContribFolder = type.getSketchbookFolder();
|
||||
File tempFolder = null;
|
||||
|
||||
try {
|
||||
tempFolder =
|
||||
Base.createTempFolder(type.toString(), "tmp", sketchbookContribFolder);
|
||||
} catch (IOException e) {
|
||||
statusBar.setErrorMessage("Could not create a temporary folder to install.");
|
||||
status.setErrorMessage("Could not create a temporary folder to install.");
|
||||
return null;
|
||||
}
|
||||
ContributionManager.unzip(contribArchive, tempFolder);
|
||||
Base.unzip(contribArchive, tempFolder);
|
||||
|
||||
// Now go looking for a legit contrib inside what's been unpacked.
|
||||
File contribFolder = null;
|
||||
|
||||
// Sometimes contrib authors place all their folders in the base directory
|
||||
// of the .zip file instead of in single folder as the guidelines suggest.
|
||||
if (InstalledContribution.isCandidate(tempFolder, type)) {
|
||||
if (type.isCandidate(tempFolder)) {
|
||||
contribFolder = tempFolder;
|
||||
}
|
||||
|
||||
if (contribFolder == null) {
|
||||
// Find the first legitimate looking folder in what we just unzipped
|
||||
contribFolder = InstalledContribution.findCandidate(tempFolder, type);
|
||||
contribFolder = type.findCandidate(tempFolder);
|
||||
}
|
||||
|
||||
InstalledContribution installedContrib = null;
|
||||
LocalContribution installedContrib = null;
|
||||
|
||||
if (contribFolder == null) {
|
||||
statusBar.setErrorMessage("Could not find a " + type + " in the downloaded file.");
|
||||
status.setErrorMessage("Could not find a " + type + " in the downloaded file.");
|
||||
|
||||
} else {
|
||||
File propFile = new File(contribFolder, type + ".properties");
|
||||
|
||||
if (!writePropertiesFile(propFile)) {
|
||||
// 1. contribFolder now has a legit contribution, load it to get info.
|
||||
InstalledContribution newContrib =
|
||||
ContributionManager.load(editor.getBase(), contribFolder, type);
|
||||
LocalContribution newContrib =
|
||||
type.load(editor.getBase(), contribFolder);
|
||||
|
||||
// 2. Check to make sure nothing has the same name already,
|
||||
// backup old if needed, then move things into place and reload.
|
||||
installedContrib =
|
||||
newContrib.moveAndLoad(editor, confirmReplace, statusBar);
|
||||
newContrib.moveAndLoad(editor, confirmReplace, status);
|
||||
|
||||
} else {
|
||||
statusBar.setErrorMessage("Error overwriting .properties file.");
|
||||
status.setErrorMessage("Error overwriting .properties file.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +120,7 @@ class AdvertisedContribution extends Contribution {
|
||||
}
|
||||
return installedContrib;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isInstalled() {
|
||||
return false;
|
||||
@@ -153,43 +131,6 @@ class AdvertisedContribution extends Contribution {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
// public String getTypeName() {
|
||||
// return type.toString();
|
||||
// }
|
||||
//
|
||||
// public String getCategory() {
|
||||
// return category;
|
||||
// }
|
||||
//
|
||||
// public String getName() {
|
||||
// return name;
|
||||
// }
|
||||
//
|
||||
// public String getAuthorList() {
|
||||
// return authorList;
|
||||
// }
|
||||
//
|
||||
// public String getUrl() {
|
||||
// return url;
|
||||
// }
|
||||
//
|
||||
// public String getSentence() {
|
||||
// return sentence;
|
||||
// }
|
||||
//
|
||||
// public String getParagraph() {
|
||||
// return paragraph;
|
||||
// }
|
||||
//
|
||||
// public int getVersion() {
|
||||
// return version;
|
||||
// }
|
||||
//
|
||||
// public String getPrettyVersion() {
|
||||
// return prettyVersion;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* We overwrite the properties file with the curated version from the
|
||||
@@ -202,7 +143,6 @@ class AdvertisedContribution extends Contribution {
|
||||
public boolean writePropertiesFile(File propFile) {
|
||||
try {
|
||||
if (propFile.delete() && propFile.createNewFile() && propFile.setWritable(true)) {
|
||||
//BufferedWriter bw = new BufferedWriter(new FileWriter(propFile));
|
||||
PrintWriter writer = PApplet.createWriter(propFile);
|
||||
|
||||
writer.println("name=" + getName());
|
||||
@@ -90,4 +90,19 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
/** Overridden by InstalledContribution. */
|
||||
boolean isDeletionFlagged() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,44 +40,38 @@ import java.net.*;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.contrib.ContributionListing.ContributionChangeListener;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
public class ContributionListPanel extends JPanel implements Scrollable, ContributionChangeListener {
|
||||
|
||||
static public final String DELETION_MESSAGE = "<i>This tool has "
|
||||
+ "been flagged for deletion. Restart all instances of the editor to "
|
||||
+ "finalize the removal process.</i>";
|
||||
static public final String DELETION_MESSAGE =
|
||||
"<i>This tool has been flagged for deletion. " +
|
||||
"Restart Proessing to finalize the removal process.</i>";
|
||||
|
||||
static public final String INSTALL_FAILURE_TITLE = "Install Failed";
|
||||
|
||||
static public final String MALFORMED_URL_MESSAGE =
|
||||
"The link fetched from Processing.org is invalid.\n"
|
||||
+ "You can still intall this library manually by visiting\n"
|
||||
+ "the library's website.";
|
||||
"The link fetched from Processing.org is not valid.\n" +
|
||||
"You can still install this library manually by visiting\n" +
|
||||
"the library's website.";
|
||||
|
||||
ContributionManagerDialog contribManager;
|
||||
|
||||
TreeMap<Contribution, ContributionPanel> panelByContribution;
|
||||
|
||||
static private HyperlinkListener nullHyperlinkListener = new HyperlinkListener() {
|
||||
|
||||
public void hyperlinkUpdate(HyperlinkEvent e) {
|
||||
}
|
||||
public void hyperlinkUpdate(HyperlinkEvent e) { }
|
||||
};
|
||||
|
||||
protected ContributionPanel selectedPanel;
|
||||
|
||||
protected JPanel statusPlaceholder;
|
||||
|
||||
ContributionListing.Filter permaFilter;
|
||||
|
||||
ContributionListing contribListing;
|
||||
|
||||
|
||||
public ContributionListPanel(ContributionManagerDialog libraryManager,
|
||||
ContributionListing.Filter filter) {
|
||||
|
||||
super();
|
||||
|
||||
this.contribManager = libraryManager;
|
||||
this.permaFilter = filter;
|
||||
|
||||
@@ -102,6 +96,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
statusPlaceholder.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
private void updatePanelOrdering() {
|
||||
int row = 0;
|
||||
for (Entry<Contribution, ContributionPanel> entry : panelByContribution.entrySet()) {
|
||||
@@ -125,8 +120,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
add(statusPlaceholder, c);
|
||||
}
|
||||
|
||||
|
||||
public void contributionAdded(final Contribution contribution) {
|
||||
|
||||
if (permaFilter.matches(contribution)) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@@ -141,10 +136,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
panelByContribution.put(contribution, newPanel);
|
||||
}
|
||||
|
||||
|
||||
if (newPanel != null) {
|
||||
newPanel.setContribution(contribution);
|
||||
|
||||
add(newPanel);
|
||||
updatePanelOrdering();
|
||||
updateColors();
|
||||
@@ -154,8 +147,9 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void contributionRemoved(final Contribution contribution) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (panelByContribution) {
|
||||
ContributionPanel panel = panelByContribution.get(contribution);
|
||||
@@ -172,11 +166,11 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void contributionChanged(final Contribution oldContrib,
|
||||
final Contribution newContrib) {
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (panelByContribution) {
|
||||
ContributionPanel panel = panelByContribution.get(oldContrib);
|
||||
@@ -285,18 +279,21 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
}
|
||||
}
|
||||
|
||||
static String toHex(Color c) {
|
||||
StringBuilder hex = new StringBuilder();
|
||||
hex.append(Integer.toString(c.getRed(), 16));
|
||||
hex.append(Integer.toString(c.getGreen(), 16));
|
||||
hex.append(Integer.toString(c.getBlue(), 16));
|
||||
return hex.toString();
|
||||
}
|
||||
|
||||
// static String toHex(Color c) {
|
||||
// StringBuilder hex = new StringBuilder();
|
||||
// hex.append(Integer.toString(c.getRed(), 16));
|
||||
// hex.append(Integer.toString(c.getGreen(), 16));
|
||||
// hex.append(Integer.toString(c.getBlue(), 16));
|
||||
// return hex.toString();
|
||||
// }
|
||||
|
||||
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Amount to scroll to reveal a new page of items
|
||||
*/
|
||||
@@ -315,6 +312,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Amount to scroll to reveal the rest of something we are on or a new item
|
||||
*/
|
||||
@@ -409,45 +407,33 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
* Panel that expands and gives a brief overview of a library when clicked.
|
||||
*/
|
||||
private class ContributionPanel extends JPanel {
|
||||
|
||||
private static final int BUTTON_WIDTH = 100;
|
||||
|
||||
/** Should only be set through setContribution(), otherwise UI components
|
||||
* will not be updated. */
|
||||
Contribution contrib;
|
||||
/**
|
||||
* Should only be set through setContribution(),
|
||||
* otherwise UI components will not be updated.
|
||||
*/
|
||||
private Contribution contrib;
|
||||
|
||||
boolean alreadySelected;
|
||||
|
||||
boolean enableHyperlinks;
|
||||
|
||||
HyperlinkListener conditionalHyperlinkOpener;
|
||||
|
||||
JTextPane headerText;
|
||||
|
||||
JTextPane descriptionText;
|
||||
|
||||
JTextPane updateNotificationLabel;
|
||||
|
||||
JButton updateButton;
|
||||
|
||||
JProgressBar installProgressBar;
|
||||
|
||||
JButton installRemoveButton;
|
||||
|
||||
JPopupMenu contextMenu;
|
||||
|
||||
JMenuItem openFolder;
|
||||
private boolean alreadySelected;
|
||||
private boolean enableHyperlinks;
|
||||
private HyperlinkListener conditionalHyperlinkOpener;
|
||||
private JTextPane headerText;
|
||||
private JTextPane descriptionText;
|
||||
private JTextPane updateNotificationLabel;
|
||||
private JButton updateButton;
|
||||
private JProgressBar installProgressBar;
|
||||
private JButton installRemoveButton;
|
||||
private JPopupMenu contextMenu;
|
||||
private JMenuItem openFolder;
|
||||
|
||||
private HashSet<JTextPane> htmlPanes;
|
||||
|
||||
private ActionListener removeActionListener;
|
||||
|
||||
private ActionListener installActionListener;
|
||||
|
||||
private ActionListener undoActionListener;
|
||||
|
||||
|
||||
private ContributionPanel() {
|
||||
|
||||
htmlPanes = new HashSet<JTextPane>();
|
||||
|
||||
enableHyperlinks = false;
|
||||
@@ -467,33 +453,32 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
|
||||
installActionListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (contrib instanceof AdvertisedContribution) {
|
||||
installContribution((AdvertisedContribution) contrib);
|
||||
if (contrib instanceof AvailableContribution) {
|
||||
installContribution((AvailableContribution) contrib);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
undoActionListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (contrib instanceof InstalledContribution) {
|
||||
InstalledContribution installed = (InstalledContribution) contrib;
|
||||
ContributionManager.unsetDeletionFlag(installed);
|
||||
contribListing.replaceContribution(contrib, contrib);
|
||||
if (contrib instanceof LocalContribution) {
|
||||
LocalContribution installed = (LocalContribution) contrib;
|
||||
installed.unsetDeletionFlag();
|
||||
contribListing.replaceContribution(contrib, contrib); // ??
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
removeActionListener = new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg) {
|
||||
if (contrib.isInstalled() && contrib instanceof InstalledContribution) {
|
||||
if (contrib.isInstalled() && contrib instanceof LocalContribution) {
|
||||
updateButton.setEnabled(false);
|
||||
installRemoveButton.setEnabled(false);
|
||||
|
||||
installProgressBar.setVisible(true);
|
||||
|
||||
ContributionManager.removeContribution(contribManager.editor,
|
||||
(InstalledContribution) contrib,
|
||||
new JProgressMonitor(installProgressBar) {
|
||||
((LocalContribution) contrib).removeContribution(contribManager.editor,
|
||||
new JProgressMonitor(installProgressBar) {
|
||||
public void finishedAction() {
|
||||
// Finished uninstalling the library
|
||||
resetInstallProgressBarState();
|
||||
@@ -509,8 +494,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
openFolder = new JMenuItem("Open Folder");
|
||||
openFolder.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (contrib instanceof InstalledContribution) {
|
||||
File folder = ((InstalledContribution) contrib).getFolder();
|
||||
if (contrib instanceof LocalContribution) {
|
||||
File folder = ((LocalContribution) contrib).getFolder();
|
||||
Base.openFolder(folder);
|
||||
}
|
||||
}
|
||||
@@ -533,9 +518,10 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the widgets for the header panel which is visible when the library
|
||||
* panel is not clicked
|
||||
* Create the widgets for the header panel which is visible when the
|
||||
* library panel is not clicked.
|
||||
*/
|
||||
private void addPaneComponents() {
|
||||
setLayout(new GridBagLayout());
|
||||
@@ -584,10 +570,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
descriptionPanel.add(descriptionText, dc);
|
||||
}
|
||||
|
||||
int margin = 5;
|
||||
if (Base.isMacOS()) {
|
||||
margin = 15;
|
||||
}
|
||||
int margin = Base.isMacOS() ? 15 : 5;
|
||||
{
|
||||
GridBagConstraints dc = new GridBagConstraints();
|
||||
dc.gridx = 1;
|
||||
@@ -635,7 +618,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateButton.setEnabled(false);
|
||||
AdvertisedContribution ad = contribListing
|
||||
AvailableContribution ad = contribListing
|
||||
.getAdvertisedContribution(contrib);
|
||||
String url = ad.link;
|
||||
installContribution(ad, url);
|
||||
@@ -732,7 +715,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
StringBuilder description = new StringBuilder();
|
||||
description.append("<html><body>");
|
||||
|
||||
boolean isFlagged = ContributionManager.isDeletionFlagSet(contrib);
|
||||
boolean isFlagged = contrib.isDeletionFlagged();
|
||||
if (isFlagged) {
|
||||
description.append(ContributionListPanel.DELETION_MESSAGE);
|
||||
} else {
|
||||
@@ -758,7 +741,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
versionText.append("To finish an update, reinstall this contribution after the restart.");
|
||||
} else {
|
||||
versionText.append("New version available!");
|
||||
if (ContributionManager.requiresRestart(contrib)) {
|
||||
if (contrib.requiresRestart()) {
|
||||
versionText.append(" To update, first remove the current version.");
|
||||
}
|
||||
}
|
||||
@@ -771,7 +754,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
}
|
||||
|
||||
updateButton.setEnabled(true);
|
||||
if (contrib != null && !ContributionManager.requiresRestart(contrib)) {
|
||||
if (contrib != null && !contrib.requiresRestart()) {
|
||||
updateButton.setVisible(isSelected()
|
||||
&& contribListing.hasUpdates(contrib));
|
||||
}
|
||||
@@ -802,7 +785,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
|
||||
}
|
||||
|
||||
private void installContribution(AdvertisedContribution info) {
|
||||
private void installContribution(AvailableContribution info) {
|
||||
if (info.link == null) {
|
||||
contribManager.statusBar.setErrorMessage("Your operating system "
|
||||
+ "doesn't appear to be supported. You should visit the "
|
||||
@@ -812,37 +795,37 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
}
|
||||
}
|
||||
|
||||
private void installContribution(AdvertisedContribution ad, String url) {
|
||||
private void installContribution(AvailableContribution ad, String url) {
|
||||
|
||||
installRemoveButton.setEnabled(false);
|
||||
|
||||
try {
|
||||
URL downloadUrl = new URL(url);
|
||||
|
||||
installProgressBar.setVisible(true);
|
||||
|
||||
JProgressMonitor downloadProgress = new JProgressMonitor(installProgressBar) {
|
||||
public void finishedAction() {
|
||||
// Finished downloading library
|
||||
}
|
||||
};
|
||||
|
||||
JProgressMonitor installProgress = new JProgressMonitor(installProgressBar) {
|
||||
public void finishedAction() {
|
||||
// Finished installing library
|
||||
resetInstallProgressBarState();
|
||||
installRemoveButton.setEnabled(true);
|
||||
|
||||
if (isError()) {
|
||||
contribManager.statusBar.setErrorMessage("An error occured when "
|
||||
+ "downloading the contribution.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ContributionManager.downloadAndInstall(contribManager.editor,
|
||||
downloadUrl, ad,
|
||||
new JProgressMonitor(installProgressBar) {
|
||||
|
||||
public void finishedAction() {
|
||||
// Finished downloading library
|
||||
}
|
||||
},
|
||||
new JProgressMonitor(installProgressBar) {
|
||||
|
||||
public void finishedAction() {
|
||||
// Finished installing library
|
||||
resetInstallProgressBarState();
|
||||
installRemoveButton.setEnabled(true);
|
||||
|
||||
if (isError()) {
|
||||
contribManager.statusBar.setErrorMessage("An error occured when "
|
||||
+ "downloading the contribution.");
|
||||
}
|
||||
}
|
||||
},
|
||||
contribManager.statusBar
|
||||
downloadUrl, ad,
|
||||
downloadProgress, installProgress,
|
||||
contribManager.statusBar
|
||||
);
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
@@ -898,7 +881,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
// hyperlink, it will be opened as the mouse is released.
|
||||
enableHyperlinks = alreadySelected;
|
||||
|
||||
if (contrib != null && !ContributionManager.requiresRestart(contrib)) {
|
||||
if (contrib != null && !contrib.requiresRestart()) {
|
||||
updateButton.setVisible(isSelected()
|
||||
&& contribListing.hasUpdates(contrib));
|
||||
}
|
||||
@@ -949,8 +932,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
if (doc instanceof HTMLDocument) {
|
||||
HTMLDocument html = (HTMLDocument) doc;
|
||||
StyleSheet stylesheet = html.getStyleSheet();
|
||||
stylesheet.addRule("body {color:" + ContributionListPanel.toHex(fg) + ";}");
|
||||
stylesheet.addRule("a {color:" + ContributionListPanel.toHex(fg) + "}");
|
||||
stylesheet.addRule("body {color:" + PApplet.hex(fg.getRGB()).substring(2) + ";}");
|
||||
stylesheet.addRule("a {color:" + PApplet.hex(fg.getRGB()).substring(2) + "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ContributionListing {
|
||||
|
||||
File listingFile;
|
||||
ArrayList<ContributionChangeListener> listeners;
|
||||
ArrayList<AdvertisedContribution> advertisedContributions;
|
||||
ArrayList<AvailableContribution> advertisedContributions;
|
||||
Map<String, List<Contribution>> librariesByCategory;
|
||||
ArrayList<Contribution> allContributions;
|
||||
boolean hasDownloadedLatestList;
|
||||
@@ -53,7 +53,7 @@ public class ContributionListing {
|
||||
|
||||
private ContributionListing() {
|
||||
listeners = new ArrayList<ContributionChangeListener>();
|
||||
advertisedContributions = new ArrayList<AdvertisedContribution>();
|
||||
advertisedContributions = new ArrayList<AvailableContribution>();
|
||||
librariesByCategory = new HashMap<String, List<Contribution>>();
|
||||
allContributions = new ArrayList<Contribution>();
|
||||
downloadingListingLock = new ReentrantLock();
|
||||
@@ -82,7 +82,6 @@ public class ContributionListing {
|
||||
for (Contribution contribution : advertisedContributions) {
|
||||
addContribution(contribution);
|
||||
}
|
||||
|
||||
Collections.sort(allContributions, contribComparator);
|
||||
}
|
||||
|
||||
@@ -170,8 +169,8 @@ public class ContributionListing {
|
||||
}
|
||||
|
||||
|
||||
public AdvertisedContribution getAdvertisedContribution(Contribution info) {
|
||||
for (AdvertisedContribution advertised : advertisedContributions) {
|
||||
public AvailableContribution getAdvertisedContribution(Contribution info) {
|
||||
for (AvailableContribution advertised : advertisedContributions) {
|
||||
if (advertised.getType() == info.getType() &&
|
||||
advertised.getName().equals(info.getName())) {
|
||||
return advertised;
|
||||
@@ -487,11 +486,11 @@ public class ContributionListing {
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<AdvertisedContribution> parseContribList(File f) {
|
||||
ArrayList<AdvertisedContribution> outgoing = new ArrayList<AdvertisedContribution>();
|
||||
ArrayList<AvailableContribution> parseContribList(File file) {
|
||||
ArrayList<AvailableContribution> outgoing = new ArrayList<AvailableContribution>();
|
||||
|
||||
if (f != null && f.exists()) {
|
||||
String lines[] = PApplet.loadStrings(f);
|
||||
if (file != null && file.exists()) {
|
||||
String lines[] = PApplet.loadStrings(file);
|
||||
|
||||
int start = 0;
|
||||
while (start < lines.length) {
|
||||
@@ -516,9 +515,9 @@ public class ContributionListing {
|
||||
System.arraycopy(lines, start, contribLines, 0, length);
|
||||
|
||||
HashMap<String,String> contribParams = new HashMap<String,String>();
|
||||
Base.readSettings(f.getName(), contribLines, contribParams);
|
||||
Base.readSettings(file.getName(), contribLines, contribParams);
|
||||
|
||||
outgoing.add(new AdvertisedContribution(contribType, contribParams));
|
||||
outgoing.add(new AvailableContribution(contribType, contribParams));
|
||||
start = end + 1;
|
||||
// } else {
|
||||
// start++;
|
||||
@@ -534,10 +533,34 @@ public class ContributionListing {
|
||||
}
|
||||
|
||||
|
||||
public static interface Filter {
|
||||
static interface Filter {
|
||||
boolean matches(Contribution contrib);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a filter for a specific contribution type.
|
||||
* @param type The type, or null for a generic update checker.
|
||||
*/
|
||||
static Filter createFilter(final ContributionType type) {
|
||||
if (type == null) {
|
||||
return new Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
if (contrib instanceof LocalContribution) {
|
||||
return ContributionListing.getInstance().hasUpdates(contrib);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
return contrib.getType() == type;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Comparator<Contribution> contribComparator = new Comparator<Contribution>() {
|
||||
public int compare(Contribution o1, Contribution o2) {
|
||||
|
||||
@@ -23,14 +23,9 @@ package processing.app.contrib;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
import processing.app.Library;
|
||||
import processing.app.Preferences;
|
||||
|
||||
|
||||
interface ErrorWidget {
|
||||
@@ -39,7 +34,6 @@ interface ErrorWidget {
|
||||
|
||||
|
||||
public class ContributionManager {
|
||||
static public final String DELETION_FLAG = "flagged_for_deletion";
|
||||
static public final ContributionListing contribListing;
|
||||
|
||||
static {
|
||||
@@ -47,65 +41,6 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non-blocking call to remove a contribution in a new thread.
|
||||
*/
|
||||
static public void removeContribution(final Editor editor,
|
||||
final InstalledContribution contribution,
|
||||
final ProgressMonitor pm,
|
||||
final ErrorWidget statusBar) {
|
||||
if (contribution != null) {
|
||||
final ProgressMonitor progressMonitor = (pm != null) ? pm : new NullProgressMonitor();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
progressMonitor.startTask("Removing", ProgressMonitor.UNKNOWN);
|
||||
|
||||
boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove");
|
||||
if (ContributionManager.requiresRestart(contribution)) {
|
||||
|
||||
if (!doBackup || (doBackup && backupContribution(editor, contribution, false, statusBar))) {
|
||||
if (ContributionManager.setDeletionFlag(contribution)) {
|
||||
contribListing.replaceContribution(contribution, contribution);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean success = false;
|
||||
if (doBackup) {
|
||||
success = backupContribution(editor, contribution, true, statusBar);
|
||||
} else {
|
||||
Base.removeDir(contribution.getFolder());
|
||||
success = !contribution.getFolder().exists();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Contribution advertisedVersion =
|
||||
contribListing.getAdvertisedContribution(contribution);
|
||||
|
||||
if (advertisedVersion == null) {
|
||||
contribListing.removeContribution(contribution);
|
||||
} else {
|
||||
contribListing.replaceContribution(contribution,
|
||||
advertisedVersion);
|
||||
}
|
||||
} else {
|
||||
// There was a failure backing up the folder
|
||||
if (doBackup) {
|
||||
|
||||
} else {
|
||||
statusBar.setErrorMessage("Could not delete the contribution's files");
|
||||
}
|
||||
}
|
||||
}
|
||||
refreshInstalled(editor);
|
||||
progressMonitor.finished();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non-blocking call to download and install a contribution in a new thread.
|
||||
*
|
||||
@@ -117,12 +52,12 @@ public class ContributionManager {
|
||||
* old version of a contribution that is being updated). Must not be
|
||||
* null.
|
||||
*/
|
||||
static public void downloadAndInstall(final Editor editor,
|
||||
final URL url,
|
||||
final AdvertisedContribution ad,
|
||||
final JProgressMonitor downloadProgress,
|
||||
final JProgressMonitor installProgress,
|
||||
final ErrorWidget statusBar) {
|
||||
static void downloadAndInstall(final Editor editor,
|
||||
final URL url,
|
||||
final AvailableContribution ad,
|
||||
final JProgressMonitor downloadProgress,
|
||||
final JProgressMonitor installProgress,
|
||||
final ErrorWidget statusBar) {
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
@@ -137,7 +72,7 @@ public class ContributionManager {
|
||||
|
||||
if (!downloadProgress.isCanceled() && !downloadProgress.isError()) {
|
||||
installProgress.startTask("Installing...", ProgressMonitor.UNKNOWN);
|
||||
InstalledContribution contribution =
|
||||
LocalContribution contribution =
|
||||
ad.install(editor, contribZip, false, statusBar);
|
||||
|
||||
if (contribution != null) {
|
||||
@@ -200,39 +135,39 @@ public class ContributionManager {
|
||||
// }
|
||||
|
||||
|
||||
static InstalledContribution load(Base base, File folder, ContributionType type) {
|
||||
switch (type) {
|
||||
case LIBRARY:
|
||||
return new Library(folder);
|
||||
// case LIBRARY_COMPILATION:
|
||||
// return LibraryCompilation.create(folder);
|
||||
case TOOL:
|
||||
return ToolContribution.load(folder);
|
||||
case MODE:
|
||||
return ModeContribution.load(base, folder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static ArrayList<InstalledContribution> listContributions(ContributionType type, Editor editor) {
|
||||
ArrayList<InstalledContribution> contribs = new ArrayList<InstalledContribution>();
|
||||
switch (type) {
|
||||
case LIBRARY:
|
||||
contribs.addAll(editor.getMode().contribLibraries);
|
||||
break;
|
||||
// case LIBRARY_COMPILATION:
|
||||
// contribs.addAll(LibraryCompilation.list(editor.getMode().contribLibraries));
|
||||
// static InstalledContribution load(Base base, File folder, ContributionType type) {
|
||||
// switch (type) {
|
||||
// case LIBRARY:
|
||||
// return new Library(folder);
|
||||
//// case LIBRARY_COMPILATION:
|
||||
//// return LibraryCompilation.create(folder);
|
||||
// case TOOL:
|
||||
// return ToolContribution.load(folder);
|
||||
// case MODE:
|
||||
// return ModeContribution.load(base, folder);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// static ArrayList<InstalledContribution> listContributions(ContributionType type, Editor editor) {
|
||||
// ArrayList<InstalledContribution> contribs = new ArrayList<InstalledContribution>();
|
||||
// switch (type) {
|
||||
// case LIBRARY:
|
||||
// contribs.addAll(editor.getMode().contribLibraries);
|
||||
// break;
|
||||
case TOOL:
|
||||
contribs.addAll(editor.contribTools);
|
||||
break;
|
||||
case MODE:
|
||||
contribs.addAll(editor.getBase().getModeContribs());
|
||||
break;
|
||||
}
|
||||
return contribs;
|
||||
}
|
||||
//// case LIBRARY_COMPILATION:
|
||||
//// contribs.addAll(LibraryCompilation.list(editor.getMode().contribLibraries));
|
||||
//// break;
|
||||
// case TOOL:
|
||||
// contribs.addAll(editor.contribTools);
|
||||
// break;
|
||||
// case MODE:
|
||||
// contribs.addAll(editor.getBase().getModeContribs());
|
||||
// break;
|
||||
// }
|
||||
// return contribs;
|
||||
// }
|
||||
|
||||
|
||||
// static void initialize(InstalledContribution contribution, Base base) throws Exception {
|
||||
@@ -461,86 +396,31 @@ public class ContributionManager {
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Moves the given contribution to a backup folder.
|
||||
* @param doDeleteOriginal
|
||||
* true if the file should be moved to the directory, false if it
|
||||
* should instead be copied, leaving the original in place
|
||||
*/
|
||||
static public boolean backupContribution(Editor editor,
|
||||
InstalledContribution contribution,
|
||||
boolean doDeleteOriginal,
|
||||
ErrorWidget statusBar) {
|
||||
|
||||
File backupFolder = null;
|
||||
|
||||
switch (contribution.getType()) {
|
||||
case LIBRARY:
|
||||
// case LIBRARY_COMPILATION:
|
||||
backupFolder = createLibraryBackupFolder(editor, statusBar);
|
||||
break;
|
||||
case MODE:
|
||||
break;
|
||||
case TOOL:
|
||||
backupFolder = createToolBackupFolder(editor, statusBar);
|
||||
break;
|
||||
}
|
||||
|
||||
if (backupFolder == null) return false;
|
||||
|
||||
String libFolderName = contribution.getFolder().getName();
|
||||
|
||||
String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
||||
final String backupName = prefix + "_" + libFolderName;
|
||||
File backupSubFolder = ContributionManager.getUniqueName(backupFolder, backupName);
|
||||
|
||||
// try {
|
||||
// FileUtils.moveDirectory(lib.folder, backupFolderForLib);
|
||||
// return true;
|
||||
|
||||
boolean success = false;
|
||||
if (doDeleteOriginal) {
|
||||
success = contribution.getFolder().renameTo(backupSubFolder);
|
||||
} else {
|
||||
try {
|
||||
Base.copyDir(contribution.getFolder(), backupSubFolder);
|
||||
success = true;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
// } catch (IOException e) {
|
||||
if (!success) {
|
||||
statusBar.setErrorMessage("Could not move contribution to backup folder.");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static public File createLibraryBackupFolder(Editor editor, ErrorWidget logger) {
|
||||
File libraryBackupFolder = new File(Base.getSketchbookLibrariesFolder(), "old");
|
||||
return createBackupFolder(libraryBackupFolder, logger,
|
||||
"Could not create backup folder for library.");
|
||||
}
|
||||
|
||||
|
||||
static public File createToolBackupFolder(Editor editor, ErrorWidget logger) {
|
||||
File libraryBackupFolder = new File(Base.getSketchbookToolsFolder(), "old");
|
||||
return createBackupFolder(libraryBackupFolder, logger,
|
||||
"Could not create backup folder for tool.");
|
||||
}
|
||||
|
||||
|
||||
static private File createBackupFolder(File backupFolder,
|
||||
ErrorWidget logger,
|
||||
String errorMessage) {
|
||||
if (!backupFolder.exists() || !backupFolder.isDirectory()) {
|
||||
if (!backupFolder.mkdirs()) {
|
||||
logger.setErrorMessage(errorMessage);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return backupFolder;
|
||||
}
|
||||
// static public File createLibraryBackupFolder(Editor editor, ErrorWidget logger) {
|
||||
// File libraryBackupFolder = new File(Base.getSketchbookLibrariesFolder(), "old");
|
||||
// return createBackupFolder(libraryBackupFolder, logger,
|
||||
// "Could not create backup folder for library.");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// static public File createToolBackupFolder(Editor editor, ErrorWidget logger) {
|
||||
// File libraryBackupFolder = new File(Base.getSketchbookToolsFolder(), "old");
|
||||
// return createBackupFolder(libraryBackupFolder, logger,
|
||||
// "Could not create backup folder for tool.");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// static private File createBackupFolder(File backupFolder,
|
||||
// ErrorWidget logger,
|
||||
// String errorMessage) {
|
||||
// if (!backupFolder.exists() || !backupFolder.isDirectory()) {
|
||||
// if (!backupFolder.mkdirs()) {
|
||||
// logger.setErrorMessage(errorMessage);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// return backupFolder;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
@@ -640,83 +520,20 @@ public class ContributionManager {
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
|
||||
public static void unzip(File zipFile, File dest) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(zipFile);
|
||||
CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32());
|
||||
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum));
|
||||
ZipEntry next = null;
|
||||
while ((next = zis.getNextEntry()) != null) {
|
||||
File currentFile = new File(dest, next.getName());
|
||||
if (next.isDirectory()) {
|
||||
currentFile.mkdirs();
|
||||
} else {
|
||||
currentFile.createNewFile();
|
||||
ContributionManager.unzipEntry(zis, currentFile);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
static public void deleteFlagged() {
|
||||
deleteFlagged(Base.getSketchbookLibrariesFolder());
|
||||
deleteFlagged(Base.getSketchbookModesFolder());
|
||||
deleteFlagged(Base.getSketchbookToolsFolder());
|
||||
}
|
||||
|
||||
|
||||
private static void unzipEntry(ZipInputStream zin, File f) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
byte[] b = new byte[512];
|
||||
int len = 0;
|
||||
while ((len = zin.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if the type of contribution requires the PDE to restart
|
||||
* when being removed. */
|
||||
static public boolean requiresRestart(Contribution contrib) {
|
||||
return contrib.getType() == ContributionType.TOOL || contrib.getType() == ContributionType.MODE;
|
||||
}
|
||||
|
||||
|
||||
static public boolean setDeletionFlag(InstalledContribution contrib) {
|
||||
// Only returns false if the file already exists, so we can
|
||||
// ignore the return value.
|
||||
try {
|
||||
new File(contrib.getFolder(), DELETION_FLAG).createNewFile();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public boolean unsetDeletionFlag(InstalledContribution contrib) {
|
||||
return new File(contrib.getFolder(), DELETION_FLAG).delete();
|
||||
}
|
||||
|
||||
|
||||
static public boolean isDeletionFlagSet(Contribution contrib) {
|
||||
if (contrib instanceof InstalledContribution) {
|
||||
InstalledContribution installed = (InstalledContribution) contrib;
|
||||
return isDeletionFlagSet(installed.getFolder());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public boolean isDeletionFlagSet(File folder) {
|
||||
return new File(folder, DELETION_FLAG).exists();
|
||||
}
|
||||
|
||||
|
||||
static public void checkDeletions(File root) {
|
||||
|
||||
static private void deleteFlagged(File root) {
|
||||
File[] markedForDeletion = root.listFiles(new FileFilter() {
|
||||
public boolean accept(File folder) {
|
||||
return (folder.isDirectory() && isDeletionFlagSet(folder));
|
||||
return (folder.isDirectory() &&
|
||||
LocalContribution.isDeletionFlagged(folder));
|
||||
}
|
||||
});
|
||||
for (File folder : markedForDeletion) {
|
||||
|
||||
@@ -39,12 +39,11 @@ import processing.app.contrib.ContributionListing.Filter;
|
||||
|
||||
|
||||
public class ContributionManagerDialog {
|
||||
|
||||
static final String ANY_CATEGORY = "All";
|
||||
|
||||
JFrame dialog;
|
||||
String title;
|
||||
Filter permaFilter;
|
||||
Filter filter;
|
||||
JComboBox categoryChooser;
|
||||
JScrollPane scrollPane;
|
||||
ContributionListPanel contributionListPanel;
|
||||
@@ -57,14 +56,14 @@ public class ContributionManagerDialog {
|
||||
ContributionListing contribListing;
|
||||
|
||||
|
||||
public ContributionManagerDialog(String title,
|
||||
ContributionListing.Filter filter) {
|
||||
|
||||
this.title = title;
|
||||
this.permaFilter = filter;
|
||||
|
||||
public ContributionManagerDialog(ContributionType type) {
|
||||
if (type == null) {
|
||||
title = "Update Manager";
|
||||
} else {
|
||||
title = type.getTitle() + " Manager";
|
||||
}
|
||||
filter = ContributionListing.createFilter(type);
|
||||
contribListing = ContributionListing.getInstance();
|
||||
|
||||
contributionListPanel = new ContributionListPanel(this, filter);
|
||||
contribListing.addContributionListener(contributionListPanel);
|
||||
}
|
||||
@@ -116,10 +115,10 @@ public class ContributionManagerDialog {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateContributionListing();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the window after an OK or Cancel.
|
||||
*/
|
||||
@@ -127,6 +126,7 @@ public class ContributionManagerDialog {
|
||||
dialog.dispose();
|
||||
editor = null;
|
||||
}
|
||||
|
||||
|
||||
/** Creates and arranges the Swing components in the dialog. */
|
||||
private void createComponents() {
|
||||
@@ -243,12 +243,13 @@ public class ContributionManagerDialog {
|
||||
|
||||
dialog.setMinimumSize(new Dimension(450, 400));
|
||||
}
|
||||
|
||||
|
||||
private void updateCategoryChooser() {
|
||||
if (categoryChooser != null) {
|
||||
ArrayList<String> categories;
|
||||
categoryChooser.removeAllItems();
|
||||
categories = new ArrayList<String>(contribListing.getCategories(permaFilter));
|
||||
categories = new ArrayList<String>(contribListing.getCategories(filter));
|
||||
// for (int i = 0; i < categories.size(); i++) {
|
||||
// System.out.println(i + " category: " + categories.get(i));
|
||||
// }
|
||||
@@ -262,6 +263,7 @@ public class ContributionManagerDialog {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerDisposeListeners() {
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
@@ -289,19 +291,17 @@ public class ContributionManagerDialog {
|
||||
});
|
||||
}
|
||||
|
||||
public void filterLibraries(String category, List<String> filters) {
|
||||
|
||||
List<Contribution> filteredLibraries = contribListing
|
||||
.getFilteredLibraryList(category, filters);
|
||||
|
||||
|
||||
protected void filterLibraries(String category, List<String> filters) {
|
||||
List<Contribution> filteredLibraries =
|
||||
contribListing.getFilteredLibraryList(category, filters);
|
||||
contributionListPanel.filterLibraries(filteredLibraries);
|
||||
}
|
||||
|
||||
|
||||
protected void updateContributionListing() {
|
||||
if (editor == null)
|
||||
return;
|
||||
|
||||
ArrayList<Library> libraries = new ArrayList<Library>(editor.getMode().contribLibraries);
|
||||
if (editor != null) {
|
||||
ArrayList<Library> libraries = new ArrayList<Library>(editor.getMode().contribLibraries);
|
||||
// ArrayList<LibraryCompilation> compilations = LibraryCompilation.list(libraries);
|
||||
//
|
||||
// // Remove libraries from the list that are part of a compilations
|
||||
@@ -315,65 +315,63 @@ public class ContributionManagerDialog {
|
||||
// }
|
||||
// }
|
||||
|
||||
ArrayList<Contribution> contributions = new ArrayList<Contribution>();
|
||||
contributions.addAll(editor.contribTools);
|
||||
contributions.addAll(libraries);
|
||||
ArrayList<Contribution> contributions = new ArrayList<Contribution>();
|
||||
contributions.addAll(editor.contribTools);
|
||||
contributions.addAll(libraries);
|
||||
// contributions.addAll(compilations);
|
||||
|
||||
contribListing.updateInstalledList(contributions);
|
||||
contribListing.updateInstalledList(contributions);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFilterText(String filter) {
|
||||
|
||||
protected void setFilterText(String filter) {
|
||||
if (filter == null || filter.isEmpty()) {
|
||||
filterField.setText("");
|
||||
filterField.isShowingHint = true;
|
||||
filterField.showingHint = true;
|
||||
} else {
|
||||
filterField.setText(filter);
|
||||
filterField.isShowingHint = false;
|
||||
filterField.showingHint = false;
|
||||
}
|
||||
filterField.applyFilter();
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected JPanel getPlaceholder() {
|
||||
return contributionListPanel.statusPlaceholder;
|
||||
}
|
||||
|
||||
|
||||
class FilterField extends JTextField {
|
||||
|
||||
final static String filterHint = "Filter your search...";
|
||||
|
||||
boolean isShowingHint;
|
||||
|
||||
boolean showingHint;
|
||||
List<String> filters;
|
||||
|
||||
public FilterField () {
|
||||
super(filterHint);
|
||||
|
||||
isShowingHint = true;
|
||||
|
||||
|
||||
showingHint = true;
|
||||
filters = new ArrayList<String>();
|
||||
|
||||
updateStyle();
|
||||
|
||||
addFocusListener(new FocusListener() {
|
||||
|
||||
public void focusLost(FocusEvent focusEvent) {
|
||||
if (filterField.getText().isEmpty()) {
|
||||
isShowingHint = true;
|
||||
showingHint = true;
|
||||
}
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
public void focusGained(FocusEvent focusEvent) {
|
||||
if (isShowingHint) {
|
||||
isShowingHint = false;
|
||||
if (showingHint) {
|
||||
showingHint = false;
|
||||
filterField.setText("");
|
||||
}
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
});
|
||||
|
||||
getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
applyFilter();
|
||||
}
|
||||
@@ -399,11 +397,11 @@ public class ContributionManagerDialog {
|
||||
}
|
||||
|
||||
public String getFilterText() {
|
||||
return isShowingHint ? "" : getText();
|
||||
return showingHint ? "" : getText();
|
||||
}
|
||||
|
||||
public void updateStyle() {
|
||||
if (isShowingHint) {
|
||||
if (showingHint) {
|
||||
setText(filterHint);
|
||||
|
||||
// setForeground(UIManager.getColor("TextField.light")); // too light
|
||||
@@ -416,12 +414,13 @@ public class ContributionManagerDialog {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean hasAlreadyBeenOpened() {
|
||||
return dialog != null;
|
||||
}
|
||||
|
||||
|
||||
class StatusPanel extends JPanel implements ErrorWidget {
|
||||
|
||||
String errorMessage;
|
||||
|
||||
StatusPanel() {
|
||||
@@ -457,27 +456,22 @@ public class ContributionManagerDialog {
|
||||
errorMessage = message;
|
||||
setVisible(true);
|
||||
|
||||
JPanel placeholder = ContributionManagerDialog.this.contributionListPanel.statusPlaceholder;
|
||||
JPanel placeholder = getPlaceholder();
|
||||
Dimension d = getPreferredSize();
|
||||
if (Base.isWindows()) {
|
||||
d.height += 5;
|
||||
placeholder.setPreferredSize(d);
|
||||
}
|
||||
placeholder.setVisible(true);
|
||||
|
||||
// Rectangle rect = scrollPane.getViewport().getViewRect();
|
||||
// rect.x += d.height;
|
||||
// scrollPane.getViewport().scrollRectToVisible(rect);
|
||||
}
|
||||
|
||||
void clearErrorMessage() {
|
||||
errorMessage = null;
|
||||
repaint();
|
||||
|
||||
ContributionManagerDialog.this.contributionListPanel.statusPlaceholder
|
||||
.setVisible(false);
|
||||
getPlaceholder().setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,42 +22,53 @@
|
||||
package processing.app.contrib;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
import processing.app.Library;
|
||||
|
||||
public enum ContributionType {
|
||||
// LIBRARY, LIBRARY_COMPILATION, TOOL, MODE;
|
||||
LIBRARY, TOOL, MODE;
|
||||
LIBRARY, TOOL, MODE;
|
||||
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return "library";
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return "library";
|
||||
// case LIBRARY_COMPILATION:
|
||||
// return "compilation";
|
||||
case TOOL:
|
||||
return "tool";
|
||||
case MODE:
|
||||
return "mode";
|
||||
}
|
||||
return null; // should be unreachable
|
||||
};
|
||||
case TOOL:
|
||||
return "tool";
|
||||
case MODE:
|
||||
return "mode";
|
||||
}
|
||||
return null; // should be unreachable
|
||||
};
|
||||
|
||||
|
||||
/** Return Mode for mode, Tool for tool, etc. */
|
||||
public String getTitle() {
|
||||
String s = toString();
|
||||
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
|
||||
}
|
||||
|
||||
|
||||
public String getFolderName() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return "libraries";
|
||||
public String getFolderName() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return "libraries";
|
||||
// case LIBRARY_COMPILATION:
|
||||
// return "libraries";
|
||||
case TOOL:
|
||||
return "tools";
|
||||
case MODE:
|
||||
return "modes";
|
||||
}
|
||||
return null; // should be unreachable
|
||||
case TOOL:
|
||||
return "tools";
|
||||
case MODE:
|
||||
return "modes";
|
||||
}
|
||||
return null; // should be unreachable
|
||||
}
|
||||
|
||||
|
||||
// public String getPropertiesName() {
|
||||
@@ -65,39 +76,117 @@ public enum ContributionType {
|
||||
// }
|
||||
|
||||
|
||||
static public ContributionType fromName(String s) {
|
||||
if (s != null) {
|
||||
if ("library".equals(s.toLowerCase())) {
|
||||
return LIBRARY;
|
||||
}
|
||||
static public ContributionType fromName(String s) {
|
||||
if (s != null) {
|
||||
if ("library".equals(s.toLowerCase())) {
|
||||
return LIBRARY;
|
||||
}
|
||||
// if ("compilation".equals(s.toLowerCase())) {
|
||||
// return LIBRARY_COMPILATION;
|
||||
// }
|
||||
if ("tool".equals(s.toLowerCase())) {
|
||||
return TOOL;
|
||||
}
|
||||
if ("mode".equals(s.toLowerCase())) {
|
||||
return MODE;
|
||||
}
|
||||
if ("tool".equals(s.toLowerCase())) {
|
||||
return TOOL;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public File getSketchbookContribFolder() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return Base.getSketchbookLibrariesFolder();
|
||||
case TOOL:
|
||||
return Base.getSketchbookToolsFolder();
|
||||
case MODE:
|
||||
return Base.getSketchbookModesFolder();
|
||||
if ("mode".equals(s.toLowerCase())) {
|
||||
return MODE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// static public boolean validName(String s) {
|
||||
// return "library".equals(s) || "tool".equals(s) || "mode".equals(s);
|
||||
// }
|
||||
}
|
||||
|
||||
public File getSketchbookFolder() {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return Base.getSketchbookLibrariesFolder();
|
||||
case TOOL:
|
||||
return Base.getSketchbookToolsFolder();
|
||||
case MODE:
|
||||
return Base.getSketchbookModesFolder();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
boolean isCandidate(File potential) {
|
||||
return (potential.isDirectory() &&
|
||||
new File(potential, getFolderName()).exists());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of directories that have the necessary subfolder for this
|
||||
* contribution type. For instance, a list of folders that have a 'mode'
|
||||
* subfolder if this is a ModeContribution.
|
||||
*/
|
||||
File[] listCandidates(File folder) {
|
||||
return folder.listFiles(new FileFilter() {
|
||||
public boolean accept(File potential) {
|
||||
return isCandidate(potential);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the first directory that has the necessary subfolder for this
|
||||
* contribution type. For instance, the first folder that has a 'mode'
|
||||
* subfolder if this is a ModeContribution.
|
||||
*/
|
||||
File findCandidate(File folder) {
|
||||
File[] folders = listCandidates(folder);
|
||||
|
||||
if (folders.length == 0) {
|
||||
return null;
|
||||
|
||||
} else if (folders.length > 1) {
|
||||
Base.log("More than one " + toString() + " found inside " + folder.getAbsolutePath());
|
||||
}
|
||||
return folders[0];
|
||||
}
|
||||
|
||||
|
||||
LocalContribution load(Base base, File folder) {
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
return new Library(folder);
|
||||
case TOOL:
|
||||
return ToolContribution.load(folder);
|
||||
case MODE:
|
||||
return ModeContribution.load(base, folder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
ArrayList<LocalContribution> listContributions(Editor editor) {
|
||||
ArrayList<LocalContribution> contribs = new ArrayList<LocalContribution>();
|
||||
switch (this) {
|
||||
case LIBRARY:
|
||||
contribs.addAll(editor.getMode().contribLibraries);
|
||||
break;
|
||||
case TOOL:
|
||||
contribs.addAll(editor.contribTools);
|
||||
break;
|
||||
case MODE:
|
||||
contribs.addAll(editor.getBase().getModeContribs());
|
||||
break;
|
||||
}
|
||||
return contribs;
|
||||
}
|
||||
|
||||
|
||||
File createBackupFolder(ErrorWidget status) {
|
||||
File backupFolder = new File(getSketchbookFolder(), "old");
|
||||
if (!backupFolder.isDirectory()) {
|
||||
status.setErrorMessage("Remove the file named \"old\" from the " +
|
||||
getFolderName() + " folder in the sketchbook.");
|
||||
return null;
|
||||
}
|
||||
if (!backupFolder.exists() && !backupFolder.mkdirs()) {
|
||||
status.setErrorMessage("Could not create a " + toString() + " backup folder.");
|
||||
return null;
|
||||
}
|
||||
return backupFolder;
|
||||
}
|
||||
}
|
||||
+180
-62
@@ -24,6 +24,7 @@ package processing.app.contrib;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
@@ -32,27 +33,21 @@ import javax.swing.JOptionPane;
|
||||
import processing.app.*;
|
||||
|
||||
|
||||
public abstract class InstalledContribution extends Contribution {
|
||||
//public abstract class InstalledContribution implements Contribution {
|
||||
// protected String name; // "pdf" or "PDF Export"
|
||||
// protected String category; // "Sound"
|
||||
// protected String authorList; // Ben Fry
|
||||
// protected String url; // http://processing.org
|
||||
// protected String sentence; // Write graphics to PDF files.
|
||||
// protected String paragraph; // <paragraph length description for site>
|
||||
// protected int version; // 102
|
||||
// protected String prettyVersion; // "1.0.2"
|
||||
|
||||
protected String id; // 1
|
||||
protected int latestVersion; // 103
|
||||
/**
|
||||
* A contribution that has been downloaded to the disk, and may or may not
|
||||
* be installed.
|
||||
*/
|
||||
public abstract class LocalContribution extends Contribution {
|
||||
static public final String DELETION_FLAG = "flagged_for_deletion";
|
||||
|
||||
protected String id; // 1
|
||||
protected int latestVersion; // 103
|
||||
protected File folder;
|
||||
|
||||
protected HashMap<String, String> properties;
|
||||
|
||||
protected ClassLoader loader;
|
||||
|
||||
|
||||
public InstalledContribution(File folder) {
|
||||
public LocalContribution(File folder) {
|
||||
this.folder = folder;
|
||||
|
||||
// required for contributed modes, but not for built-in core modes
|
||||
@@ -149,62 +144,62 @@ public abstract class InstalledContribution extends Contribution {
|
||||
*/
|
||||
|
||||
|
||||
static protected boolean isCandidate(File potential, final ContributionType type) {
|
||||
return (potential.isDirectory() &&
|
||||
new File(potential, type.getFolderName()).exists());
|
||||
}
|
||||
// static protected boolean isCandidate(File potential, final ContributionType type) {
|
||||
// return (potential.isDirectory() &&
|
||||
// new File(potential, type.getFolderName()).exists());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Return a list of directories that have the necessary subfolder for this
|
||||
// * contribution type. For instance, a list of folders that have a 'mode'
|
||||
// * subfolder if this is a ModeContribution.
|
||||
// */
|
||||
// static protected File[] listCandidates(File folder, final ContributionType type) {
|
||||
// return folder.listFiles(new FileFilter() {
|
||||
// public boolean accept(File potential) {
|
||||
// return isCandidate(potential, type);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Return the first directory that has the necessary subfolder for this
|
||||
// * contribution type. For instance, the first folder that has a 'mode'
|
||||
// * subfolder if this is a ModeContribution.
|
||||
// */
|
||||
// static protected File findCandidate(File folder, final ContributionType type) {
|
||||
// File[] folders = listCandidates(folder, type);
|
||||
//
|
||||
// if (folders.length == 0) {
|
||||
// return null;
|
||||
//
|
||||
// } else if (folders.length > 1) {
|
||||
// Base.log("More than one " + type.toString() + " found inside " + folder.getAbsolutePath());
|
||||
// }
|
||||
// return folders[0];
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Return a list of directories that have the necessary subfolder for this
|
||||
* contribution type. For instance, a list of folders that have a 'mode'
|
||||
* subfolder if this is a ModeContribution.
|
||||
*/
|
||||
static protected File[] listCandidates(File folder, final ContributionType type) {
|
||||
return folder.listFiles(new FileFilter() {
|
||||
public boolean accept(File potential) {
|
||||
return isCandidate(potential, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the first directory that has the necessary subfolder for this
|
||||
* contribution type. For instance, the first folder that has a 'mode'
|
||||
* subfolder if this is a ModeContribution.
|
||||
*/
|
||||
static protected File findCandidate(File folder, final ContributionType type) {
|
||||
File[] folders = listCandidates(folder, type);
|
||||
|
||||
if (folders.length == 0) {
|
||||
return null;
|
||||
|
||||
} else if (folders.length > 1) {
|
||||
Base.log("More than one " + type.toString() + " found inside " + folder.getAbsolutePath());
|
||||
}
|
||||
return folders[0];
|
||||
}
|
||||
|
||||
|
||||
InstalledContribution moveAndLoad(Editor editor,
|
||||
LocalContribution moveAndLoad(Editor editor,
|
||||
boolean confirmReplace,
|
||||
ErrorWidget statusBar) {
|
||||
ArrayList<InstalledContribution> oldContribs =
|
||||
ContributionManager.listContributions(getType(), editor);
|
||||
ArrayList<LocalContribution> oldContribs =
|
||||
getType().listContributions(editor);
|
||||
|
||||
String contribFolderName = getFolder().getName();
|
||||
|
||||
File contribTypeFolder = getType().getSketchbookContribFolder();
|
||||
File contribTypeFolder = getType().getSketchbookFolder();
|
||||
File contribFolder = new File(contribTypeFolder, contribFolderName);
|
||||
|
||||
for (InstalledContribution oldContrib : oldContribs) {
|
||||
for (LocalContribution oldContrib : oldContribs) {
|
||||
if ((oldContrib.getFolder().exists() && oldContrib.getFolder().equals(contribFolder)) ||
|
||||
(oldContrib.getId() != null && oldContrib.getId().equals(getId()))) {
|
||||
|
||||
if (ContributionManager.requiresRestart(oldContrib)) {
|
||||
if (oldContrib.requiresRestart()) {
|
||||
// XXX: We can't replace stuff, soooooo.... do something different
|
||||
if (!ContributionManager.backupContribution(editor, oldContrib, false, statusBar)) {
|
||||
if (!oldContrib.backup(editor, false, statusBar)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
@@ -218,7 +213,7 @@ public abstract class InstalledContribution extends Contribution {
|
||||
"has been found in your sketchbook. Clicking “Yes”<br>"+
|
||||
"will move the existing library to a backup folder<br>" +
|
||||
" in <i>libraries/old</i> before replacing it.");
|
||||
if (result != JOptionPane.YES_OPTION || !ContributionManager.backupContribution(editor, oldContrib, true, statusBar)) {
|
||||
if (result != JOptionPane.YES_OPTION || !oldContrib.backup(editor, true, statusBar)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
@@ -233,7 +228,7 @@ public abstract class InstalledContribution extends Contribution {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((doBackup && !ContributionManager.backupContribution(editor, oldContrib, true, statusBar)) ||
|
||||
if ((doBackup && !oldContrib.backup(editor, true, statusBar)) ||
|
||||
(!doBackup && !oldContrib.getFolder().delete())) {
|
||||
return null;
|
||||
}
|
||||
@@ -252,10 +247,106 @@ public abstract class InstalledContribution extends Contribution {
|
||||
" \"" + getName() + "\" to the sketchbook.");
|
||||
return null;
|
||||
}
|
||||
return ContributionManager.load(editor.getBase(), contribFolder, getType());
|
||||
return getType().load(editor.getBase(), contribFolder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the given contribution to a backup folder.
|
||||
* @param deleteOriginal
|
||||
* true if the file should be moved to the directory, false if it
|
||||
* should instead be copied, leaving the original in place
|
||||
*/
|
||||
boolean backup(Editor editor, boolean deleteOriginal, ErrorWidget status) {
|
||||
|
||||
boolean success = false;
|
||||
File backupFolder = getType().createBackupFolder(status);
|
||||
|
||||
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);
|
||||
|
||||
if (deleteOriginal) {
|
||||
success = getFolder().renameTo(backupSubFolder);
|
||||
} else {
|
||||
try {
|
||||
Base.copyDir(getFolder(), backupSubFolder);
|
||||
success = true;
|
||||
} catch (IOException e) { }
|
||||
}
|
||||
if (!success) {
|
||||
status.setErrorMessage("Could not move contribution to backup folder.");
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non-blocking call to remove a contribution in a new thread.
|
||||
*/
|
||||
void removeContribution(final Editor editor,
|
||||
final ProgressMonitor pm,
|
||||
final ErrorWidget statusBar) {
|
||||
// final ContributionListing contribListing = ContributionListing.getInstance();
|
||||
// final ProgressMonitor progressMonitor = ;
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
remove(editor,
|
||||
(pm != null) ? pm : new NullProgressMonitor(),
|
||||
statusBar,
|
||||
ContributionListing.getInstance());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
void remove(final Editor editor,
|
||||
final ProgressMonitor pm,
|
||||
final ErrorWidget statusBar,
|
||||
final ContributionListing contribListing) {
|
||||
pm.startTask("Removing", ProgressMonitor.UNKNOWN);
|
||||
|
||||
boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove");
|
||||
if (requiresRestart()) {
|
||||
if (!doBackup || (doBackup && backup(editor, false, statusBar))) {
|
||||
if (setDeletionFlag()) {
|
||||
contribListing.replaceContribution(this, this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean success = false;
|
||||
if (doBackup) {
|
||||
success = backup(editor, true, statusBar);
|
||||
} else {
|
||||
Base.removeDir(getFolder());
|
||||
success = !getFolder().exists();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Contribution advertisedVersion =
|
||||
contribListing.getAdvertisedContribution(this);
|
||||
|
||||
if (advertisedVersion == null) {
|
||||
contribListing.removeContribution(this);
|
||||
} else {
|
||||
contribListing.replaceContribution(this, advertisedVersion);
|
||||
}
|
||||
} else {
|
||||
// There was a failure backing up the folder
|
||||
if (!doBackup) {
|
||||
statusBar.setErrorMessage("Could not delete the contribution's files");
|
||||
}
|
||||
}
|
||||
}
|
||||
ContributionManager.refreshInstalled(editor);
|
||||
pm.finished();
|
||||
}
|
||||
|
||||
|
||||
public File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
@@ -264,6 +355,33 @@ public abstract class InstalledContribution extends Contribution {
|
||||
public boolean isInstalled() {
|
||||
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() {
|
||||
@@ -30,7 +30,7 @@ import processing.app.Base;
|
||||
import processing.app.Mode;
|
||||
|
||||
|
||||
public class ModeContribution extends InstalledContribution {
|
||||
public class ModeContribution extends LocalContribution {
|
||||
private Mode mode;
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ModeContribution extends InstalledContribution {
|
||||
for (ModeContribution contrib : contribModes) {
|
||||
existing.put(contrib.getFolder(), contrib);
|
||||
}
|
||||
File[] potential = listCandidates(modesFolder, ContributionType.MODE);
|
||||
File[] potential = ContributionType.MODE.listCandidates(modesFolder);
|
||||
for (File folder : potential) {
|
||||
if (!existing.containsKey(folder)) {
|
||||
try {
|
||||
|
||||
@@ -88,9 +88,9 @@ public interface ProgressMonitor {
|
||||
* task was cancelled.
|
||||
*/
|
||||
public void finished();
|
||||
|
||||
}
|
||||
|
||||
|
||||
abstract class AbstractProgressMonitor implements ProgressMonitor {
|
||||
boolean isCanceled = false;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import processing.app.Editor;
|
||||
import processing.app.tools.Tool;
|
||||
|
||||
|
||||
public class ToolContribution extends InstalledContribution implements Tool {
|
||||
public class ToolContribution extends LocalContribution implements Tool {
|
||||
private Tool tool;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public class ToolContribution extends InstalledContribution implements Tool {
|
||||
|
||||
|
||||
static public ArrayList<ToolContribution> loadAll(File toolsFolder) {
|
||||
File[] list = listCandidates(toolsFolder, ContributionType.TOOL);
|
||||
File[] list = ContributionType.TOOL.listCandidates(toolsFolder);
|
||||
ArrayList<ToolContribution> outgoing = new ArrayList<ToolContribution>();
|
||||
for (File folder : list) {
|
||||
try {
|
||||
|
||||
@@ -653,6 +653,11 @@ public class PShape implements PConstants {
|
||||
}
|
||||
|
||||
fill = false;
|
||||
fillColor = 0x0;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -665,6 +670,10 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(rgb);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -677,6 +686,10 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(rgb, alpha);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -689,6 +702,10 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(gray);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -701,6 +718,15 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(gray, alpha);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambient(fillColor);
|
||||
setAmbient = false;
|
||||
}
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -713,6 +739,10 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(x, y, z);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -725,6 +755,10 @@ public class PShape implements PConstants {
|
||||
fill = true;
|
||||
colorCalc(x, y, z, a);
|
||||
fillColor = calcColor;
|
||||
|
||||
if (!setAmbient) {
|
||||
ambientColor = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,8 +61,6 @@ import processing.event.MouseEvent;
|
||||
|
||||
import com.jogamp.newt.awt.NewtCanvasAWT;
|
||||
import com.jogamp.newt.event.InputEvent;
|
||||
import com.jogamp.newt.event.WindowEvent;
|
||||
import com.jogamp.newt.event.WindowUpdateEvent;
|
||||
import com.jogamp.newt.opengl.GLWindow;
|
||||
import com.jogamp.opengl.FBObject;
|
||||
import com.jogamp.opengl.util.AnimatorBase;
|
||||
@@ -630,6 +628,7 @@ public class PGL {
|
||||
canvasAWT = new GLCanvas(caps);
|
||||
canvasAWT.setBounds(0, 0, pg.width, pg.height);
|
||||
canvasAWT.setBackground(new Color(pg.backgroundColor, true));
|
||||
canvasAWT.setFocusable(true);
|
||||
|
||||
pg.parent.setLayout(new BorderLayout());
|
||||
pg.parent.add(canvasAWT, BorderLayout.CENTER);
|
||||
@@ -651,9 +650,7 @@ public class PGL {
|
||||
canvasNEWT = new NewtCanvasAWT(window);
|
||||
canvasNEWT.setBounds(0, 0, pg.width, pg.height);
|
||||
canvasNEWT.setBackground(new Color(pg.backgroundColor, true));
|
||||
|
||||
pg.parent.setLayout(new BorderLayout());
|
||||
pg.parent.add(canvasNEWT, BorderLayout.CENTER);
|
||||
canvasNEWT.setFocusable(true);
|
||||
|
||||
NEWTMouseListener mouseListener = new NEWTMouseListener();
|
||||
window.addMouseListener(mouseListener);
|
||||
@@ -663,6 +660,9 @@ public class PGL {
|
||||
window.addWindowListener(winListener);
|
||||
canvasNEWT.addFocusListener(pg.parent); // So focus detection work.
|
||||
|
||||
pg.parent.setLayout(new BorderLayout());
|
||||
pg.parent.add(canvasNEWT, BorderLayout.CENTER);
|
||||
|
||||
capabilities = window.getChosenGLCapabilities();
|
||||
canvas = canvasNEWT;
|
||||
canvasAWT = null;
|
||||
@@ -3237,6 +3237,7 @@ public class PGL {
|
||||
|
||||
protected void nativeMouseEvent(com.jogamp.newt.event.MouseEvent nativeEvent,
|
||||
int peAction) {
|
||||
// if (!hasFocus) return;
|
||||
int modifiers = nativeEvent.getModifiers();
|
||||
int peModifiers = modifiers &
|
||||
(InputEvent.SHIFT_MASK |
|
||||
@@ -3296,31 +3297,44 @@ public class PGL {
|
||||
pg.parent.postEvent(ke);
|
||||
}
|
||||
|
||||
boolean hasFocus = true;
|
||||
class NEWTWindowListener implements com.jogamp.newt.event.WindowListener {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent arg0) {
|
||||
public void windowGainedFocus(com.jogamp.newt.event.WindowEvent arg0) {
|
||||
PApplet.println("window gained focus");
|
||||
pg.parent.focusGained(null);
|
||||
hasFocus = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowLostFocus(WindowEvent arg0) {
|
||||
public void windowLostFocus(com.jogamp.newt.event.WindowEvent arg0) {
|
||||
PApplet.println("window lost focus");
|
||||
pg.parent.focusLost(null);
|
||||
hasFocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDestroyNotify(WindowEvent arg0) { }
|
||||
public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) {
|
||||
PApplet.println("destroy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDestroyed(WindowEvent arg0) { }
|
||||
public void windowDestroyed(com.jogamp.newt.event.WindowEvent arg0) {
|
||||
PApplet.println("destroyed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowMoved(WindowEvent arg0) { }
|
||||
public void windowMoved(com.jogamp.newt.event.WindowEvent arg0) {
|
||||
PApplet.println("moved");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowRepaint(WindowUpdateEvent arg0) { }
|
||||
public void windowRepaint(com.jogamp.newt.event.WindowUpdateEvent arg0) {
|
||||
PApplet.println("window repaint");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowResized(WindowEvent arg0) { }
|
||||
public void windowResized(com.jogamp.newt.event.WindowEvent arg0) { }
|
||||
}
|
||||
|
||||
// NEWT mouse listener
|
||||
|
||||
@@ -389,7 +389,7 @@ public class PGraphics2D extends PGraphicsOpenGL {
|
||||
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
|
||||
shape.setKind(ELLIPSE);
|
||||
} else if (kind == ARC) {
|
||||
if (len != 6) {
|
||||
if (len != 6 && len != 7) {
|
||||
showWarning("Wrong number of parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ public class PGraphics3D extends PGraphicsOpenGL {
|
||||
shape = new PShapeOpenGL(parent, PShape.PRIMITIVE);
|
||||
shape.setKind(ELLIPSE);
|
||||
} else if (kind == ARC) {
|
||||
if (len != 6) {
|
||||
if (len != 6 && len != 7) {
|
||||
showWarning("Wrong number of parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -4971,8 +4971,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
// color buffer into it.
|
||||
@Override
|
||||
public void loadPixels() {
|
||||
if (sized) {
|
||||
// Something wrong going on with threading, sized can never be true if the
|
||||
if (primarySurface && sized) {
|
||||
// Something wrong going on with threading, sized can never be true if
|
||||
// all the steps in a resize happen inside the Animation thread.
|
||||
return;
|
||||
}
|
||||
@@ -5397,6 +5397,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
textureMode = NORMAL;
|
||||
boolean prevStroke = stroke;
|
||||
stroke = false;
|
||||
// int prevBlendMode = blendMode;
|
||||
// blendMode(REPLACE);
|
||||
PolyTexShader prevTexShader = polyTexShader;
|
||||
polyTexShader = (PolyTexShader) shader;
|
||||
beginShape(QUADS);
|
||||
@@ -5414,6 +5416,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
stroke = prevStroke;
|
||||
lights = prevLights;
|
||||
textureMode = prevTextureMode;
|
||||
// blendMode(prevBlendMode);
|
||||
|
||||
if (!hints[DISABLE_DEPTH_TEST]) {
|
||||
pgl.enable(PGL.DEPTH_TEST);
|
||||
|
||||
@@ -3416,7 +3416,7 @@ public class PShapeOpenGL extends PShape {
|
||||
d = params[3];
|
||||
}
|
||||
|
||||
ellipseMode = CORNER;
|
||||
// ellipseMode = CORNER;
|
||||
inGeo.setMaterial(fillColor, strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininess);
|
||||
inGeo.setNormal(normalX, normalY, normalZ);
|
||||
@@ -3428,20 +3428,24 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void tessellateArc() {
|
||||
float a = 0, b = 0, c = 0, d = 0;
|
||||
float start = 0, stop = 0;
|
||||
if (params.length == 6) {
|
||||
int mode = 0;
|
||||
if (params.length == 6 || params.length == 7) {
|
||||
a = params[0];
|
||||
b = params[1];
|
||||
c = params[2];
|
||||
d = params[3];
|
||||
start = params[4];
|
||||
stop = params[5];
|
||||
if (params.length == 7) {
|
||||
mode = (int)(params[6]);
|
||||
}
|
||||
}
|
||||
|
||||
ellipseMode = CORNER;
|
||||
// ellipseMode = CORNER;
|
||||
inGeo.setMaterial(fillColor, strokeColor, strokeWeight,
|
||||
ambientColor, specularColor, emissiveColor, shininess);
|
||||
inGeo.setNormal(normalX, normalY, normalZ);
|
||||
inGeo.addArc(a, b, c, d, start, stop, fill, stroke, ellipseMode);
|
||||
inGeo.addArc(a, b, c, d, start, stop, fill, stroke, mode);
|
||||
tessellator.tessellateTriangleFan();
|
||||
}
|
||||
|
||||
@@ -4432,8 +4436,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyVertices(int offset, int size) {
|
||||
tessGeo.updatePolyVerticesBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyVertex);
|
||||
tessGeo.polyVerticesBuffer.position(4 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT,
|
||||
4 * size * PGL.SIZEOF_FLOAT, tessGeo.polyVerticesBuffer);
|
||||
tessGeo.polyVerticesBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4441,8 +4447,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyColors(int offset, int size) {
|
||||
tessGeo.updatePolyColorsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyColor);
|
||||
tessGeo.polyColorsBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT, tessGeo.polyColorsBuffer);
|
||||
tessGeo.polyColorsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4450,8 +4458,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyNormals(int offset, int size) {
|
||||
tessGeo.updatePolyNormalsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyNormal);
|
||||
tessGeo.polyNormalsBuffer.position(3 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 3 * offset * PGL.SIZEOF_FLOAT,
|
||||
3 * size * PGL.SIZEOF_FLOAT, tessGeo.polyNormalsBuffer);
|
||||
tessGeo.polyNormalsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4459,8 +4469,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyTexcoords(int offset, int size) {
|
||||
tessGeo.updatePolyTexcoordsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyTexcoord);
|
||||
tessGeo.polyTexcoordsBuffer.position(2 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT,
|
||||
2 * size * PGL.SIZEOF_FLOAT, tessGeo.polyTexcoordsBuffer);
|
||||
tessGeo.polyTexcoordsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4468,8 +4480,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyAmbient(int offset, int size) {
|
||||
tessGeo.updatePolyAmbientBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyAmbient);
|
||||
tessGeo.polyAmbientBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT, tessGeo.polyAmbientBuffer);
|
||||
tessGeo.polyAmbientBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4477,8 +4491,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolySpecular(int offset, int size) {
|
||||
tessGeo.updatePolySpecularBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolySpecular);
|
||||
tessGeo.polySpecularBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT, tessGeo.polySpecularBuffer);
|
||||
tessGeo.polySpecularBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4486,8 +4502,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyEmissive(int offset, int size) {
|
||||
tessGeo.updatePolyEmissiveBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyEmissive);
|
||||
tessGeo.polyEmissiveBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT, tessGeo.polyEmissiveBuffer);
|
||||
tessGeo.polyEmissiveBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4495,8 +4513,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPolyShininess(int offset, int size) {
|
||||
tessGeo.updatePolyShininessBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyShininess);
|
||||
tessGeo.polyShininessBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_FLOAT,
|
||||
size * PGL.SIZEOF_FLOAT, tessGeo.polyShininessBuffer);
|
||||
tessGeo.polyShininessBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4504,8 +4524,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyLineVertices(int offset, int size) {
|
||||
tessGeo.updateLineVerticesBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glLineVertex);
|
||||
tessGeo.lineVerticesBuffer.position(4 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT,
|
||||
4 * size * PGL.SIZEOF_FLOAT, tessGeo.lineVerticesBuffer);
|
||||
tessGeo.lineVerticesBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4513,8 +4535,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyLineColors(int offset, int size) {
|
||||
tessGeo.updateLineColorsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glLineColor);
|
||||
tessGeo.lineColorsBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT, tessGeo.lineColorsBuffer);
|
||||
tessGeo.lineColorsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4522,8 +4546,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyLineAttributes(int offset, int size) {
|
||||
tessGeo.updateLineAttribsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glLineAttrib);
|
||||
tessGeo.lineAttribsBuffer.position(4 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT,
|
||||
4 * size * PGL.SIZEOF_FLOAT, tessGeo.lineAttribsBuffer);
|
||||
tessGeo.lineAttribsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4531,8 +4557,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPointVertices(int offset, int size) {
|
||||
tessGeo.updatePointVerticesBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPointVertex);
|
||||
tessGeo.pointVerticesBuffer.position(4 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 4 * offset * PGL.SIZEOF_FLOAT,
|
||||
4 * size * PGL.SIZEOF_FLOAT, tessGeo.pointVerticesBuffer);
|
||||
tessGeo.pointVerticesBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4540,8 +4568,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPointColors(int offset, int size) {
|
||||
tessGeo.updatePointColorsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPointColor);
|
||||
tessGeo.pointColorsBuffer.position(offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, offset * PGL.SIZEOF_INT,
|
||||
size * PGL.SIZEOF_INT,tessGeo.pointColorsBuffer);
|
||||
tessGeo.pointColorsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -4549,8 +4579,10 @@ public class PShapeOpenGL extends PShape {
|
||||
protected void copyPointAttributes(int offset, int size) {
|
||||
tessGeo.updatePointAttribsBuffer(offset, size);
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, glPointAttrib);
|
||||
tessGeo.pointAttribsBuffer.position(2 * offset);
|
||||
pgl.bufferSubData(PGL.ARRAY_BUFFER, 2 * offset * PGL.SIZEOF_FLOAT,
|
||||
2 * size * PGL.SIZEOF_FLOAT, tessGeo.pointAttribsBuffer);
|
||||
tessGeo.pointAttribsBuffer.rewind();
|
||||
pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +328,6 @@ public class Texture implements PConstants {
|
||||
|
||||
public void set(int[] pixels, int x, int y, int w, int h, int format) {
|
||||
if (pixels == null) {
|
||||
pixels = null;
|
||||
PGraphics.showWarning("The pixels array is null.");
|
||||
return;
|
||||
}
|
||||
@@ -1283,6 +1282,9 @@ public class Texture implements PConstants {
|
||||
// FBO copy:
|
||||
pg.pushFramebuffer();
|
||||
pg.setFramebuffer(tempFbo);
|
||||
// Clear the color buffer to make sure that the alpha of the
|
||||
pgl.clearColor(0, 0, 0, 0);
|
||||
pgl.clear(PGL.COLOR_BUFFER_BIT);
|
||||
if (scale) {
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
|
||||
@@ -73,6 +73,13 @@ A https://github.com/processing/processing/issues/1598
|
||||
X http://code.google.com/p/processing/issues/detail?id=1560
|
||||
A disable stroke perspective by default (but this didn't fix it)
|
||||
A fixed the disappearance, though still imperfect
|
||||
A Fix get()/set() problems with images and OpenGL
|
||||
A https://github.com/processing/processing/issues/1613
|
||||
X http://code.google.com/p/processing/issues/detail?id=1575
|
||||
o arc with large strokeWeight is very slow in P2D renderer
|
||||
A marked WontFix, workaround is to create a PShape
|
||||
A https://github.com/processing/processing/issues/1583
|
||||
A http://code.google.com/p/processing/issues/detail?id=1545
|
||||
|
||||
cleaning/earlier
|
||||
C textureWrap() CLAMP and REPEAT now added
|
||||
|
||||
Executable → Regular
+32
-31
@@ -6,63 +6,63 @@
|
||||
*/
|
||||
|
||||
int cuantos = 16000;
|
||||
pelo[] lista ;
|
||||
float[] z = new float[cuantos];
|
||||
float[] phi = new float[cuantos];
|
||||
float[] largos = new float[cuantos];
|
||||
Pelo[] lista ;
|
||||
float radio = 200;
|
||||
float rx = 0;
|
||||
float ry =0;
|
||||
|
||||
void setup() {
|
||||
size(1024, 768, P3D);
|
||||
noSmooth();
|
||||
frameRate(120);
|
||||
|
||||
radio = height/3.5;
|
||||
|
||||
lista = new pelo[cuantos];
|
||||
for (int i=0; i<cuantos; i++){
|
||||
lista[i] = new pelo();
|
||||
|
||||
lista = new Pelo[cuantos];
|
||||
for (int i = 0; i < lista.length; i++) {
|
||||
lista[i] = new Pelo();
|
||||
}
|
||||
noiseDetail(3);
|
||||
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
translate(width/2,height/2);
|
||||
|
||||
float rxp = (mouseX-(width/2)) * 0.005;
|
||||
float ryp = (mouseY-(height/2)) * 0.005;
|
||||
rx = rx*0.9 + rxp*0.1;
|
||||
ry = ry*0.9 + ryp*0.1;
|
||||
|
||||
float rxp = ((mouseX-(width/2))*0.005);
|
||||
float ryp = ((mouseY-(height/2))*0.005);
|
||||
rx = (rx*0.9)+(rxp*0.1);
|
||||
ry = (ry*0.9)+(ryp*0.1);
|
||||
translate(width/2, height/2);
|
||||
rotateY(rx);
|
||||
rotateX(ry);
|
||||
fill(0);
|
||||
noStroke();
|
||||
sphere(radio);
|
||||
|
||||
for (int i=0;i<cuantos;i++){
|
||||
for (int i = 0; i < lista.length; i++) {
|
||||
lista[i].dibujar();
|
||||
|
||||
}
|
||||
if (frameCount % 10 == 0) {
|
||||
println(frameRate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class pelo
|
||||
class Pelo
|
||||
{
|
||||
float z = random(-radio,radio);
|
||||
float z = random(-radio, radio);
|
||||
float phi = random(TWO_PI);
|
||||
float largo = random(1.15,1.2);
|
||||
float largo = random(1.15, 1.2);
|
||||
float theta = asin(z/radio);
|
||||
|
||||
void dibujar(){
|
||||
Pelo() { // what's wrong with a constructor here
|
||||
z = random(-radio, radio);
|
||||
phi = random(TWO_PI);
|
||||
largo = random(1.15, 1.2);
|
||||
theta = asin(z/radio);
|
||||
}
|
||||
|
||||
float off = (noise(millis() * 0.0005,sin(phi))-0.5) * 0.3;
|
||||
float offb = (noise(millis() * 0.0007,sin(z) * 0.01)-0.5) * 0.3;
|
||||
void dibujar() {
|
||||
|
||||
float off = (noise(millis() * 0.0005, sin(phi))-0.5) * 0.3;
|
||||
float offb = (noise(millis() * 0.0007, sin(z) * 0.01)-0.5) * 0.3;
|
||||
|
||||
float thetaff = theta+off;
|
||||
float phff = phi+offb;
|
||||
@@ -77,13 +77,14 @@ class pelo
|
||||
float xb = xo * largo;
|
||||
float yb = yo * largo;
|
||||
float zb = zo * largo;
|
||||
|
||||
|
||||
strokeWeight(1);
|
||||
beginShape(LINES);
|
||||
stroke(0);
|
||||
vertex(x,y,z);
|
||||
stroke(200,150);
|
||||
vertex(xb,yb,zb);
|
||||
vertex(x, y, z);
|
||||
stroke(200, 150);
|
||||
vertex(xb, yb, zb);
|
||||
endShape();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,17 +45,15 @@ void setup() {
|
||||
// Make a primitive (Rectangle) PShape
|
||||
PShape rectangle = createShape(RECT,-10,-10,20,20);
|
||||
rectangle.setFill(false);
|
||||
rectangle.setStroke(255);
|
||||
rectangle.setStroke(color(255));
|
||||
|
||||
// Add them all to the group
|
||||
group.addChild(star);
|
||||
group.addChild(path);
|
||||
group.addChild(rectangle); // Rectangle is missing???
|
||||
|
||||
group.addChild(rectangle);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
// We can access them individually via the group PShape
|
||||
PShape rectangle = group.getChild(2);
|
||||
// Shapes can be rotated
|
||||
|
||||
Reference in New Issue
Block a user