mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Merge branch 'master' of github.com:processing/processing
This commit is contained in:
@@ -53,18 +53,18 @@ public class ContributionListing {
|
||||
Map<String, Contribution> librariesByImportHeader;
|
||||
// TODO: Every contribution is getting added twice
|
||||
// and nothing is replaced ever.
|
||||
List<Contribution> allContributions;
|
||||
Set<Contribution> allContributions;
|
||||
boolean listDownloaded;
|
||||
boolean listDownloadFailed;
|
||||
ReentrantLock downloadingListingLock;
|
||||
|
||||
|
||||
private ContributionListing() {
|
||||
listeners = new ArrayList<ChangeListener>();
|
||||
advertisedContributions = new ArrayList<AvailableContribution>();
|
||||
librariesByCategory = new HashMap<String, List<Contribution>>();
|
||||
librariesByImportHeader = new HashMap<String, Contribution>();
|
||||
allContributions = new ArrayList<Contribution>();
|
||||
listeners = new ArrayList<>();
|
||||
advertisedContributions = new ArrayList<>();
|
||||
librariesByCategory = new HashMap<>();
|
||||
librariesByImportHeader = new HashMap<>();
|
||||
allContributions = new LinkedHashSet<>();
|
||||
downloadingListingLock = new ReentrantLock();
|
||||
|
||||
//listingFile = Base.getSettingsFile("contributions.txt");
|
||||
@@ -96,7 +96,6 @@ public class ContributionListing {
|
||||
for (Contribution contribution : advertisedContributions) {
|
||||
addContribution(contribution);
|
||||
}
|
||||
Collections.sort(allContributions, COMPARATOR);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,11 +138,8 @@ public class ContributionListing {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < allContributions.size(); i++) {
|
||||
if (allContributions.get(i) == oldLib) {
|
||||
allContributions.set(i, newLib);
|
||||
}
|
||||
}
|
||||
allContributions.remove(oldLib);
|
||||
allContributions.add(newLib);
|
||||
|
||||
notifyChange(oldLib, newLib);
|
||||
}
|
||||
@@ -169,7 +165,6 @@ public class ContributionListing {
|
||||
}
|
||||
allContributions.add(contribution);
|
||||
notifyAdd(contribution);
|
||||
Collections.sort(allContributions, COMPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,43 +229,7 @@ public class ContributionListing {
|
||||
}
|
||||
|
||||
|
||||
// public List<Contribution> getAllContributions() {
|
||||
// return new ArrayList<Contribution>(allContributions);
|
||||
// }
|
||||
|
||||
|
||||
// public List<Contribution> getLibararies(String category) {
|
||||
// ArrayList<Contribution> libinfos =
|
||||
// new ArrayList<Contribution>(librariesByCategory.get(category));
|
||||
// Collections.sort(libinfos, nameComparator);
|
||||
// return libinfos;
|
||||
// }
|
||||
|
||||
|
||||
protected List<Contribution> getFilteredLibraryList(String category, List<String> filters) {
|
||||
ArrayList<Contribution> filteredList =
|
||||
new ArrayList<Contribution>(allContributions);
|
||||
|
||||
Iterator<Contribution> it = filteredList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Contribution libInfo = it.next();
|
||||
//if (category != null && !category.equals(libInfo.getCategory())) {
|
||||
if (category != null && !libInfo.hasCategory(category)) {
|
||||
it.remove();
|
||||
} else {
|
||||
for (String filter : filters) {
|
||||
if (!matches(libInfo, filter)) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredList;
|
||||
}
|
||||
|
||||
|
||||
private boolean matches(Contribution contrib, String typed) {
|
||||
public boolean matches(Contribution contrib, String typed) {
|
||||
int colon = typed.indexOf(":");
|
||||
if (colon != -1) {
|
||||
String isText = typed.substring(0, colon);
|
||||
@@ -601,11 +560,7 @@ public class ContributionListing {
|
||||
}
|
||||
|
||||
|
||||
static public Comparator<Contribution> COMPARATOR = new Comparator<Contribution>() {
|
||||
public int compare(Contribution o1, Contribution o2) {
|
||||
return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
|
||||
}
|
||||
};
|
||||
static public Comparator<Contribution> COMPARATOR = Comparator.comparing(o -> o.getName().toLowerCase());
|
||||
|
||||
|
||||
public interface ChangeListener {
|
||||
|
||||
@@ -73,24 +73,14 @@ public class ContributionTab extends JPanel {
|
||||
this.contribDialog = dialog;
|
||||
this.contribType = type;
|
||||
|
||||
filter = new Contribution.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
return contrib.getType() == contribType;
|
||||
}
|
||||
};
|
||||
filter = contrib -> contrib.getType() == contribType;
|
||||
|
||||
contribListing = ContributionListing.getInstance();
|
||||
statusPanel = new StatusPanel(this, 650);
|
||||
contributionListPanel = new ListPanel(this, filter);
|
||||
contributionListPanel = new ListPanel(this, filter, false);
|
||||
contribListing.addListener(contributionListPanel);
|
||||
}
|
||||
|
||||
|
||||
// public boolean hasUpdates(Base base) {
|
||||
// return contribListing.hasUpdates(base);
|
||||
// }
|
||||
|
||||
|
||||
public void showFrame(final Editor editor, boolean error, boolean loading) {
|
||||
this.editor = editor;
|
||||
|
||||
@@ -277,9 +267,7 @@ public class ContributionTab extends JPanel {
|
||||
|
||||
|
||||
protected void filterLibraries(String category, List<String> filters) {
|
||||
List<Contribution> filteredLibraries =
|
||||
contribListing.getFilteredLibraryList(category, filters);
|
||||
contributionListPanel.filterLibraries(filteredLibraries);
|
||||
contributionListPanel.filterLibraries(category, filters);
|
||||
}
|
||||
|
||||
|
||||
@@ -449,15 +437,16 @@ public class ContributionTab extends JPanel {
|
||||
contributionListPanel.panelByContribution.values();
|
||||
for (DetailPanel detailPanel : collection) {
|
||||
detailPanel.update();
|
||||
|
||||
// Refreshing the ContributionUpdateTab's status icons
|
||||
contributionListPanel.updatePanelOrdering(contributionListPanel
|
||||
.panelByContribution.keySet());
|
||||
}
|
||||
contributionListPanel.model.fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
||||
protected boolean hasUpdates() {
|
||||
return contributionListPanel.getRowCount() > 0;
|
||||
}
|
||||
|
||||
public boolean filterHasFocus() {
|
||||
return filterField != null && filterField.hasFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.swing.table.*;
|
||||
import processing.app.Base;
|
||||
import processing.app.Platform;
|
||||
import processing.app.ui.Toolkit;
|
||||
import sun.swing.SwingUtilities2;
|
||||
|
||||
|
||||
// The "Scrollable" implementation and its methods here take care of preventing
|
||||
@@ -45,14 +46,13 @@ import processing.app.ui.Toolkit;
|
||||
public class ListPanel extends JPanel
|
||||
implements Scrollable, ContributionListing.ChangeListener {
|
||||
ContributionTab contributionTab;
|
||||
TreeMap<Contribution, DetailPanel> panelByContribution = new TreeMap<Contribution, DetailPanel>(ContributionListing.COMPARATOR);
|
||||
Set<Contribution> visibleContributions = new TreeSet<Contribution>(ContributionListing.COMPARATOR);
|
||||
TreeMap<Contribution, DetailPanel> panelByContribution = new TreeMap<>(ContributionListing.COMPARATOR);
|
||||
|
||||
private DetailPanel selectedPanel;
|
||||
protected Contribution.Filter filter;
|
||||
protected ContributionListing contribListing = ContributionListing.getInstance();
|
||||
protected ContributionRowFilter filter;
|
||||
protected JTable table;
|
||||
DefaultTableModel model;
|
||||
protected TableRowSorter<ContributionTableModel> sorter;
|
||||
ContributionTableModel model;
|
||||
JScrollPane scrollPane;
|
||||
|
||||
static Icon upToDateIcon;
|
||||
@@ -63,7 +63,15 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
|
||||
// Should this be in theme.txt? Of course! Is it? No.
|
||||
static final Color HEADER_BGCOLOR = new Color(0xffEBEBEB);
|
||||
static final Color SECTION_COLOR = new Color(0xFFf8f8f8);
|
||||
static final Color SELECTION_COLOR = new Color(0xffe0fffd);
|
||||
|
||||
static final SectionHeaderContribution[] sections = {
|
||||
new SectionHeaderContribution(ContributionType.LIBRARY),
|
||||
new SectionHeaderContribution(ContributionType.MODE),
|
||||
new SectionHeaderContribution(ContributionType.TOOL),
|
||||
new SectionHeaderContribution(ContributionType.EXAMPLES)
|
||||
};
|
||||
|
||||
public ListPanel() {
|
||||
if (upToDateIcon == null) {
|
||||
@@ -77,30 +85,42 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
|
||||
|
||||
public ListPanel(final ContributionTab contributionTab,
|
||||
Contribution.Filter filter) {
|
||||
final Contribution.Filter filter,
|
||||
final boolean enableSections,
|
||||
final ContributionColumn... columns) {
|
||||
this();
|
||||
this.contributionTab = contributionTab;
|
||||
this.filter = filter;
|
||||
this.filter = new ContributionRowFilter(filter);
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
setOpaque(true);
|
||||
setBackground(Color.WHITE);
|
||||
model = new ContribTableModel();
|
||||
model = new ContributionTableModel(columns);
|
||||
model.enableSections(enableSections);
|
||||
table = new JTable(model) {
|
||||
@Override
|
||||
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
|
||||
Component c = super.prepareRenderer(renderer, row, column);
|
||||
if (isRowSelected(row)) {
|
||||
c.setBackground(new Color(0xe0fffd));
|
||||
Object rowValue = getValueAt(row, column);
|
||||
if (rowValue instanceof SectionHeaderContribution) {
|
||||
c.setBackground(SECTION_COLOR);
|
||||
} else if (isRowSelected(row)) {
|
||||
c.setBackground(SELECTION_COLOR);
|
||||
} else {
|
||||
c.setBackground(Color.white);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
|
||||
if (!(getValueAt(rowIndex, columnIndex) instanceof SectionHeaderContribution)) {
|
||||
super.changeSelection(rowIndex, columnIndex, toggle, extend);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// There is a space before Status
|
||||
String[] colName = { " Status", "Name", "Author" };
|
||||
model.setColumnIdentifiers(colName);
|
||||
scrollPane = new JScrollPane(table);
|
||||
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
@@ -128,55 +148,22 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
setSelectedPanel(panelByContribution.get(table.getValueAt(table
|
||||
.getSelectedRow(), 0)));
|
||||
// Preventing the focus to move out of filterField after typing every character
|
||||
if (!contributionTab.filterField.hasFocus()) {
|
||||
if (!contributionTab.filterHasFocus()) {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel());
|
||||
sorter = new TableRowSorter<>(model);
|
||||
table.setRowSorter(sorter);
|
||||
sorter.setComparator(1, ContributionListing.COMPARATOR);
|
||||
sorter.setComparator(2, new Comparator<Contribution>() {
|
||||
|
||||
@Override
|
||||
public int compare(Contribution o1, Contribution o2) {
|
||||
return getAuthorNameWithoutMarkup(o1.getAuthorList())
|
||||
.compareTo(getAuthorNameWithoutMarkup(o2.getAuthorList()));
|
||||
sorter.setRowFilter(this.filter);
|
||||
for (int i=0; i < model.getColumnCount(); i++) {
|
||||
if (model.columns[i] == ContributionColumn.NAME) {
|
||||
sorter.setSortKeys(Collections.singletonList(new SortKey(i, SortOrder.ASCENDING)));
|
||||
}
|
||||
});
|
||||
sorter.setComparator(0, new Comparator<Contribution>() {
|
||||
|
||||
@Override
|
||||
public int compare(Contribution o1, Contribution o2) {
|
||||
int pos1 = 0;
|
||||
if (o1.isInstalled()) {
|
||||
pos1 = 1;
|
||||
if (contribListing.hasUpdates(o1)) {
|
||||
pos1 = 2;
|
||||
}
|
||||
if (!o1.isCompatible(Base.getRevision())) {
|
||||
pos1 = 3;
|
||||
}
|
||||
} else {
|
||||
pos1 = 4;
|
||||
}
|
||||
int pos2 = 0;
|
||||
if (o2.isInstalled()) {
|
||||
pos2 = 1;
|
||||
if (contribListing.hasUpdates(o2)) {
|
||||
pos2 = 2;
|
||||
}
|
||||
if (!o2.isCompatible(Base.getRevision())) {
|
||||
pos2 = 3;
|
||||
}
|
||||
} else {
|
||||
pos2 = 4;
|
||||
}
|
||||
return pos1 - pos2;
|
||||
}
|
||||
});
|
||||
sorter.setComparator(i, model.columns[i].getComparator());
|
||||
}
|
||||
table.getTableHeader().setDefaultRenderer(new ContribHeaderRenderer());
|
||||
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
@@ -187,6 +174,19 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
table.setVisible(true);
|
||||
}
|
||||
|
||||
private static int getContributionStatusRank(Contribution c) {
|
||||
int pos = 4;
|
||||
if (c.isInstalled()) {
|
||||
pos = 1;
|
||||
if (ContributionListing.getInstance().hasUpdates(c)) {
|
||||
pos = 2;
|
||||
}
|
||||
if (!c.isCompatible(Base.getRevision())) {
|
||||
pos = 3;
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
class ContribHeaderRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
@@ -264,16 +264,11 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
* @return the SortKey, or null if the column is unsorted
|
||||
*/
|
||||
protected SortKey getSortKey(JTable table, int column) {
|
||||
RowSorter rowSorter = table.getRowSorter();
|
||||
if (rowSorter == null) {
|
||||
return null;
|
||||
}
|
||||
return Optional.ofNullable(table.getRowSorter())
|
||||
.map(RowSorter::getSortKeys)
|
||||
.map(columns -> columns.isEmpty() ? null : columns.get(0))
|
||||
.orElse(null);
|
||||
|
||||
List sortedColumns = rowSorter.getSortKeys();
|
||||
if (sortedColumns.size() > 0) {
|
||||
return (SortKey) sortedColumns.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,130 +287,269 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
int column) {
|
||||
Contribution contribution = (Contribution) value;
|
||||
JLabel label = new JLabel();
|
||||
ContributionColumn col = model.columns[column];
|
||||
if (value == null) {
|
||||
// Working on https://github.com/processing/processing/issues/3667
|
||||
//System.err.println("null value seen in getTableCellRendererComponent()");
|
||||
// TODO this is now working, but the underlying issue is not fixed
|
||||
return label;
|
||||
}
|
||||
if (column == 0) {
|
||||
Icon icon = null;
|
||||
label.setFont(ManagerFrame.NORMAL_PLAIN);
|
||||
if (contribution.isInstalled()) {
|
||||
icon = upToDateIcon;
|
||||
if (contribListing.hasUpdates(contribution)) {
|
||||
icon = updateAvailableIcon;
|
||||
}
|
||||
if (!contribution.isCompatible(Base.getRevision())) {
|
||||
icon = incompatibleIcon;
|
||||
}
|
||||
}
|
||||
if ((panelByContribution.get(contribution)).updateInProgress ||
|
||||
(panelByContribution.get(contribution)).installInProgress) {
|
||||
// Display "Loading icon" if download/install in progress
|
||||
label.setIcon(downloadingIcon);
|
||||
} else {
|
||||
label.setIcon(icon);
|
||||
}
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
if (isSelected) {
|
||||
label.setBackground(new Color(0xe0fffd));
|
||||
}
|
||||
label.setOpaque(true);
|
||||
// return table.getDefaultRenderer(Icon.class).getTableCellRendererComponent(table, icon, isSelected, false, row, column);
|
||||
|
||||
} else if (column == 1) {
|
||||
// Generating ellipses based on fontMetrics
|
||||
final Font boldFont = ManagerFrame.NORMAL_BOLD;
|
||||
String fontFace = "<font face=\"" + boldFont.getName() + "\">";
|
||||
FontMetrics fontMetrics = table.getFontMetrics(boldFont); //table.getFont());
|
||||
int colSize = table.getColumnModel().getColumn(1).getWidth();
|
||||
String sentence = contribution.getSentence();
|
||||
//int currentWidth = table.getFontMetrics(table.getFont().deriveFont(Font.BOLD)).stringWidth(contribution.getName() + " | ");
|
||||
int currentWidth = table.getFontMetrics(boldFont).stringWidth(contribution.getName() + " | ");
|
||||
int ellipsesWidth = fontMetrics.stringWidth("...");
|
||||
//String name = "<html><body><b>" + contribution.getName();
|
||||
String name = "<html><body>" + fontFace + contribution.getName();
|
||||
if (sentence == null) {
|
||||
label.setText(name + "</font></body></html>");
|
||||
} else {
|
||||
sentence = " | </font>" + sentence;
|
||||
currentWidth += ellipsesWidth;
|
||||
int i = 0;
|
||||
for (i = 0; i < sentence.length(); i++) {
|
||||
currentWidth += fontMetrics.charWidth(sentence.charAt(i));
|
||||
if (currentWidth >= colSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Adding ellipses only if text doesn't fits into the column
|
||||
if(i != sentence.length()){
|
||||
label.setText(name + sentence.substring(0, i) + "...</body></html>");
|
||||
}else {
|
||||
label.setText(name + sentence + "</body></html>");
|
||||
}
|
||||
}
|
||||
if (!contribution.isCompatible(Base.getRevision())) {
|
||||
label.setForeground(Color.LIGHT_GRAY);
|
||||
}
|
||||
if (table.isRowSelected(row)) {
|
||||
label.setBackground(new Color(0xe0fffd));
|
||||
}
|
||||
label.setFont(ManagerFrame.NORMAL_PLAIN);
|
||||
label.setOpaque(true);
|
||||
} else {
|
||||
if (contribution.isSpecial()) {
|
||||
label = new JLabel(foundationIcon);
|
||||
} else {
|
||||
label = new JLabel();
|
||||
}
|
||||
String authorList = contribution.getAuthorList();
|
||||
String name = getAuthorNameWithoutMarkup(authorList);
|
||||
label.setText(name);
|
||||
label.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
if(!contribution.isCompatible(Base.getRevision())){
|
||||
label.setForeground(Color.LIGHT_GRAY);
|
||||
}else{
|
||||
label.setForeground(Color.BLACK);
|
||||
}
|
||||
if (table.isRowSelected(row)) {
|
||||
label.setBackground(new Color(0xe0fffd));
|
||||
}
|
||||
label.setFont(ManagerFrame.NORMAL_BOLD);
|
||||
label.setOpaque(true);
|
||||
label.setOpaque(true);
|
||||
|
||||
if (value instanceof SectionHeaderContribution && col != ContributionColumn.NAME) {
|
||||
return label;
|
||||
}
|
||||
switch (col) {
|
||||
case STATUS:
|
||||
case STATUS_NO_HEADER:
|
||||
configureStatusColumnLabel(label, contribution);
|
||||
break;
|
||||
case NAME:
|
||||
configureNameColumnLabel(table, label, contribution);
|
||||
break;
|
||||
case AUTHOR:
|
||||
configureAuthorsColumnLabel(label, contribution);
|
||||
break;
|
||||
case INSTALLED_VERSION:
|
||||
label.setText(contribution.getBenignVersion());
|
||||
break;
|
||||
case AVAILABLE_VERSION:
|
||||
label.setText(ContributionListing.getInstance().getLatestPrettyVersion(contribution));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!contribution.isCompatible(Base.getRevision())){
|
||||
label.setForeground(Color.LIGHT_GRAY);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
private void configureStatusColumnLabel(JLabel label, Contribution contribution) {
|
||||
Icon icon = null;
|
||||
label.setFont(ManagerFrame.NORMAL_PLAIN);
|
||||
if ((panelByContribution.get(contribution)).updateInProgress ||
|
||||
(panelByContribution.get(contribution)).installInProgress) {
|
||||
// Display "Loading icon" if download/install in progress
|
||||
icon = downloadingIcon;
|
||||
} else if (contribution.isInstalled()) {
|
||||
if (!contribution.isCompatible(Base.getRevision())) {
|
||||
icon = incompatibleIcon;
|
||||
} else if (ContributionListing.getInstance().hasUpdates(contribution)) {
|
||||
icon = updateAvailableIcon;
|
||||
} else if (panelByContribution.get(contribution).installInProgress
|
||||
|| panelByContribution.get(contribution).updateInProgress) {
|
||||
icon = downloadingIcon;
|
||||
} else {
|
||||
icon = upToDateIcon;
|
||||
}
|
||||
}
|
||||
|
||||
label.setIcon(icon);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
}
|
||||
|
||||
private void configureNameColumnLabel(JTable table, JLabel label, Contribution contribution) {
|
||||
// Generating ellipses based on fontMetrics
|
||||
final Font boldFont = ManagerFrame.NORMAL_BOLD;
|
||||
FontMetrics fontMetrics = table.getFontMetrics(boldFont); //table.getFont());
|
||||
int colSize = table.getColumnModel().getColumn(1).getWidth();
|
||||
int currentWidth = fontMetrics.stringWidth(contribution.getName() + " | ...");
|
||||
String sentence = contribution.getSentence();
|
||||
StringBuilder text = new StringBuilder("<html><body><font face=\"")
|
||||
.append(boldFont.getName())
|
||||
.append("\">")
|
||||
.append(contribution.getName());
|
||||
|
||||
if (sentence == null) {
|
||||
text.append("</font>");
|
||||
} else {
|
||||
int i = 0;
|
||||
for (i = 0; i < sentence.length(); i++) {
|
||||
currentWidth += fontMetrics.charWidth(sentence.charAt(i));
|
||||
if (currentWidth >= colSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
text.append(" | </font>").append(sentence, 0, i);
|
||||
// Adding ellipses only if text doesn't fits into the column
|
||||
if(i != sentence.length()) {
|
||||
text.append("...");
|
||||
}
|
||||
}
|
||||
text.append("</body></html>");
|
||||
label.setText(text.toString());
|
||||
label.setFont(ManagerFrame.NORMAL_PLAIN);
|
||||
}
|
||||
|
||||
private void configureAuthorsColumnLabel(JLabel label, Contribution contribution) {
|
||||
if (contribution.isSpecial()) {
|
||||
label.setIcon(foundationIcon);
|
||||
}
|
||||
String authorList = contribution.getAuthorList();
|
||||
String name = getAuthorNameWithoutMarkup(authorList);
|
||||
label.setText(name);
|
||||
label.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
label.setForeground(Color.BLACK);
|
||||
label.setFont(ManagerFrame.NORMAL_BOLD);
|
||||
}
|
||||
}
|
||||
|
||||
protected enum ContributionColumn {
|
||||
STATUS(" Status"),
|
||||
NAME("Name"),
|
||||
AUTHOR("Author"),
|
||||
INSTALLED_VERSION("Installed"),
|
||||
AVAILABLE_VERSION("Available"),
|
||||
STATUS_NO_HEADER("");
|
||||
|
||||
final String name;
|
||||
|
||||
ContributionColumn(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Comparator<Contribution> getComparator() {
|
||||
Comparator<Contribution> comparator = Comparator.comparing(Contribution::getType)
|
||||
.thenComparingInt(contribution -> contribution instanceof SectionHeaderContribution ? 0 : 1);
|
||||
switch (this) {
|
||||
case STATUS:
|
||||
case STATUS_NO_HEADER:
|
||||
return comparator.thenComparingInt(ListPanel::getContributionStatusRank);
|
||||
case AUTHOR:
|
||||
return comparator.thenComparing(contribution -> getAuthorNameWithoutMarkup(contribution.getAuthorList()));
|
||||
case NAME:
|
||||
default:
|
||||
return comparator.thenComparing(Contribution::getName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContributionTableModel extends AbstractTableModel {
|
||||
|
||||
ContributionColumn[] columns = { ContributionColumn.STATUS, ContributionColumn.NAME, ContributionColumn.AUTHOR };
|
||||
boolean sectionsEnabled;
|
||||
|
||||
ContributionTableModel(ContributionColumn... columns) {
|
||||
if (columns.length > 0) {
|
||||
this.columns = columns;
|
||||
}
|
||||
}
|
||||
|
||||
static private class ContribTableModel extends DefaultTableModel {
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
public int getRowCount() {
|
||||
return ContributionListing.getInstance().allContributions.size() + (sectionsEnabled ? 4 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return columns.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
if (column < 0 || column > columns.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return columns[column].name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return Contribution.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
if (rowIndex >= ContributionListing.getInstance().allContributions.size()) {
|
||||
return sections[rowIndex - ContributionListing.getInstance().allContributions.size()];
|
||||
}
|
||||
|
||||
return ContributionListing.getInstance().allContributions.stream().skip(rowIndex).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public void setColumns(ContributionColumn[] columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public void enableSections(boolean enable) {
|
||||
this.sectionsEnabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContributionRowFilter extends RowFilter<ContributionTableModel, Integer> {
|
||||
Contribution.Filter contributionFilter;
|
||||
Optional<String> categoryFilter = Optional.empty();
|
||||
List<String> stringFilters = Collections.emptyList();
|
||||
|
||||
String getAuthorNameWithoutMarkup(String authorList) {
|
||||
StringBuilder name = new StringBuilder("");
|
||||
ContributionRowFilter(Contribution.Filter contributionFilter) {
|
||||
this.contributionFilter = contributionFilter;
|
||||
}
|
||||
|
||||
public void setCategoryFilter(String categoryFilter) {
|
||||
this.categoryFilter = Optional.ofNullable(categoryFilter);
|
||||
}
|
||||
|
||||
public void setStringFilters(List<String> filters) {
|
||||
this.stringFilters = filters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean include(Entry<? extends ContributionTableModel, ? extends Integer> entry) {
|
||||
Contribution contribution = (Contribution) entry.getValue(0);
|
||||
if (contribution instanceof SectionHeaderContribution) {
|
||||
return includeSection((SectionHeaderContribution) contribution);
|
||||
}
|
||||
return includeContribution(contribution);
|
||||
}
|
||||
|
||||
private boolean includeContribution(Contribution contribution) {
|
||||
return contributionFilter.matches(contribution)
|
||||
&& categoryFilter.map(contribution::hasCategory).orElse(true)
|
||||
&& stringFilters.stream().allMatch(pattern -> ContributionListing.getInstance().matches(contribution, pattern));
|
||||
}
|
||||
|
||||
private boolean includeSection(SectionHeaderContribution section) {
|
||||
return ContributionListing.getInstance().allContributions.stream()
|
||||
.filter(contribution -> contribution.getType() == section.getType())
|
||||
.anyMatch(this::includeContribution);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SectionHeaderContribution extends Contribution {
|
||||
ContributionType type;
|
||||
|
||||
SectionHeaderContribution(ContributionType type) {
|
||||
this.type = type;
|
||||
this.name = getTypeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContributionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstalled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static String getAuthorNameWithoutMarkup(String authorList) {
|
||||
StringBuilder name = new StringBuilder();
|
||||
if (authorList != null) {
|
||||
int parentheses = 0;
|
||||
for (int i = 0; i < authorList.length(); i++) {
|
||||
|
||||
if (authorList.charAt(i) == '[' || authorList.charAt(i) == ']') {
|
||||
continue;
|
||||
}
|
||||
if (authorList.charAt(i) == '(') {
|
||||
i++;
|
||||
while (authorList.charAt(i) != ')') {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
parentheses++;
|
||||
} else if (authorList.charAt(i) == ')') {
|
||||
parentheses--;
|
||||
} else if (parentheses == 0) {
|
||||
name.append(authorList.charAt(i));
|
||||
}
|
||||
}
|
||||
@@ -423,59 +557,36 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
// Thread: EDT
|
||||
void updatePanelOrdering(Set<Contribution> contributionsSet) {
|
||||
model.getDataVector().removeAllElements();
|
||||
int rowCount = 0;
|
||||
for (Contribution entry : contributionsSet) {
|
||||
model.addRow(new Object[]{entry, entry, entry});
|
||||
if (selectedPanel != null &&
|
||||
entry.getName().equals(selectedPanel.getContrib().getName())) {
|
||||
table.setRowSelectionInterval(rowCount, rowCount);
|
||||
}
|
||||
rowCount++;
|
||||
}
|
||||
model.fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
||||
// Thread: EDT
|
||||
public void contributionAdded(final Contribution contribution) {
|
||||
if (filter.matches(contribution)) {
|
||||
if (!panelByContribution.containsKey(contribution)) {
|
||||
DetailPanel newPanel =
|
||||
new DetailPanel(ListPanel.this);
|
||||
panelByContribution.put(contribution, newPanel);
|
||||
visibleContributions.add(contribution);
|
||||
newPanel.setContribution(contribution);
|
||||
add(newPanel);
|
||||
updatePanelOrdering(visibleContributions);
|
||||
updateColors(); // XXX this is the place
|
||||
}
|
||||
if (!panelByContribution.containsKey(contribution)) {
|
||||
DetailPanel newPanel =
|
||||
new DetailPanel(this);
|
||||
panelByContribution.put(contribution, newPanel);
|
||||
newPanel.setContribution(contribution);
|
||||
add(newPanel);
|
||||
model.fireTableDataChanged();
|
||||
updateColors(); // XXX this is the place
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Thread: EDT
|
||||
public void contributionRemoved(final Contribution contribution) {
|
||||
if (filter.matches(contribution)) {
|
||||
DetailPanel panel = panelByContribution.get(contribution);
|
||||
if (panel != null) {
|
||||
remove(panel);
|
||||
panelByContribution.remove(contribution);
|
||||
}
|
||||
visibleContributions.remove(contribution);
|
||||
updatePanelOrdering(visibleContributions);
|
||||
model.fireTableDataChanged();
|
||||
updateColors();
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Thread: EDT
|
||||
public void contributionChanged(final Contribution oldContrib,
|
||||
final Contribution newContrib) {
|
||||
if (filter.matches(oldContrib) || filter.matches(newContrib)) {
|
||||
DetailPanel panel = panelByContribution.get(oldContrib);
|
||||
if (panel == null) {
|
||||
contributionAdded(newContrib);
|
||||
@@ -483,39 +594,16 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
panelByContribution.remove(oldContrib);
|
||||
panel.setContribution(newContrib);
|
||||
panelByContribution.put(newContrib, panel);
|
||||
model.fireTableDataChanged();
|
||||
}
|
||||
if (visibleContributions.contains(oldContrib)) {
|
||||
visibleContributions.remove(oldContrib);
|
||||
visibleContributions.add(newContrib);
|
||||
}
|
||||
updatePanelOrdering(visibleContributions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Thread: EDT
|
||||
public void filterLibraries(List<Contribution> filteredContributions) {
|
||||
visibleContributions.clear();
|
||||
for (Contribution contribution : panelByContribution.keySet()) {
|
||||
if (contribution.getType() == contributionTab.contribType) {
|
||||
// contains() uses equals() and there can be multiple instances,
|
||||
// so Contribution.equals() has to be overridden
|
||||
if (filteredContributions.contains(contribution)) {
|
||||
if (panelByContribution.keySet().contains(contribution)) {
|
||||
visibleContributions.add(contribution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Make the following loop work for optimization
|
||||
// for (Contribution contribution : filteredContributions) {
|
||||
// if (contribution.getType() == contributionTab.contribType) {
|
||||
// if(panelByContribution.keySet().contains(contribution)){
|
||||
// visibleContributions.add(contribution);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
updatePanelOrdering(visibleContributions);
|
||||
public void filterLibraries(String category, List<String> filters) {
|
||||
filter.setCategoryFilter(category);
|
||||
filter.setStringFilters(filters);
|
||||
model.fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -554,38 +642,35 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
int count = 0;
|
||||
for (Entry<Contribution, DetailPanel> entry : panelByContribution.entrySet()) {
|
||||
DetailPanel panel = entry.getValue();
|
||||
Border border = BorderFactory.createEmptyBorder(1, 1, 1, 1);
|
||||
|
||||
if (panel.isVisible() && panel.isSelected()) {
|
||||
panel.setBackground(UIManager.getColor("List.selectionBackground"));
|
||||
panel.setForeground(UIManager.getColor("List.selectionForeground"));
|
||||
panel.setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
|
||||
if (panel.isVisible()) {
|
||||
boolean oddRow = count % 2 == 1;
|
||||
Color bgColor = null;
|
||||
Color fgColor = UIManager.getColor("List.foreground");
|
||||
|
||||
if (panel.isSelected()) {
|
||||
bgColor = UIManager.getColor("List.selectionBackground");
|
||||
fgColor = UIManager.getColor("List.selectionForeground");
|
||||
border = UIManager.getBorder("List.focusCellHighlightBorder");
|
||||
} else if (Platform.isMacOS()) {
|
||||
border = oddRow
|
||||
? UIManager.getBorder("List.oddRowBackgroundPainter")
|
||||
: UIManager.getBorder("List.evenRowBackgroundPainter");
|
||||
} else {
|
||||
bgColor = oddRow
|
||||
? new Color(219, 224, 229)
|
||||
: new Color(241, 241, 241);
|
||||
}
|
||||
|
||||
panel.setForeground(fgColor);
|
||||
if (bgColor != null) {
|
||||
panel.setBackground(bgColor);
|
||||
}
|
||||
count++;
|
||||
|
||||
} else {
|
||||
Border border = null;
|
||||
if (panel.isVisible()) {
|
||||
if (Platform.isMacOS()) {
|
||||
if (count % 2 == 1) {
|
||||
border = UIManager.getBorder("List.oddRowBackgroundPainter");
|
||||
} else {
|
||||
border = UIManager.getBorder("List.evenRowBackgroundPainter");
|
||||
}
|
||||
} else {
|
||||
if (count % 2 == 1) {
|
||||
panel.setBackground(new Color(219, 224, 229));
|
||||
} else {
|
||||
panel.setBackground(new Color(241, 241, 241));
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (border == null) {
|
||||
border = BorderFactory.createEmptyBorder(1, 1, 1, 1);
|
||||
}
|
||||
panel.setBorder(border);
|
||||
panel.setForeground(UIManager.getColor("List.foreground"));
|
||||
}
|
||||
|
||||
panel.setBorder(border);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,39 +708,38 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
*/
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
if (orientation == SwingConstants.VERTICAL) {
|
||||
int lastHeight = 0, height = 0;
|
||||
int bottomOfScrollArea = visibleRect.y + visibleRect.height;
|
||||
if (orientation != SwingConstants.VERTICAL) {
|
||||
return 0;
|
||||
}
|
||||
int lastHeight = 0;
|
||||
int height = 0;
|
||||
int bottomOfScrollArea = visibleRect.y + visibleRect.height;
|
||||
|
||||
for (Component c : getComponents()) {
|
||||
if (c.isVisible()) {
|
||||
if (c instanceof DetailPanel) {
|
||||
Dimension d = c.getPreferredSize();
|
||||
for (Component c : getComponents()) {
|
||||
if (!(c.isVisible() && c instanceof DetailPanel)) {
|
||||
continue;
|
||||
}
|
||||
Dimension d = c.getPreferredSize();
|
||||
|
||||
int nextHeight = height + d.height;
|
||||
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;
|
||||
} else {
|
||||
return visibleRect.y - lastHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastHeight = height;
|
||||
height = nextHeight;
|
||||
}
|
||||
if (direction > 0) {
|
||||
// scrolling down
|
||||
if (nextHeight > bottomOfScrollArea) {
|
||||
return nextHeight - bottomOfScrollArea;
|
||||
}
|
||||
} else if (nextHeight > visibleRect.y) {
|
||||
if (visibleRect.y != height) {
|
||||
return visibleRect.y - height;
|
||||
} else {
|
||||
return visibleRect.y - lastHeight;
|
||||
}
|
||||
}
|
||||
|
||||
lastHeight = height;
|
||||
height = nextHeight;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -673,6 +757,7 @@ implements Scrollable, ContributionListing.ChangeListener {
|
||||
|
||||
|
||||
public int getRowCount() {
|
||||
return panelByContribution.size();
|
||||
// This will count section headers, but it is only used to check if any rows are shown
|
||||
return sorter.getViewRowCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ManagerFrame {
|
||||
modesTab = new ContributionTab(this, ContributionType.MODE);
|
||||
toolsTab = new ContributionTab(this, ContributionType.TOOL);
|
||||
examplesTab = new ContributionTab(this, ContributionType.EXAMPLES);
|
||||
updatesTab = new UpdateContributionTab(this, null);
|
||||
updatesTab = new UpdateContributionTab(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,18 +11,18 @@ import processing.app.ui.Toolkit;
|
||||
|
||||
public class UpdateContributionTab extends ContributionTab {
|
||||
|
||||
public UpdateContributionTab(ManagerFrame dialog, ContributionType type) {
|
||||
public UpdateContributionTab(ManagerFrame dialog) {
|
||||
super();
|
||||
this.contribDialog = dialog;
|
||||
this.contribType = type;
|
||||
|
||||
filter = new Contribution.Filter() {
|
||||
public boolean matches(Contribution contrib) {
|
||||
if (contrib instanceof LocalContribution) {
|
||||
return ContributionListing.getInstance().hasUpdates(contrib);
|
||||
}
|
||||
return false;
|
||||
filter = contrib -> {
|
||||
if (contrib instanceof ListPanel.SectionHeaderContribution) {
|
||||
return true;
|
||||
}
|
||||
if (contrib instanceof LocalContribution) {
|
||||
return ContributionListing.getInstance().hasUpdates(contrib);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
contributionListPanel = new UpdateListPanel(this, filter);
|
||||
// contributionListPanel.setBorder(new EmptyBorder(8, 8, 8, 8));
|
||||
@@ -67,4 +67,9 @@ public class UpdateContributionTab extends ContributionTab {
|
||||
|
||||
setBackground(Color.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatusPanel(DetailPanel contributionPanel) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,236 +1,39 @@
|
||||
package processing.app.contrib;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
import processing.app.Base;
|
||||
|
||||
|
||||
public class UpdateListPanel extends ListPanel {
|
||||
static final Color SECTION_COLOR = new Color(0xFFf8f8f8);
|
||||
static final String[] PLURAL_TYPES = {
|
||||
ContributionType.LIBRARY.getPluralTitle(),
|
||||
ContributionType.MODE.getPluralTitle(),
|
||||
ContributionType.TOOL.getPluralTitle(),
|
||||
ContributionType.EXAMPLES.getPluralTitle(),
|
||||
};
|
||||
Set<String> sectionNames = new HashSet<String>(Arrays.asList(PLURAL_TYPES));
|
||||
|
||||
Contribution.Filter filter;
|
||||
|
||||
public UpdateListPanel(ContributionTab contributionTab,
|
||||
Contribution.Filter filter) {
|
||||
this.contributionTab = contributionTab;
|
||||
super(contributionTab, filter, true,
|
||||
ContributionColumn.STATUS_NO_HEADER,
|
||||
ContributionColumn.NAME,
|
||||
ContributionColumn.AUTHOR,
|
||||
ContributionColumn.INSTALLED_VERSION,
|
||||
ContributionColumn.AVAILABLE_VERSION);
|
||||
|
||||
this.filter = filter;
|
||||
|
||||
setOpaque(true);
|
||||
setBackground(Color.WHITE);
|
||||
|
||||
model = new DefaultTableModel() {
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return (columnIndex == 0) ? Icon.class : String.class;
|
||||
}
|
||||
};
|
||||
|
||||
model.setColumnIdentifiers(new String[] {
|
||||
"", "Name", "Author", "Installed", "Available"
|
||||
});
|
||||
|
||||
table = new JTable(model) {
|
||||
@Override
|
||||
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
|
||||
Component c = super.prepareRenderer(renderer, row, column);
|
||||
String title = (String) getValueAt(row, 1);
|
||||
if (sectionNames.contains(title)) {
|
||||
c.setBackground(SECTION_COLOR);
|
||||
} else {
|
||||
c.setBackground(Color.WHITE);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeSelection(int rowIndex, int columnIndex,
|
||||
boolean toggle, boolean extend) {
|
||||
String title = (String) getValueAt(rowIndex, 1);
|
||||
// Disallow selection on the fake rows
|
||||
if (!sectionNames.contains(title)) {
|
||||
super.changeSelection(rowIndex, columnIndex, toggle, extend);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scrollPane = new JScrollPane(table);
|
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
|
||||
table.setFillsViewportHeight(true);
|
||||
table.setSelectionBackground(new Color(0xe0fffd));
|
||||
table.setSelectionForeground(table.getForeground());
|
||||
table.setFont(ManagerFrame.NORMAL_PLAIN);
|
||||
table.setRowHeight(30);
|
||||
table.setRowMargin(6);
|
||||
table.getColumnModel().setColumnMargin(-1);
|
||||
table.getColumnModel().getColumn(0).setMaxWidth(60);
|
||||
table.setShowGrid(false);
|
||||
table.setCellSelectionEnabled(false);
|
||||
table.setRowSelectionAllowed(true);
|
||||
table.setAutoCreateColumnsFromModel(true);
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value,
|
||||
boolean isSelected,
|
||||
boolean hasFocus,
|
||||
int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, value, isSelected,
|
||||
false, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
table.getTableHeader().setDefaultRenderer(new ContribHeaderRenderer()); /* {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value,
|
||||
boolean isSelected,
|
||||
boolean hasFocus, int row,
|
||||
int column) {
|
||||
super.getTableCellRendererComponent(table, value, isSelected,
|
||||
hasFocus, row, column);
|
||||
JTableHeader tableHeader = table.getTableHeader();
|
||||
if (tableHeader != null) {
|
||||
setForeground(tableHeader.getForeground());
|
||||
}
|
||||
setIcon(getSortIcon(table, column));
|
||||
setBackground(new Color(0xebebeb));
|
||||
return this;
|
||||
}
|
||||
});*/
|
||||
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
layout.setHorizontalGroup(layout.createParallelGroup().addComponent(scrollPane));
|
||||
layout.setVerticalGroup(layout.createSequentialGroup().addComponent(scrollPane));
|
||||
|
||||
setLayout(layout);
|
||||
table.setVisible(true);
|
||||
|
||||
panelByContribution = new TreeMap<Contribution, DetailPanel>(new Comparator<Contribution>() {
|
||||
@Override
|
||||
public int compare(Contribution o1, Contribution o2) {
|
||||
int diff =
|
||||
ContributionManager.getTypeIndex(o1.getType()) -
|
||||
ContributionManager.getTypeIndex(o2.getType());
|
||||
if (diff == 0) {
|
||||
diff = o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
});
|
||||
table.getTableHeader().setEnabled(false);
|
||||
}
|
||||
|
||||
// Thread: EDT
|
||||
@Override
|
||||
void updatePanelOrdering(Set<Contribution> contributionsSet) {
|
||||
model.getDataVector().removeAllElements();
|
||||
ContributionType currentType = null;
|
||||
|
||||
String fontFace = "<font face=\"" + ManagerFrame.NORMAL_BOLD.getName() + "\">";
|
||||
|
||||
for (Contribution entry : contributionsSet) {
|
||||
if (entry.getType() != currentType) {
|
||||
currentType = entry.getType();
|
||||
model.addRow(new Object[] {
|
||||
null, currentType.getPluralTitle(), null, null, null
|
||||
});
|
||||
}
|
||||
//TODO Make this into a function
|
||||
StringBuilder name = new StringBuilder("");
|
||||
String authorList = entry.getAuthorList();
|
||||
if (authorList != null) {
|
||||
for (int i = 0; i < authorList.length(); i++) {
|
||||
if (authorList.charAt(i) == '[' || authorList.charAt(i) == ']') {
|
||||
continue;
|
||||
}
|
||||
if (authorList.charAt(i) == '(') {
|
||||
i++;
|
||||
while (authorList.charAt(i) != ')') {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
name.append(authorList.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
Icon icon = null;
|
||||
if (entry.isInstalled()) {
|
||||
icon = upToDateIcon;
|
||||
if (contribListing.hasUpdates(entry)) {
|
||||
icon = updateAvailableIcon;
|
||||
}
|
||||
if (!entry.isCompatible(Base.getRevision())) {
|
||||
icon = incompatibleIcon;
|
||||
}
|
||||
}
|
||||
if ((panelByContribution.get(entry)).updateInProgress ||
|
||||
(panelByContribution.get(entry)).installInProgress) {
|
||||
// Display "Loading icon" if download/install in progress
|
||||
icon = downloadingIcon;
|
||||
}
|
||||
model.addRow(new Object[] {
|
||||
icon,
|
||||
"<html>" + fontFace + entry.getName() + "</font></html>",
|
||||
name,
|
||||
entry.getBenignVersion(),
|
||||
contributionTab.contribListing.getLatestPrettyVersion(entry)
|
||||
});
|
||||
}
|
||||
model.fireTableDataChanged();
|
||||
UpdateContributionTab tab = (UpdateContributionTab) contributionTab;
|
||||
((UpdateStatusPanel) tab.statusPanel).update();
|
||||
}
|
||||
|
||||
|
||||
// Thread: EDT
|
||||
@Override
|
||||
public void contributionAdded(final Contribution contribution) {
|
||||
// Ensures contributionAdded in ListPanel is only run on LocalContributions
|
||||
if (filter.matches(contribution)) {
|
||||
// TODO make this longer and more contorted [fry]
|
||||
DetailPanel newPanel =
|
||||
contributionTab.contribDialog.getTab(contribution.getType()).contributionListPanel.panelByContribution.get(contribution);
|
||||
if (newPanel == null) {
|
||||
newPanel = new DetailPanel(UpdateListPanel.this);
|
||||
}
|
||||
if (!panelByContribution.containsKey(contribution)) {
|
||||
panelByContribution.put(contribution, newPanel);
|
||||
}
|
||||
visibleContributions.add(contribution);
|
||||
newPanel.setContribution(contribution);
|
||||
add(newPanel);
|
||||
updatePanelOrdering(panelByContribution.keySet());
|
||||
updateColors(); // XXX this is the place
|
||||
super.contributionAdded(contribution);
|
||||
((UpdateStatusPanel) contributionTab.statusPanel).update(); // Enables update button
|
||||
}
|
||||
}
|
||||
|
||||
// Thread: EDT
|
||||
@Override
|
||||
public void contributionRemoved(final Contribution contribution) {
|
||||
super.contributionRemoved(contribution);
|
||||
((UpdateStatusPanel) contributionTab.statusPanel).update(); // Disables update button on last contribution
|
||||
}
|
||||
|
||||
// Thread: EDT
|
||||
@Override
|
||||
public void contributionChanged(final Contribution oldContrib,
|
||||
@@ -240,8 +43,8 @@ public class UpdateListPanel extends ListPanel {
|
||||
contributionAdded(newContrib);
|
||||
} else if (newContrib.isInstalled()) {
|
||||
panelByContribution.remove(oldContrib);
|
||||
visibleContributions.remove(oldContrib);
|
||||
}
|
||||
updatePanelOrdering(visibleContributions);
|
||||
model.fireTableDataChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user