Changed layout of library panels. Fixed bugs with filtering.

This commit is contained in:
pesckal
2011-06-29 08:50:22 +00:00
parent 55b112eb6c
commit 2a9a564d80
3 changed files with 192 additions and 233 deletions
+169 -204
View File
@@ -26,18 +26,17 @@ import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.*;
import java.text.*;
import processing.app.LibraryListing.LibraryInfo;
import processing.app.LibraryManager.LibraryInstaller;
import processing.app.LibraryListing.LibraryInfo.Author;
public class LibraryListPanel extends JPanel implements Scrollable {
@@ -49,7 +48,13 @@ public class LibraryListPanel extends JPanel implements Scrollable {
public LibraryListPanel(LibraryManager libraryManager) {
super();
preferredViewPositionListener = null;
preferredViewPositionListener = new PreferredViewPositionListener() {
public void handlePreferredLocation(Point p) {
}
};
this.libraryManager = libraryManager;
libraries = libraryManager.getLibraryListing(null);
@@ -98,71 +103,6 @@ public class LibraryListPanel extends JPanel implements Scrollable {
for (LibraryInfo lib : hiddenLibraries) {
libPanelsByInfo.get(lib).setVisible(false);
}
updateLibraryListSizeAndPosition(0, false, null);
}
/**
* Updates the widths of all library panels in this library list.
*/
public void setWidth(int newWidth) {
for (Component c : getComponents()) {
if (c instanceof LibraryPanel) {
((LibraryPanel) c).updateSize(newWidth);
}
}
updateLibraryListSizeAndPosition(0, true, null);
}
/**
* Updates the width and height of this library list based on the sizes of the
* library panes it contains.
*
* @param obtainedSpace
* the height of the space obtained from the closing of the previous
* panel
* @param obtainedSpaceIsAbove
* true if the panel that was closed was above the panel which was
* just opened
* @param expandedPanel
* the panel that was expanded, or null if none
*/
private void updateLibraryListSizeAndPosition(int obtainedSpace,
boolean obtainedSpaceIsAbove,
LibraryPanel expandedPanel) {
int height = 0;
int width = 0;
// int selectedTop = 0, selectedBottom = 0;
// if (expandedPanel != null) {
// selectedTop = expandedPanel.getLocation().y;
// selectedBottom = selectedTop + expandedPanel.getHeight();
// }
for (Component c : getComponents()) {
if (c.isVisible()) {
if (c instanceof LibraryPanel) {
Dimension d = c.getPreferredSize();
if (d.width > width) {
width = d.width;
}
height += d.height;
}
}
}
Rectangle r = getVisibleRect();
if (obtainedSpaceIsAbove && preferredViewPositionListener != null) {
Point p = new Point(r.x, r.y);
p.y -= obtainedSpace;
preferredViewPositionListener.handlePreferredLocation(p);
}
setPreferredSize(new Dimension(width, height));
}
/**
@@ -247,13 +187,14 @@ public class LibraryListPanel extends JPanel implements Scrollable {
* as a contained. This assumed that both word wrap and wrap-style word are
* enabled for the JTextArea.
*/
@SuppressWarnings("unused")
private static int calculateHeight(JTextArea textArea, int width) {
Font font = textArea.getFont();
FontMetrics fontMetrics = textArea.getFontMetrics(font);
int lineHeight = fontMetrics.getAscent() + fontMetrics.getDescent();
return lineHeight * lineCount(textArea, width);
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
@@ -293,10 +234,12 @@ public class LibraryListPanel extends JPanel implements Scrollable {
int nextHeight = height + d.height;
if (direction > 0) {
// scrolling down
if (nextHeight > bottomOfScrollArea) {
return nextHeight - bottomOfScrollArea;
}
} else {
// scrolling up
if (nextHeight > visibleRect.y) {
if (visibleRect.y != height) {
return visibleRect.y - height;
@@ -321,7 +264,7 @@ public class LibraryListPanel extends JPanel implements Scrollable {
}
public boolean getScrollableTracksViewportWidth() {
return false;
return true;
}
public void setPreferredViewPositionListener(PreferredViewPositionListener preferredViewPositionListener) {
@@ -335,79 +278,110 @@ public class LibraryListPanel extends JPanel implements Scrollable {
private static final int BUTTON_WIDTH = 100;
final String unclickedCardId = "unclicked";
final String clickedCardId = "clicked";
final int topAndBottomBorder = 2;
LibraryInfo libInfo;
JPanel headerPanel;
// JTextArea briefText;
JPanel infoPanel;
JPanel unclickedCard;
JPanel clickedCard;
JTextArea description;
JProgressBar installProgressBar;
JTextPane authorLabel;
JTextPane descriptionText;
JButton installOrRemove;
boolean isInfoShown;
String authorsWithLinks = "";
String authorsWithouthLinks = "";
private HyperlinkListener hyperlinkOpener;
private LibraryPanel(LibraryInfo libInfo) {
this.libInfo = libInfo;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
generateAuthorStrings();
hyperlinkOpener = new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
Base.openURL(e.getURL().toString());
}
}
};
setBorder(BorderFactory.createEmptyBorder(topAndBottomBorder, 2,
topAndBottomBorder, 2));
configureHeaderPane();
configureInfoPane();
addPaneComponents();
addProgressBarAndButton();
setFocusable(true);
setShowInfo(false);
updateColors();
updateLibraryListSizeAndPosition(0, true, null);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int obtainedSpace = 0;
boolean obtainedSpaceIsAbove = true;
MouseAdapter expandPanelMouseListener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
for (Component c : LibraryListPanel.this.getComponents()) {
if (c == LibraryPanel.this) {
obtainedSpaceIsAbove = false;
} else if (c instanceof LibraryPanel) {
if (c instanceof LibraryPanel) {
LibraryPanel lp = (LibraryPanel) c;
if (lp.isInfoShown) {
obtainedSpace = lp.description.getSize().height;
lp.setShowInfo(false);
break;
}
}
}
setShowInfo(true);
updateColors();
updateLibraryListSizeAndPosition(obtainedSpace, obtainedSpaceIsAbove,
LibraryPanel.this);
requestFocusInWindow();
getParent().requestFocusInWindow();
}
});
};
addMouseListener(expandPanelMouseListener);
authorLabel.addMouseListener(expandPanelMouseListener);
descriptionText.addMouseListener(expandPanelMouseListener);
}
private void generateAuthorStrings() {
if (!libInfo.authors.isEmpty()) {
authorsWithLinks = "<html><body><small>by ";
authorsWithouthLinks = "<html><body><small>by ";
for (int i = 0; i < libInfo.authors.size(); i++) {
Author author = libInfo.authors.get(i);
authorsWithLinks += "<a href=\"" + author.url + "\">" + author.name + "</a>";
authorsWithouthLinks += author.name;
if (i + 2 < libInfo.authors.size()) {
authorsWithLinks += ", ";
authorsWithouthLinks += ", ";
} else if (i + 2 == libInfo.authors.size()) {
if (libInfo.authors.size() > 2) {
authorsWithLinks += ", and ";
authorsWithouthLinks += ", and ";
} else {
authorsWithLinks += " and ";
authorsWithouthLinks += " and ";
}
}
}
authorsWithLinks += "</small></body></html>";
authorsWithouthLinks += "</small></body></html>";
}
}
/**
* Create the widgets for the header panel which is visible when the library
* panel is not clicked
*/
private void configureHeaderPane() {
private void addPaneComponents() {
headerPanel = new JPanel();
headerPanel.setFocusable(true);
headerPanel.setOpaque(false);
@@ -416,65 +390,94 @@ public class LibraryListPanel extends JPanel implements Scrollable {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.anchor = GridBagConstraints.WEST;
JLabel nameLabel = new JLabel(libInfo.name);
Font font = nameLabel.getFont();
font = font.deriveFont(font.getStyle() | Font.BOLD);
nameLabel.setFont(font);
headerPanel.add(nameLabel, c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.EAST;
authorLabel = new JTextPane();
authorLabel.setContentType("text/html");
authorLabel.setText(authorsWithouthLinks);
authorLabel.setHighlighter(null);
authorLabel.setOpaque(false);
authorLabel.setEditable(false);
authorLabel.addHyperlinkListener(hyperlinkOpener);
headerPanel.add(authorLabel, c);
// c = new GridBagConstraints();
// c.gridx = 2;
// c.gridy = 0;
// c.anchor = GridBagConstraints.NORTHEAST;
// JLabel categoryLabel = new JLabel(libInfo.categoryName + " ");
// font = categoryLabel.getFont();
// font = font.deriveFont(font.getSize() * 0.7f);
// categoryLabel.setFont(font);
// headerPanel.add(categoryLabel, c);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.WEST;
// briefText = new JTextArea(libInfo.brief);
// briefText.setHighlighter(null);
// briefText.setOpaque(false);
// briefText.setEditable(false);
// briefText.setLineWrap(true);
// briefText.setWrapStyleWord(true);
// Font font = briefText.getFont();
// font = font.deriveFont(font.getSize() * 0.85f);
// briefText.setFont(font);
// headerPanel.add(briefText, c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.anchor = GridBagConstraints.EAST;
headerPanel.add(Box.createRigidArea(new Dimension(BUTTON_WIDTH, 1)), c);
descriptionText = new JTextPane();
descriptionText.setContentType("text/html");
descriptionText.setText("<html><body>" + libInfo.description + "</body></html>");
descriptionText.setHighlighter(null);
descriptionText.setOpaque(false);
descriptionText.setEditable(false);
descriptionText.setMargin(new Insets(0, 0, 10, 5));
descriptionText.addHyperlinkListener(hyperlinkOpener);
headerPanel.add(descriptionText, c);
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);
description = new JTextArea(libInfo.description);
public void addProgressBarAndButton() {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 3;
c.gridy = 0;
c.weighty = 1;
c.gridheight = 2;
c.fill = GridBagConstraints.VERTICAL;
c.anchor = GridBagConstraints.NORTH;
JPanel rightPane = new JPanel();
rightPane.setOpaque(false);
rightPane.setLayout(new BoxLayout(rightPane, BoxLayout.Y_AXIS));
headerPanel.add(rightPane, c);
installProgressBar = new JProgressBar();
installProgressBar.setString("");
installProgressBar.setStringPainted(true);
installProgressBar.setVisible(false);
Dimension d = installProgressBar.getPreferredSize();
d.width = BUTTON_WIDTH;
installProgressBar.setPreferredSize(d);
installProgressBar.setMaximumSize(d);
installProgressBar.setMinimumSize(d);
installProgressBar.setOpaque(false);
rightPane.add(installProgressBar);
installProgressBar.setAlignmentX(CENTER_ALIGNMENT);
rightPane.add(Box.createVerticalGlue());
installOrRemove = new JButton();
if (libInfo.isInstalled) {
} else {
installOrRemove.setText("Install");
ActionListener installLibAction = new ActionListener() {
public void actionPerformed(ActionEvent arg) {
try {
URL url = new URL(libInfo.link);
@@ -490,85 +493,47 @@ public class LibraryListPanel extends JPanel implements Scrollable {
};
installOrRemove.addActionListener(installLibAction);
}
clickedCard.setLayout(new BoxLayout(clickedCard, BoxLayout.X_AXIS));
description.setHighlighter(null);
description.setOpaque(false);
description.setEditable(false);
description.setLineWrap(true);
description.setWrapStyleWord(true);
Font font = this.description.getFont();
font = font.deriveFont(font.getSize() * 0.9f);
description.setFont(font);
clickedCard.add(description);
clickedCard.add(Box.createHorizontalGlue());
clickedCard.add(installOrRemove);
installOrRemove.setAlignmentY(Component.BOTTOM_ALIGNMENT);
description.setAlignmentY(Component.BOTTOM_ALIGNMENT);
Dimension installButtonDimensions = installOrRemove.getPreferredSize();
installButtonDimensions.width = BUTTON_WIDTH;
installOrRemove.setPreferredSize(installButtonDimensions);
infoPanel.add(unclickedCard, unclickedCardId);
infoPanel.add(clickedCard, clickedCardId);
add(infoPanel);
installOrRemove.setMaximumSize(installButtonDimensions);
installOrRemove.setMinimumSize(installButtonDimensions);
installOrRemove.setOpaque(false);
rightPane.add(installOrRemove);
installOrRemove.setAlignmentX(CENTER_ALIGNMENT);
// Set the minimum size of this pane to be the sum of the height of the
// progress bar and install button
d = installProgressBar.getPreferredSize();
Dimension d2 = installOrRemove.getPreferredSize();
d.width = BUTTON_WIDTH;
d.height = d.height+d2.height;
rightPane.setMinimumSize(d);
rightPane.setPreferredSize(d);
}
/**
* 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);
installOrRemove.setVisible(doShow);
if (doShow) {
authorLabel.setText(authorsWithLinks);
} else {
cardLayout.show(infoPanel, unclickedCardId);
authorLabel.setText(authorsWithouthLinks);
}
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) {
if (isInfoShown) {
Dimension textDimentions = description.getPreferredSize();
textDimentions.width = width - installOrRemove.getPreferredSize().width;
textDimentions.height = calculateHeight(description, textDimentions.width);
description.setMaximumSize(textDimentions);
description.setMinimumSize(textDimentions);
description.setPreferredSize(textDimentions);
description.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;
}
Dimension d = headerPanel.getPreferredSize();
d.width = width;
setMaximumSize(d);
setMinimumSize(d);
setPreferredSize(d);
setSize(d);
revalidate();
}
+17 -6
View File
@@ -93,7 +93,7 @@ public class LibraryListing {
}
private boolean matches(LibraryInfo libInfo, String filter) {
filter = "\\p{Alnum}*" + filter.toLowerCase() + "\\p{Alnum}*";
filter = ".*" + filter.toLowerCase() + ".*";
if (filter.isEmpty()) {
return true;
@@ -104,9 +104,11 @@ public class LibraryListing {
return true;
}
}
return libInfo.name.toLowerCase().matches(filter)
return libInfo.description.toLowerCase().matches(filter)
|| libInfo.categoryName.toLowerCase().matches(filter)
|| libInfo.name.toLowerCase().matches(filter);
}
public static class LibraryListFetcher {
@@ -175,7 +177,7 @@ public class LibraryListing {
public String versionId;
public String link;
boolean isInstalled;
boolean isInstalled = false;
public String brief;
@@ -271,9 +273,15 @@ public class LibraryListing {
currentLibInfo.authors.add(currentAuthor);
currentAuthor = null;
doingAuthor = false;
} else if (doingDescription) {
currentLibInfo.description = new String(ch, start, length).trim();
doingDescription = false;
String str = new String(ch, start, length);
if (currentLibInfo.description == null) {
currentLibInfo.description = str;
} else {
currentLibInfo.description += str;
}
}
}
@@ -291,6 +299,9 @@ public class LibraryListing {
}
currentLibInfo = null;
} else if ("description".equals(qName)) {
currentLibInfo.description = currentLibInfo.description.trim();
doingDescription = false;
}
}
+6 -23
View File
@@ -269,15 +269,6 @@ public class LibraryManager {
pane.add(scrollPane, c);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.getViewport().addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ce) {
int width = scrollPane.getViewportBorderBounds().width;
libraryListPane.setWidth(width);
}
});
libraryListPane.setPreferredViewPositionListener(new PreferredViewPositionListener() {
public void handlePreferredLocation(Point p) {
@@ -314,19 +305,7 @@ public class LibraryManager {
}
});
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 3;
c.weightx = 1;
c.gridwidth = 2;
installProgressBar = new JProgressBar();
installProgressBar.setString("");
installProgressBar.setStringPainted(true);
installProgressBar.setVisible(false);
pane.add(installProgressBar, c);
dialog.setMinimumSize(new Dimension(400, 400));
dialog.setMinimumSize(new Dimension(650, 400));
}
private void registerDisposeListeners() {
@@ -690,7 +669,11 @@ public class LibraryManager {
FileDownloader fileDownloader;
public LibraryInstaller(FileDownloader downloader, ProgressMonitor pm) {
progressMonitor = pm;
if (pm == null) {
progressMonitor = new NullProgressMonitor();
} else {
progressMonitor = pm;
}
fileDownloader = downloader;
}