mirror of
https://github.com/processing/processing4.git
synced 2026-02-12 01:50:44 +01:00
Support for tools in the contribution manager.
This commit is contained in:
@@ -1683,6 +1683,11 @@ public class Base {
|
||||
}
|
||||
|
||||
|
||||
public File getSketchbookToolsFolder() {
|
||||
return new File(sketchbookFolder, "tools");
|
||||
}
|
||||
|
||||
|
||||
static protected File getDefaultSketchbookFolder() {
|
||||
File sketchbookFolder = null;
|
||||
try {
|
||||
|
||||
@@ -100,21 +100,13 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib
|
||||
|
||||
public void contributionAdded(ContributionInfo contributionInfo) {
|
||||
|
||||
if (setupProgressBar.isVisible()) {
|
||||
setupProgressBar.setVisible(false);
|
||||
}
|
||||
setupProgressBar.setVisible(false);
|
||||
|
||||
if (contributionPanelsByInfo.containsKey(contributionInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContributionPanel newPanel = null;
|
||||
if (contributionInfo.getType() == ContributionType.LIBRARY) {
|
||||
newPanel = new ContributionPanel();
|
||||
|
||||
} else if (contributionInfo.getType() == ContributionType.LIBRARY_COMPILATION) {
|
||||
newPanel = new ContributionPanel();
|
||||
}
|
||||
ContributionPanel newPanel = new ContributionPanel();
|
||||
|
||||
synchronized (contributionPanelsByInfo) {
|
||||
contributionPanelsByInfo.put(contributionInfo, newPanel);
|
||||
|
||||
@@ -37,6 +37,7 @@ import processing.app.Contribution.ContributionInfo.Author;
|
||||
import processing.app.Contribution.ContributionInfo.ContributionType;
|
||||
import processing.app.Library.LibraryInfo;
|
||||
import processing.app.LibraryCompilation.LibraryCompilationInfo;
|
||||
import processing.app.ToolContribution.ToolInfo;
|
||||
|
||||
public class ContributionListing {
|
||||
|
||||
@@ -141,21 +142,21 @@ public class ContributionListing {
|
||||
notifyChange(oldLib, newLib);
|
||||
}
|
||||
|
||||
public void addContribution(ContributionInfo libInfo) {
|
||||
public void addContribution(ContributionInfo info) {
|
||||
|
||||
if (librariesByCategory.containsKey(libInfo.category)) {
|
||||
List<ContributionInfo> list = librariesByCategory.get(libInfo.category);
|
||||
list.add(libInfo);
|
||||
if (librariesByCategory.containsKey(info.category)) {
|
||||
List<ContributionInfo> list = librariesByCategory.get(info.category);
|
||||
list.add(info);
|
||||
|
||||
Collections.sort(list);
|
||||
} else {
|
||||
ArrayList<ContributionInfo> libs = new ArrayList<ContributionInfo>();
|
||||
libs.add(libInfo);
|
||||
librariesByCategory.put(libInfo.category, libs);
|
||||
ArrayList<ContributionInfo> list = new ArrayList<ContributionInfo>();
|
||||
list.add(info);
|
||||
librariesByCategory.put(info.category, list);
|
||||
}
|
||||
allLibraries.add(libInfo);
|
||||
allLibraries.add(info);
|
||||
|
||||
notifyAdd(libInfo);
|
||||
notifyAdd(info);
|
||||
|
||||
Collections.sort(allLibraries);
|
||||
}
|
||||
@@ -361,7 +362,12 @@ public class ContributionListing {
|
||||
*/
|
||||
private static class ContributionXmlParser extends DefaultHandler {
|
||||
|
||||
ArrayList<ContributionInfo> libraries;
|
||||
final static String LIBRARY_TAG = "library";
|
||||
final static String LIBRARY_COMPILATION_TAG = "librarycompilation";
|
||||
final static String TOOL_TAG = "tool";
|
||||
//final static String MODE_TAG = "mode";
|
||||
|
||||
ArrayList<ContributionInfo> contributions;
|
||||
|
||||
String currentCategoryName;
|
||||
|
||||
@@ -376,7 +382,7 @@ public class ContributionListing {
|
||||
|
||||
InputSource input = new InputSource(new FileReader(xmlFile));
|
||||
|
||||
libraries = new ArrayList<ContributionInfo>();
|
||||
contributions = new ArrayList<ContributionInfo>();
|
||||
sp.parse(input, this); // throws SAXException
|
||||
|
||||
} catch (ParserConfigurationException e) {
|
||||
@@ -393,12 +399,12 @@ public class ContributionListing {
|
||||
"The list of libraries downloaded from Processing.org\n" +
|
||||
"appears to be malformed. You can still install libraries\n" +
|
||||
"manually while we work on fixing this.", e);
|
||||
libraries = null;
|
||||
contributions = null;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<ContributionInfo> getLibraries() {
|
||||
return libraries;
|
||||
return contributions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,11 +414,11 @@ public class ContributionListing {
|
||||
if ("category".equals(qName)) {
|
||||
currentCategoryName = attributes.getValue("name");
|
||||
|
||||
} else if ("library".equals(qName)) {
|
||||
} else if (LIBRARY_TAG.equals(qName)) {
|
||||
currentInfo = new LibraryInfo();
|
||||
setCommonAttributes(attributes);
|
||||
|
||||
} else if ("librarycompilation".equals(qName)) {
|
||||
} else if (LIBRARY_COMPILATION_TAG.equals(qName)) {
|
||||
LibraryCompilationInfo compilationInfo = new LibraryCompilationInfo();
|
||||
String[] names = attributes.getValue("libraryNames").split(";");
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
@@ -422,6 +428,10 @@ public class ContributionListing {
|
||||
currentInfo = compilationInfo;
|
||||
setCommonAttributes(attributes);
|
||||
|
||||
} else if (TOOL_TAG.equals(qName)) {
|
||||
currentInfo = new ToolInfo();
|
||||
setCommonAttributes(attributes);
|
||||
|
||||
} else if ("author".equals(qName)) {
|
||||
Author author = new Author();
|
||||
author.name = attributes.getValue("name");
|
||||
@@ -454,8 +464,9 @@ public class ContributionListing {
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
|
||||
if ("library".equals(qName) || "librarycompilation".equals(qName)) {
|
||||
libraries.add(currentInfo);
|
||||
if (LIBRARY_TAG.equals(qName) || LIBRARY_COMPILATION_TAG.equals(qName)
|
||||
|| TOOL_TAG.equals(qName)) {
|
||||
contributions.add(currentInfo);
|
||||
currentInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,18 +309,21 @@ public class ContributionManager {
|
||||
ArrayList<Library> libraries = editor.getMode().contribLibraries;
|
||||
ArrayList<LibraryCompilation> compilations = LibraryCompilation.list(libraries);
|
||||
|
||||
// Remove libraries from the list that are part of a compilations
|
||||
for (LibraryCompilation compilation : compilations) {
|
||||
for (Library lib : compilation.libraries) {
|
||||
libraries.remove(lib);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Contribution> contributions = new ArrayList<Contribution>();
|
||||
contributions.addAll(editor.contribTools);
|
||||
contributions.addAll(libraries);
|
||||
contributions.addAll(compilations);
|
||||
|
||||
ArrayList<ContributionInfo> infoList = new ArrayList<ContributionInfo>();
|
||||
for (Library library : libraries) {
|
||||
infoList.add(library.info);
|
||||
}
|
||||
for (LibraryCompilation compilation : compilations) {
|
||||
infoList.add(compilation.info);
|
||||
for (Contribution contribution : contributions) {
|
||||
infoList.add(contribution.getInfo());
|
||||
}
|
||||
|
||||
contributionListing.updateInstalledList(infoList);
|
||||
@@ -372,19 +375,22 @@ public class ContributionManager {
|
||||
|
||||
public void run() {
|
||||
|
||||
File libFile = downloader.getFile();
|
||||
File contributionFile = downloader.getFile();
|
||||
|
||||
if (libFile != null) {
|
||||
if (contributionFile != null) {
|
||||
installProgressMonitor.startTask("Installing",
|
||||
ProgressMonitor.UNKNOWN);
|
||||
|
||||
Contribution contribution = null;
|
||||
switch (info.getType()) {
|
||||
case LIBRARY:
|
||||
contribution = installLibrary(libFile, false);
|
||||
contribution = installLibrary(contributionFile, false);
|
||||
break;
|
||||
case LIBRARY_COMPILATION:
|
||||
contribution = installLibraryCompilation(libFile);
|
||||
contribution = installLibraryCompilation(contributionFile);
|
||||
break;
|
||||
case TOOL:
|
||||
contribution = installTool(contributionFile);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -531,6 +537,71 @@ public class ContributionManager {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
protected ToolContribution installTool(File zippedToolFile) {
|
||||
File tempDir = unzipFileToTemp(zippedToolFile);
|
||||
|
||||
ArrayList<ToolContribution> discoveredTools = ToolContribution.list(tempDir);
|
||||
if (discoveredTools.isEmpty()) {
|
||||
// Sometimes tool authors place all their folders in the base
|
||||
// directory of a zip file instead of in single folder as the
|
||||
// guidelines suggest. If this is the case, we might be able to find the
|
||||
// library by stepping up a directory and searching for libraries again.
|
||||
discoveredTools = ToolContribution.list(tempDir.getParentFile());
|
||||
}
|
||||
|
||||
if (discoveredTools != null && discoveredTools.size() == 1) {
|
||||
ToolContribution discoveredTool = discoveredTools.get(0);
|
||||
return installTool(discoveredTool);
|
||||
} else {
|
||||
// Diagnose the problem and notify the user
|
||||
if (discoveredTools == null || discoveredTools.isEmpty()) {
|
||||
Base.showWarning(DISCOVERY_ERROR_TITLE,
|
||||
DISCOVERY_INTERNAL_ERROR_MESSAGE, null);
|
||||
} else {
|
||||
Base.showWarning("Too many tools",
|
||||
"We found more than one tool in the file we just\n"
|
||||
+ "downloaded. That shouldn't happen, so we're going\n"
|
||||
+ "to ignore this file.", null);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ToolContribution installTool(ToolContribution newTool) {
|
||||
|
||||
ArrayList<ToolContribution> oldTools = editor.contribTools;
|
||||
|
||||
String toolFolderName = newTool.folder.getName();
|
||||
|
||||
File toolDestination = editor.getBase().getSketchbookToolsFolder();
|
||||
File newToolDest = new File(toolDestination, toolFolderName);
|
||||
|
||||
for (ToolContribution oldTool : oldTools) {
|
||||
|
||||
// XXX: Handle other cases when installing libraries.
|
||||
// -What if a library by the same name is already installed?
|
||||
// -What if newLibDest exists, but isn't used by an existing library?
|
||||
if (oldTool.folder.exists() && oldTool.folder.equals(newToolDest)) {
|
||||
|
||||
if (!backupContribution(oldTool)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move newLib to the sketchbook library folder
|
||||
if (newTool.folder.renameTo(newToolDest)) {
|
||||
return ToolContribution.getTool(newToolDest);
|
||||
} else {
|
||||
Base.showWarning("Trouble moving new tool to the sketchbook",
|
||||
"Could not move tool \"" + newTool.info.name + "\" to "
|
||||
+ newToolDest.getAbsolutePath() + ".\n", null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Library installLibrary(File libFile, boolean confirmReplace) {
|
||||
File tempDir = unzipFileToTemp(libFile);
|
||||
|
||||
@@ -575,7 +646,6 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param confirmReplace
|
||||
* if true and the library is already installed, opens a prompt to
|
||||
* ask the user if it's okay to replace the library. If false, the
|
||||
@@ -639,30 +709,31 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
public void refreshInstalled() {
|
||||
editor.getMode().rebuildLibraryList();
|
||||
editor.getMode().rebuildImportMenu();
|
||||
editor.rebuildToolMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the given contribution to a backup folder.
|
||||
*/
|
||||
private boolean backupContribution(Contribution lib) {
|
||||
private boolean backupContribution(Contribution contribution) {
|
||||
|
||||
File backupFolder = null;
|
||||
|
||||
switch (lib.getInfo().getType()) {
|
||||
switch (contribution.getInfo().getType()) {
|
||||
case LIBRARY:
|
||||
case LIBRARY_COMPILATION:
|
||||
backupFolder = createLibraryBackupFolder();
|
||||
break;
|
||||
case MODE:
|
||||
case TOOL:
|
||||
backupFolder = createToolBackupFolder();
|
||||
break;
|
||||
}
|
||||
|
||||
if (backupFolder == null) return false;
|
||||
|
||||
String libFolderName = lib.getFolder().getName();
|
||||
String libFolderName = contribution.getFolder().getName();
|
||||
|
||||
String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
||||
final String backupName = prefix + "_" + libFolderName;
|
||||
@@ -671,21 +742,17 @@ public class ContributionManager {
|
||||
// try {
|
||||
// FileUtils.moveDirectory(lib.folder, backupFolderForLib);
|
||||
// return true;
|
||||
if (lib.getFolder().renameTo(backupFolderForLib)) {
|
||||
if (contribution.getFolder().renameTo(backupFolderForLib)) {
|
||||
return true;
|
||||
} else {
|
||||
// } catch (IOException e) {
|
||||
Base.showWarning("Trouble creating backup of old \"" + lib.getInfo().name + "\" library",
|
||||
Base.showWarning("Trouble creating backup of old \"" + contribution.getInfo().name + "\" library",
|
||||
"Could not move library to backup folder:\n"
|
||||
+ backupFolderForLib.getAbsolutePath(), null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if there was an error creating the backup folder, true if it
|
||||
* already exists or was created successfully
|
||||
*/
|
||||
private File createLibraryBackupFolder() {
|
||||
|
||||
File libraryBackupFolder = new File(editor.getBase()
|
||||
@@ -705,6 +772,26 @@ public class ContributionManager {
|
||||
|
||||
return libraryBackupFolder;
|
||||
}
|
||||
|
||||
private File createToolBackupFolder() {
|
||||
|
||||
File toolsBackupFolder = new File(editor.getBase()
|
||||
.getSketchbookToolsFolder(), "old");
|
||||
|
||||
if (!toolsBackupFolder.exists() || !toolsBackupFolder.isDirectory()) {
|
||||
if (!toolsBackupFolder.mkdirs()) {
|
||||
Base.showWarning("Trouble creating folder to store old libraries in",
|
||||
"Could not create folder "
|
||||
+ toolsBackupFolder.getAbsolutePath()
|
||||
+ ".\n"
|
||||
+ "That's gonna prevent us from replacing the library.",
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return toolsBackupFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file in the parent folder that does not exist yet. If
|
||||
|
||||
@@ -31,9 +31,7 @@ import java.awt.datatransfer.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.print.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
@@ -98,8 +96,11 @@ public abstract class Editor extends JFrame implements RunnerListener {
|
||||
private final Stack<Integer> caretRedoStack = new Stack<Integer>();
|
||||
|
||||
private FindReplace find;
|
||||
JMenu toolsMenu;
|
||||
JMenu modeMenu;
|
||||
|
||||
ArrayList<ToolContribution> coreTools;
|
||||
ArrayList<ToolContribution> contribTools;
|
||||
|
||||
protected Editor(final Base base, String path, int[] location, final Mode mode) {
|
||||
super("Processing");
|
||||
@@ -451,7 +452,9 @@ public abstract class Editor extends JFrame implements RunnerListener {
|
||||
menubar.add(fileMenu);
|
||||
menubar.add(buildEditMenu());
|
||||
menubar.add(buildSketchMenu());
|
||||
menubar.add(buildToolsMenu());
|
||||
rebuildToolList();
|
||||
rebuildToolMenu();
|
||||
menubar.add(getToolMenu());
|
||||
|
||||
JMenu modeMenu = buildModeMenu();
|
||||
if (modeMenu != null) {
|
||||
@@ -804,109 +807,51 @@ public abstract class Editor extends JFrame implements RunnerListener {
|
||||
abstract public void handleImportLibrary(String jarPath);
|
||||
|
||||
|
||||
protected JMenu buildToolsMenu() {
|
||||
JMenu menu = new JMenu("Tools");
|
||||
|
||||
addInternalTools(menu);
|
||||
addTools(menu, base.getToolsFolder());
|
||||
File sketchbookTools = new File(base.getSketchbookFolder(), "tools");
|
||||
addTools(menu, sketchbookTools);
|
||||
|
||||
return menu;
|
||||
public JMenu getToolMenu() {
|
||||
if (toolsMenu == null) {
|
||||
rebuildToolMenu();
|
||||
}
|
||||
return toolsMenu;
|
||||
}
|
||||
|
||||
|
||||
protected void addTools(JMenu menu, File sourceFolder) {
|
||||
protected void rebuildToolList() {
|
||||
coreTools = ToolContribution.list(base.getToolsFolder());
|
||||
contribTools = ToolContribution.list(base.getSketchbookToolsFolder());
|
||||
}
|
||||
|
||||
|
||||
protected void rebuildToolMenu() {
|
||||
if (toolsMenu == null) {
|
||||
toolsMenu = new JMenu("Tools");
|
||||
} else {
|
||||
toolsMenu.removeAll();
|
||||
}
|
||||
|
||||
rebuildToolList();
|
||||
|
||||
addInternalTools(toolsMenu);
|
||||
addTools(toolsMenu, coreTools);
|
||||
addTools(toolsMenu, contribTools);
|
||||
}
|
||||
|
||||
|
||||
protected void addTools(JMenu menu, ArrayList<ToolContribution> tools) {
|
||||
HashMap<String, JMenuItem> toolItems = new HashMap<String, JMenuItem>();
|
||||
|
||||
File[] folders = sourceFolder.listFiles(new FileFilter() {
|
||||
public boolean accept(File folder) {
|
||||
if (folder.isDirectory()) {
|
||||
//System.out.println("checking " + folder);
|
||||
File subfolder = new File(folder, "tool");
|
||||
return subfolder.exists();
|
||||
for (final ToolContribution tool : tools) {
|
||||
String title = tool.getMenuTitle();
|
||||
JMenuItem item = new JMenuItem(title);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SwingUtilities.invokeLater(tool);
|
||||
//new Thread(tool).start();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (folders == null || folders.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < folders.length; i++) {
|
||||
File toolDirectory = new File(folders[i], "tool");
|
||||
|
||||
try {
|
||||
// add dir to classpath for .classes
|
||||
//urlList.add(toolDirectory.toURL());
|
||||
|
||||
// add .jar files to classpath
|
||||
File[] archives = toolDirectory.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.toLowerCase().endsWith(".jar") ||
|
||||
name.toLowerCase().endsWith(".zip"));
|
||||
}
|
||||
});
|
||||
|
||||
URL[] urlList = new URL[archives.length];
|
||||
for (int j = 0; j < urlList.length; j++) {
|
||||
urlList[j] = archives[j].toURI().toURL();
|
||||
}
|
||||
URLClassLoader loader = new URLClassLoader(urlList);
|
||||
|
||||
String className = null;
|
||||
for (int j = 0; j < archives.length; j++) {
|
||||
className = findClassInZipFile(folders[i].getName(), archives[j]);
|
||||
if (className != null) break;
|
||||
}
|
||||
|
||||
/*
|
||||
// Alternatively, could use manifest files with special attributes:
|
||||
// http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html
|
||||
// Example code for loading from a manifest file:
|
||||
// http://forums.sun.com/thread.jspa?messageID=3791501
|
||||
File infoFile = new File(toolDirectory, "tool.txt");
|
||||
if (!infoFile.exists()) continue;
|
||||
|
||||
String[] info = PApplet.loadStrings(infoFile);
|
||||
//Main-Class: org.poo.shoe.AwesomerTool
|
||||
//String className = folders[i].getName();
|
||||
String className = null;
|
||||
for (int k = 0; k < info.length; k++) {
|
||||
if (info[k].startsWith(";")) continue;
|
||||
|
||||
String[] pieces = PApplet.splitTokens(info[k], ": ");
|
||||
if (pieces.length == 2) {
|
||||
if (pieces[0].equals("Main-Class")) {
|
||||
className = pieces[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// If no class name found, just move on.
|
||||
if (className == null) continue;
|
||||
|
||||
Class<?> toolClass = Class.forName(className, true, loader);
|
||||
final Tool tool = (Tool) toolClass.newInstance();
|
||||
|
||||
tool.init(Editor.this);
|
||||
|
||||
String title = tool.getMenuTitle();
|
||||
JMenuItem item = new JMenuItem(title);
|
||||
item.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SwingUtilities.invokeLater(tool);
|
||||
//new Thread(tool).start();
|
||||
}
|
||||
});
|
||||
//menu.add(item);
|
||||
toolItems.put(title, item);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
//menu.add(item);
|
||||
toolItems.put(title, item);
|
||||
}
|
||||
|
||||
ArrayList<String> toolList = new ArrayList<String>(toolItems.keySet());
|
||||
if (toolList.size() == 0) return;
|
||||
|
||||
@@ -925,37 +870,6 @@ public abstract class Editor extends JFrame implements RunnerListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected String findClassInZipFile(String base, File file) {
|
||||
// Class file to search for
|
||||
String classFileName = "/" + base + ".class";
|
||||
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(file);
|
||||
Enumeration<?> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
String name = entry.getName();
|
||||
//System.out.println("entry: " + name);
|
||||
|
||||
if (name.endsWith(classFileName)) {
|
||||
//int slash = name.lastIndexOf('/');
|
||||
//String packageName = (slash == -1) ? "" : name.substring(0, slash);
|
||||
// Remove .class and convert slashes to periods.
|
||||
return name.substring(0, name.length() - 6).replace('/', '.');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected JMenuItem createToolMenuItem(String className) {
|
||||
try {
|
||||
Class<?> toolClass = Class.forName(className);
|
||||
|
||||
201
app/src/processing/app/ToolContribution.java
Normal file
201
app/src/processing/app/ToolContribution.java
Normal file
@@ -0,0 +1,201 @@
|
||||
package processing.app;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
import processing.app.tools.Tool;
|
||||
|
||||
public class ToolContribution extends Contribution implements Tool {
|
||||
|
||||
Tool tool;
|
||||
|
||||
ToolInfo info;
|
||||
|
||||
File folder;
|
||||
|
||||
static public ToolContribution getTool(File folder) {
|
||||
try {
|
||||
ToolContribution tool = new ToolContribution(folder);
|
||||
if (tool.tool != null)
|
||||
return tool;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ToolContribution(File folder) throws Exception {
|
||||
this.folder = folder;
|
||||
|
||||
// XXX: This is repeated in LibraryCompilcation.java
|
||||
File propertiesFile = new File(folder, "properties.txt");
|
||||
|
||||
info = new ToolInfo();
|
||||
info.tool = this;
|
||||
|
||||
HashMap<String,String> propertiesTable = Base.readSettings(propertiesFile);
|
||||
readProperties(propertiesTable, info);
|
||||
if (info.name == null) {
|
||||
info.name = folder.getName();
|
||||
}
|
||||
|
||||
File toolDirectory = new File(folder, "tool");
|
||||
// add dir to classpath for .classes
|
||||
//urlList.add(toolDirectory.toURL());
|
||||
|
||||
// add .jar files to classpath
|
||||
File[] archives = toolDirectory.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.toLowerCase().endsWith(".jar") ||
|
||||
name.toLowerCase().endsWith(".zip"));
|
||||
}
|
||||
});
|
||||
|
||||
URL[] urlList = new URL[archives.length];
|
||||
for (int j = 0; j < urlList.length; j++) {
|
||||
urlList[j] = archives[j].toURI().toURL();
|
||||
}
|
||||
URLClassLoader loader = new URLClassLoader(urlList);
|
||||
|
||||
String className = null;
|
||||
for (int j = 0; j < archives.length; j++) {
|
||||
className = findClassInZipFile(folder.getName(), archives[j]);
|
||||
if (className != null) break;
|
||||
}
|
||||
|
||||
/*
|
||||
// Alternatively, could use manifest files with special attributes:
|
||||
// http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html
|
||||
// Example code for loading from a manifest file:
|
||||
// http://forums.sun.com/thread.jspa?messageID=3791501
|
||||
File infoFile = new File(toolDirectory, "tool.txt");
|
||||
if (!infoFile.exists()) continue;
|
||||
|
||||
String[] info = PApplet.loadStrings(infoFile);
|
||||
//Main-Class: org.poo.shoe.AwesomerTool
|
||||
//String className = folders[i].getName();
|
||||
String className = null;
|
||||
for (int k = 0; k < info.length; k++) {
|
||||
if (info[k].startsWith(";")) continue;
|
||||
|
||||
String[] pieces = PApplet.splitTokens(info[k], ": ");
|
||||
if (pieces.length == 2) {
|
||||
if (pieces[0].equals("Main-Class")) {
|
||||
className = pieces[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// If no class name found, just move on.
|
||||
if (className == null) return;
|
||||
|
||||
Class<?> toolClass = Class.forName(className, true, loader);
|
||||
tool = (Tool) toolClass.newInstance();
|
||||
}
|
||||
|
||||
protected String findClassInZipFile(String base, File file) {
|
||||
// Class file to search for
|
||||
String classFileName = "/" + base + ".class";
|
||||
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(file);
|
||||
Enumeration<?> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
String name = entry.getName();
|
||||
//System.out.println("entry: " + name);
|
||||
|
||||
if (name.endsWith(classFileName)) {
|
||||
//int slash = name.lastIndexOf('/');
|
||||
//String packageName = (slash == -1) ? "" : name.substring(0, slash);
|
||||
// Remove .class and convert slashes to periods.
|
||||
zipFile.close();
|
||||
return name.substring(0, name.length() - 6).replace('/', '.');
|
||||
}
|
||||
}
|
||||
}
|
||||
zipFile.close();
|
||||
} catch (IOException e) {
|
||||
//System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static protected ArrayList<ToolContribution> list(File folder) {
|
||||
ArrayList<ToolContribution> tools = new ArrayList<ToolContribution>();
|
||||
list(folder, tools);
|
||||
return tools;
|
||||
}
|
||||
|
||||
static protected void list(File folder, ArrayList<ToolContribution> tools) {
|
||||
|
||||
File[] folders = folder.listFiles(new FileFilter() {
|
||||
public boolean accept(File folder) {
|
||||
if (folder.isDirectory()) {
|
||||
//System.out.println("checking " + folder);
|
||||
File subfolder = new File(folder, "tool");
|
||||
return subfolder.exists();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (folders == null || folders.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < folders.length; i++) {
|
||||
try {
|
||||
final ToolContribution tool = getTool(folders[i]);
|
||||
if (tool != null) {
|
||||
tools.add(tool);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContributionInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
File getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public void init(Editor editor) {
|
||||
tool.init(editor);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
tool.run();
|
||||
}
|
||||
|
||||
public String getMenuTitle() {
|
||||
return tool.getMenuTitle();
|
||||
}
|
||||
|
||||
public static class ToolInfo extends ContributionInfo {
|
||||
|
||||
ToolContribution tool;
|
||||
|
||||
public ContributionType getType() {
|
||||
return ContributionType.TOOL;
|
||||
}
|
||||
|
||||
public boolean isInstalled() {
|
||||
return tool != null;
|
||||
}
|
||||
|
||||
public Contribution getContribution() {
|
||||
return tool;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user