Fetching libraries from xml and loading them into library manager.

This commit is contained in:
pesckal
2011-06-24 20:56:37 +00:00
parent b820abf45f
commit 5c1eb3f313
5 changed files with 579 additions and 261 deletions
+5 -1
View File
@@ -59,7 +59,11 @@ public class FileDownloader implements Runnable {
public FileDownloader(URL url, File dest, ProgressMonitor progressMonitor) {
this.url = url;
this.dest = dest;
this.progressMonitor = progressMonitor;
if (progressMonitor == null) {
this.progressMonitor = new NullProgressMonitor();
} else {
this.progressMonitor = progressMonitor;
}
post = null;
libFile = null;
}
+217 -211
View File
@@ -31,209 +31,17 @@ import java.awt.*;
import java.text.*;
import java.util.*;
import processing.app.LibraryListing.LibraryInfo;
import processing.app.LibraryManager.*;
public class LibraryListPanel extends JPanel {
/**
* Panel that expands and gives a brief overview of a library when clicked.
*/
class LibraryPanel extends JPanel {
final String unclickedCardId = "unclicked";
final String clickedCardId = "clicked";
final int topAndBottomBorder = 2;
LibraryInfo libInfo;
JPanel headerPanel;
JLabel nameLabel;
JPanel infoPanel;
JPanel unclickedCard;
JPanel clickedCard;
JTextArea briefText;
JButton installOrRemove;
boolean isInfoShown;
private LibraryPanel(LibraryInfo libInfo) {
this.libInfo = libInfo;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createEmptyBorder(topAndBottomBorder, 2, topAndBottomBorder, 2));
configureHeaderPane();
configureInfoPane();
setFocusable(true);
setShowInfo(false);
updateColors();
updateLibraryListSize();
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
for (Component c : LibraryListPanel.this.getComponents()) {
if (c != LibraryPanel.this && c instanceof LibraryPanel) {
LibraryPanel lp = (LibraryPanel) c;
lp.setShowInfo(false);
}
}
setShowInfo(true);
updateColors();
updateLibraryListSize();
requestFocusInWindow();
}
});
}
/**
* Create the widgets for the header panel which is visible when the library
* panel is not clicked
*/
private void configureHeaderPane() {
headerPanel = new JPanel();
headerPanel.setFocusable(true);
headerPanel.setOpaque(false);
headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.X_AXIS));
nameLabel = new JLabel(libInfo.name);
headerPanel.add(this.nameLabel);
headerPanel.add(Box.createHorizontalGlue());
add(headerPanel);
}
/**
* Create the widgets for the info panel which is visible when the library
* panel is clicked
*/
private void configureInfoPane() {
infoPanel = new JPanel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
infoPanel.setLayout(new CardLayout());
unclickedCard = new JPanel();
clickedCard = new JPanel();
infoPanel.setOpaque(false);
unclickedCard.setOpaque(false);
clickedCard.setOpaque(false);
infoPanel.setFocusable(true);
unclickedCard.setFocusable(true);
clickedCard.setFocusable(true);
briefText = new JTextArea(libInfo.briefOverview);
installOrRemove = new JButton();
// installOrRemove = new JButton("Install");
// ActionListener installLibAction = new ActionListener() {
//
// public void actionPerformed(ActionEvent arg) {
// try {
// URL url = new URL(libraryUri.getText());
// // System.out.println("Installing library: " + url);
// File libFile = downloadLibrary(url);
// if (libFile != null) {
// installLibrary(libFile);
// }
// } catch (MalformedURLException e) {
// System.err.println("Malformed URL");
// }
// libraryUri.setText("");
// }
// };
// installOrRemove.addActionListener(installLibAction);
clickedCard.setLayout(new BoxLayout(clickedCard, BoxLayout.X_AXIS));
briefText.setHighlighter(null);
briefText.setOpaque(false);
briefText.setEditable(false);
briefText.setLineWrap(true);
briefText.setWrapStyleWord(true);
Font font = this.briefText.getFont();
font = font.deriveFont(font.getSize() * 0.9f);
briefText.setFont(font);
clickedCard.add(briefText);
clickedCard.add(Box.createHorizontalGlue());
clickedCard.add(installOrRemove);
installOrRemove.setAlignmentY(Component.BOTTOM_ALIGNMENT);
briefText.setAlignmentY(Component.BOTTOM_ALIGNMENT);
installOrRemove.setText("Install");
Dimension installButtonDimensions = installOrRemove.getPreferredSize();
installButtonDimensions.width = 100;
installOrRemove.setPreferredSize(installButtonDimensions);
infoPanel.add(unclickedCard, unclickedCardId);
infoPanel.add(clickedCard, clickedCardId);
add(infoPanel);
}
/**
* Turns on/off the info panel which contains a brief description of the
* library and a button to Install/Remove a library.
*/
public void setShowInfo(boolean doShow) {
isInfoShown = doShow;
CardLayout cardLayout = (CardLayout) infoPanel.getLayout();
if (isInfoShown) {
cardLayout.show(infoPanel, clickedCardId);
} else {
cardLayout.show(infoPanel, unclickedCardId);
}
int width = getSize().width;
updateSize(width > 0 ? width : 100);
}
/**
* Updates the sizes of components in this panel given width as a constraint
*/
public void updateSize(int width) {
Dimension textDimentions = briefText.getPreferredSize();
textDimentions.width = width - installOrRemove.getPreferredSize().width;
textDimentions.height = calculateHeight(briefText, textDimentions.width);
briefText.setMaximumSize(textDimentions);
briefText.setMinimumSize(textDimentions);
briefText.setPreferredSize(textDimentions);
//briefText.setSize(textDimentions);
Dimension d;
if (isInfoShown) {
d = headerPanel.getPreferredSize();
d.width = width;
d.height += clickedCard.getPreferredSize().height + 2 * topAndBottomBorder;
} else {
d = headerPanel.getPreferredSize();
d.width = width;
d.height += 2 * topAndBottomBorder;
}
setMaximumSize(d);
setMinimumSize(d);
setPreferredSize(d);
//setSize(d);
revalidate();
}
}
public LibraryListPanel(ArrayList<LibraryInfo> libraries) {
public LibraryListPanel(LibraryListing libraries) {
super();
setLayout(new GridBagLayout());
int row = 0;
for (LibraryInfo libInfo : libraries) {
for (LibraryInfo libInfo : libraries.getAllLibararies()) {
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
@@ -272,7 +80,7 @@ public class LibraryListPanel extends JPanel {
updateLibraryListSize();
}
/**
* Updates the width and height of this library list based on the sizes of
* the library panes it contains.
@@ -317,24 +125,29 @@ public class LibraryListPanel extends JPanel {
* word are enabled for the JTextArea.
*/
private static int lineCount(JTextArea textArea, int width) {
AttributedString text = new AttributedString(textArea.getText());
FontRenderContext frc = textArea.getFontMetrics(textArea.getFont())
.getFontRenderContext();
AttributedCharacterIterator charIt = text.getIterator();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc);
lineMeasurer.setPosition(charIt.getBeginIndex());
// Get lines from lineMeasurer until the entire
// paragraph has been displayed.
int noLines = 0;
while (lineMeasurer.getPosition() < charIt.getEndIndex()) {
lineMeasurer.nextLayout(width);
noLines++;
try {
AttributedString text = new AttributedString(textArea.getText());
FontRenderContext frc = textArea.getFontMetrics(textArea.getFont())
.getFontRenderContext();
AttributedCharacterIterator charIt = text.getIterator();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc);
lineMeasurer.setPosition(charIt.getBeginIndex());
// Get lines from lineMeasurer until the entire
// paragraph has been displayed.
int noLines = 0;
while (lineMeasurer.getPosition() < charIt.getEndIndex()) {
lineMeasurer.nextLayout(width);
noLines++;
}
return noLines;
} catch (IllegalArgumentException e) {
return 1;
}
return noLines;
}
/**
* Updates the colors of all library panels that are visible.
*/
@@ -380,4 +193,197 @@ public class LibraryListPanel extends JPanel {
return lineHeight * lineCount(textArea, width);
}
/**
* Panel that expands and gives a brief overview of a library when clicked.
*/
class LibraryPanel extends JPanel {
final String unclickedCardId = "unclicked";
final String clickedCardId = "clicked";
final int topAndBottomBorder = 2;
LibraryInfo libInfo;
JPanel headerPanel;
JLabel nameLabel;
JPanel infoPanel;
JPanel unclickedCard;
JPanel clickedCard;
JTextArea briefText;
JButton installOrRemove;
boolean isInfoShown;
private LibraryPanel(LibraryInfo libInfo) {
this.libInfo = libInfo;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createEmptyBorder(topAndBottomBorder, 2, topAndBottomBorder, 2));
configureHeaderPane();
configureInfoPane();
setFocusable(true);
setShowInfo(false);
updateColors();
updateLibraryListSize();
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
for (Component c : LibraryListPanel.this.getComponents()) {
if (c != LibraryPanel.this && c instanceof LibraryPanel) {
LibraryPanel lp = (LibraryPanel) c;
lp.setShowInfo(false);
}
}
setShowInfo(true);
updateColors();
updateLibraryListSize();
requestFocusInWindow();
}
});
}
/**
* Create the widgets for the header panel which is visible when the library
* panel is not clicked
*/
private void configureHeaderPane() {
headerPanel = new JPanel();
headerPanel.setFocusable(true);
headerPanel.setOpaque(false);
headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.X_AXIS));
nameLabel = new JLabel(libInfo.name);
headerPanel.add(this.nameLabel);
headerPanel.add(Box.createHorizontalGlue());
add(headerPanel);
}
/**
* Create the widgets for the info panel which is visible when the library
* panel is clicked
*/
private void configureInfoPane() {
infoPanel = new JPanel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
infoPanel.setLayout(new CardLayout());
unclickedCard = new JPanel();
clickedCard = new JPanel();
infoPanel.setOpaque(false);
unclickedCard.setOpaque(false);
clickedCard.setOpaque(false);
infoPanel.setFocusable(true);
unclickedCard.setFocusable(true);
clickedCard.setFocusable(true);
briefText = new JTextArea(libInfo.description);
installOrRemove = new JButton();
// installOrRemove = new JButton("Install");
// ActionListener installLibAction = new ActionListener() {
//
// public void actionPerformed(ActionEvent arg) {
// try {
// URL url = new URL(libraryUri.getText());
// // System.out.println("Installing library: " + url);
// File libFile = downloadLibrary(url);
// if (libFile != null) {
// installLibrary(libFile);
// }
// } catch (MalformedURLException e) {
// System.err.println("Malformed URL");
// }
// libraryUri.setText("");
// }
// };
// installOrRemove.addActionListener(installLibAction);
clickedCard.setLayout(new BoxLayout(clickedCard, BoxLayout.X_AXIS));
briefText.setHighlighter(null);
briefText.setOpaque(false);
briefText.setEditable(false);
briefText.setLineWrap(true);
briefText.setWrapStyleWord(true);
Font font = this.briefText.getFont();
font = font.deriveFont(font.getSize() * 0.9f);
briefText.setFont(font);
clickedCard.add(briefText);
clickedCard.add(Box.createHorizontalGlue());
clickedCard.add(installOrRemove);
installOrRemove.setAlignmentY(Component.BOTTOM_ALIGNMENT);
briefText.setAlignmentY(Component.BOTTOM_ALIGNMENT);
installOrRemove.setText("Install");
Dimension installButtonDimensions = installOrRemove.getPreferredSize();
installButtonDimensions.width = 100;
installOrRemove.setPreferredSize(installButtonDimensions);
infoPanel.add(unclickedCard, unclickedCardId);
infoPanel.add(clickedCard, clickedCardId);
add(infoPanel);
}
/**
* Turns on/off the info panel which contains a brief description of the
* library and a button to Install/Remove a library.
*/
public void setShowInfo(boolean doShow) {
isInfoShown = doShow;
CardLayout cardLayout = (CardLayout) infoPanel.getLayout();
if (isInfoShown) {
cardLayout.show(infoPanel, clickedCardId);
} else {
cardLayout.show(infoPanel, unclickedCardId);
}
int width = getSize().width;
updateSize(width > 0 ? width : 100);
}
/**
* Updates the sizes of components in this panel given width as a constraint
*/
public void updateSize(int width) {
Dimension textDimentions = briefText.getPreferredSize();
textDimentions.width = width - installOrRemove.getPreferredSize().width;
textDimentions.height = calculateHeight(briefText, textDimentions.width);
briefText.setMaximumSize(textDimentions);
briefText.setMinimumSize(textDimentions);
briefText.setPreferredSize(textDimentions);
//briefText.setSize(textDimentions);
Dimension d;
if (isInfoShown) {
d = headerPanel.getPreferredSize();
d.width = width;
d.height += clickedCard.getPreferredSize().height + 2 * topAndBottomBorder;
} else {
d = headerPanel.getPreferredSize();
d.width = width;
d.height += 2 * topAndBottomBorder;
}
setMaximumSize(d);
setMinimumSize(d);
setPreferredSize(d);
//setSize(d);
revalidate();
}
}
}
+306
View File
@@ -0,0 +1,306 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2004-11 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.Map.Entry;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class LibraryListing {
Map<String, List<LibraryInfo>> librariesByCategory;
public LibraryListing(File xmlFile) {
librariesByCategory = new HashMap<String, List<LibraryInfo>>();
new LibraryXmlParser(xmlFile);
}
public Set<String> getCategories() {
return librariesByCategory.keySet();
}
public List<LibraryInfo> getAllLibararies() {
ArrayList<LibraryInfo> allLibs = new ArrayList<LibraryInfo>();
for (Entry<String, List<LibraryInfo>> libListEntry : librariesByCategory
.entrySet()) {
allLibs.addAll(libListEntry.getValue());
}
return allLibs;
}
public List<LibraryInfo> getLibararies(String category) {
return librariesByCategory.get(category);
}
public static class LibraryListFetcher {
LibraryListing libListing;
File dest;
URL url;
FileDownloader downloader;
Thread downloaderThread;
public LibraryListFetcher() {
libListing = null;
try {
File tmpFolder = Base.createTempFolder("libarylist", "download");
dest = new File(tmpFolder, "libraries.xml");
dest.setWritable(true);
url = new URL("http://dl.dropbox.com/u/700641/libraries.xml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void fetchLibraryList(ProgressMonitor pm) {
downloader = new FileDownloader(url, dest, pm);
downloader.setPostOperation(new Runnable() {
public void run() {
File xmlFile = downloader.getFile();
if (xmlFile != null) {
libListing = new LibraryListing(xmlFile);
}
}
});
downloaderThread = new Thread(downloader);
downloaderThread.start();
}
public boolean isDone() {
return !downloaderThread.isAlive();
}
public LibraryListing getLibraryListing() {
return libListing;
}
}
public static class LibraryInfo {
public final String categoryName;
public final String name;
public final String url;
public final String description;
public final ArrayList<Author> authors;
public final String versionId;
public final String link;
final boolean isInstalled;
public LibraryInfo(String categoryName, String name, String url,
String description, ArrayList<Author> authors,
String versionId, String link) {
this.categoryName = categoryName;
this.name = name;
this.url = url;
this.description = description;
this.authors = authors;
this.versionId = versionId;
this.link = link;
isInstalled = false;
}
public static class Author {
public final String name;
public final String url;
public Author(String name, String url) {
this.name = name;
this.url = url;
}
}
}
/**
* Class to parse the libraries xml file
*/
class LibraryXmlParser extends DefaultHandler {
String categoryName;
String libraryName;
String libraryUrl;
String libraryVersionId;
String libraryLink;
String libraryDescription;
boolean doingDescription;
ArrayList<LibraryInfo.Author> authors;
String authorUrl;
boolean doingAuthor;
LibraryXmlParser(File xmlFile) {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(false);
try {
SAXParser sp = spf.newSAXParser();
InputSource input = new InputSource(new FileReader(xmlFile));
sp.parse(input, this);
// XXX: Do something meaningful when we get an error
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
private void reset() {
libraryName = null;
libraryUrl = null;
libraryVersionId = null;
libraryLink = null;
libraryDescription = null;
doingDescription = false;
authors = new ArrayList<LibraryInfo.Author>();
authorUrl = null;
doingAuthor = false;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("category".equals(qName)) {
categoryName = attributes.getValue("name");
} else if ("library".equals(qName)) {
reset();
libraryName = attributes.getValue("name");
libraryUrl = attributes.getValue("url");
} else if ("author".equals(qName)) {
authorUrl = attributes.getValue("url");
doingAuthor = true;
} else if ("description".equals(qName)) {
doingDescription = true;
} else if ("version".equals(qName)) {
libraryVersionId = attributes.getValue("id");
} else if ("location".equals(qName)) {
libraryLink = attributes.getValue("url");
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (doingAuthor) {
String authorName = new String(ch, start, length).trim();
authors.add(new LibraryInfo.Author(authorName, authorUrl));
authorUrl = null;
doingAuthor = false;
} else if (doingDescription) {
libraryDescription = new String(ch, start, length).trim();
doingDescription = false;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("library".equals(qName)) {
// Dump the information we collected and reset the variables
LibraryInfo libInfo = new LibraryInfo(categoryName, libraryName,
libraryUrl, libraryDescription,
authors, libraryVersionId,
libraryLink);
if (librariesByCategory.containsKey(categoryName)) {
librariesByCategory.get(categoryName).add(libInfo);
} else {
ArrayList<LibraryInfo> libs = new ArrayList<LibraryInfo>();
libs.add(libInfo);
librariesByCategory.put(categoryName, libs);
}
reset();
}
}
@Override
public void warning(SAXParseException exception) {
System.err.println("WARNING: line " + exception.getLineNumber() + ": "
+ exception.getMessage());
}
@Override
public void error(SAXParseException exception) {
System.err.println("ERROR: line " + exception.getLineNumber() + ": "
+ exception.getMessage());
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
System.err.println("FATAL: line " + exception.getLineNumber() + ": "
+ exception.getMessage());
throw (exception);
}
}
}
+44 -49
View File
@@ -33,6 +33,16 @@ import java.util.zip.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import processing.app.LibraryListing.LibraryListFetcher;
class JProgressMonitor extends AbstractProgressMonitor {
JProgressBar progressBar;
@@ -69,7 +79,7 @@ public class LibraryManager {
* true to use manual URL specification only
* false to use searchable library list
*/
static boolean USE_SIMPLE = true;
static boolean USE_SIMPLE = false;
JFrame dialog;
@@ -244,7 +254,13 @@ public class LibraryManager {
filterField = new FilterField();
pane.add(filterField, c);
libraryListPane = new LibraryListPanel(fetchLibraryInfo());
LibraryListFetcher llf = new LibraryListFetcher();
llf.fetchLibraryList(null);
while (!llf.isDone()) {
Thread.yield();
}
libraryListPane = new LibraryListPanel(llf.getLibraryListing());
c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
@@ -517,39 +533,32 @@ public class LibraryManager {
out.close();
}
/**
* Placeholder function which returns a list of information on libraries.
*/
public static ArrayList<LibraryInfo> fetchLibraryInfo() {
ArrayList<LibraryInfo> libInfos = new ArrayList<LibraryInfo>();
LibraryInfo libInfo = new LibraryInfo();
libInfo.name = "BlobDetection";
libInfo.briefOverview = "Performs the computer vision technique of finding \"blobs\" in an image.";
libInfo.isInstalled = true;
libInfo.tags.add("blob");
libInfo.tags.add("vision");
libInfo.tags.add("image");
libInfos.add(libInfo);
libInfo = new LibraryInfo();
libInfo.name = "OpenCV";
libInfo.briefOverview = "An OpenCV implementation for processing including blob detection, face recognition and more. This library is highly recommended.";
libInfo.isInstalled = false;
libInfo.tags.add("face");
libInfo.tags.add("vision");
libInfo.tags.add("image");
libInfos.add(libInfo);
libInfo = new LibraryInfo();
libInfo.name = "SQLibrary";
libInfo.briefOverview = "A library to facilitate communication with MySQL or SQLite databases.";
libInfo.isInstalled = false;
libInfo.tags.add("database");
libInfos.add(libInfo);
return libInfos;
}
// /**
// * Placeholder function which returns a list of information on libraries.
// */
// public static ArrayList<LibraryInfo> fetchLibraryInfo() {
// ArrayList<LibraryInfo> libInfos = new ArrayList<LibraryInfo>();
//
// LibraryInfo libInfo = new LibraryInfo();
// libInfo.name = "BlobDetection";
// libInfo.description = "Performs the computer vision technique of finding \"blobs\" in an image.";
// libInfo.isInstalled = true;
// libInfos.add(libInfo);
//
// libInfo = new LibraryInfo();
// libInfo.name = "OpenCV";
// libInfo.description = "An OpenCV implementation for processing including blob detection, face recognition and more. This library is highly recommended.";
// libInfo.isInstalled = false;
// libInfos.add(libInfo);
//
// libInfo = new LibraryInfo();
// libInfo.name = "SQLibrary";
// libInfo.description = "A library to facilitate communication with MySQL or SQLite databases.";
// libInfo.isInstalled = false;
// libInfos.add(libInfo);
//
// return libInfos;
// }
class FilterField extends JTextField {
final static String filterHint = "Filter your search...";
@@ -622,19 +631,5 @@ public class LibraryManager {
}
}
static class LibraryInfo {
String name;
String briefOverview;
String version;
String url;
ArrayList<String> tags;
boolean isInstalled;
public LibraryInfo() {
tags = new ArrayList<String>();
isInstalled = false;
}
}
}
@@ -87,3 +87,10 @@ abstract class AbstractProgressMonitor implements ProgressMonitor {
}
}
class NullProgressMonitor extends AbstractProgressMonitor {
public void startTask(String name, int maxValue) {
}
}