From b0a357f5d3e973106c4b8dcf2f067993c4377a92 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Thu, 26 Mar 2015 10:40:58 +0100 Subject: [PATCH] Library Manager: added Type filter dropdown --- .../libraries/filters/TypePredicate.java | 24 +++++++ .../ui/DropdownLibraryOfTypeItem.java | 25 ++++++++ .../ui/LibrariesIndexTableModel.java | 5 +- .../libraries/ui/LibraryManagerUI.java | 63 +++++++++++++++++-- .../ui/ContributionIndexTableModel.java | 6 +- .../ui/FilteredAbstractTableModel.java | 2 +- .../contributions/ui/InstallerJDialog.java | 50 ++++++++------- .../libraries/ContributedLibrary.java | 2 + .../libraries/LibrariesIndex.java | 14 +++++ .../processing/app/packages/UserLibrary.java | 5 ++ 10 files changed, 161 insertions(+), 35 deletions(-) create mode 100644 app/src/cc/arduino/contributions/libraries/filters/TypePredicate.java create mode 100644 app/src/cc/arduino/contributions/libraries/ui/DropdownLibraryOfTypeItem.java diff --git a/app/src/cc/arduino/contributions/libraries/filters/TypePredicate.java b/app/src/cc/arduino/contributions/libraries/filters/TypePredicate.java new file mode 100644 index 000000000..8cb56a544 --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/filters/TypePredicate.java @@ -0,0 +1,24 @@ +package cc.arduino.contributions.libraries.filters; + +import cc.arduino.contributions.libraries.ContributedLibrary; +import com.google.common.base.Predicate; + +public class TypePredicate implements Predicate { + + private final String type; + + public TypePredicate(String type) { + this.type = type; + } + + @Override + public boolean apply(ContributedLibrary input) { + return input.getTypes() != null && input.getTypes().contains(type); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof TypePredicate && ((TypePredicate) obj).type.equals(type); + } + +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/DropdownLibraryOfTypeItem.java b/app/src/cc/arduino/contributions/libraries/ui/DropdownLibraryOfTypeItem.java new file mode 100644 index 000000000..07a650bee --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/ui/DropdownLibraryOfTypeItem.java @@ -0,0 +1,25 @@ +package cc.arduino.contributions.libraries.ui; + +import cc.arduino.contributions.libraries.ContributedLibrary; +import cc.arduino.contributions.libraries.filters.CategoryPredicate; +import cc.arduino.contributions.libraries.filters.TypePredicate; +import cc.arduino.contributions.ui.DropdownItem; +import com.google.common.base.Predicate; + +public class DropdownLibraryOfTypeItem implements DropdownItem { + + private final String type; + + public DropdownLibraryOfTypeItem(String type) { + this.type = type; + } + + public String toString() { + return type; + } + + @Override + public Predicate getFilterPredicate() { + return new TypePredicate(type); + } +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java b/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java index f9d9f69e3..63e6aac68 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java @@ -34,6 +34,7 @@ import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.VersionComparator; import cc.arduino.contributions.ui.FilteredAbstractTableModel; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import java.util.*; @@ -137,8 +138,8 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel selectedCategoryFilter = null; String selectedFilters[] = null; - public void updateIndexFilter(Predicate categoryFilter, String filters[]) { - selectedCategoryFilter = categoryFilter; + public void updateIndexFilter(String filters[], Predicate... additionalFilters) { + selectedCategoryFilter = Predicates.and(additionalFilters); selectedFilters = filters; update(); } diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index e949ddbed..beb16ce19 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -33,17 +33,23 @@ import cc.arduino.contributions.libraries.LibrariesIndexer; import cc.arduino.contributions.packages.ui.InstallerJDialogUncaughtExceptionHandler; import cc.arduino.contributions.ui.*; import cc.arduino.utils.Progress; +import com.google.common.base.Predicate; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Arrays; import java.util.Collection; import static processing.app.I18n._; @SuppressWarnings("serial") -public class LibraryManagerUI extends InstallerJDialog { +public class LibraryManagerUI extends InstallerJDialog { private LibrariesIndexer indexer; + private final JComboBox typeChooser; + private Predicate typeFilter; @Override protected FilteredAbstractTableModel createContribModel() { @@ -80,11 +86,46 @@ public class LibraryManagerUI extends InstallerJDialog { public LibraryManagerUI(Frame parent) { super(parent, "Library Manager", Dialog.ModalityType.APPLICATION_MODAL, _("No internet connection available, the list of available libraries is not complete. You will be able to manage only the libraries you've already installed.")); + + filtersContainer.add(new JLabel(_("Category:")), 1); + filtersContainer.remove(2); + + typeChooser = new JComboBox(); + typeChooser.setMaximumRowCount(20); + typeChooser.setEnabled(false); + + filtersContainer.add(Box.createHorizontalStrut(5), 0); + filtersContainer.add(new JLabel(_("Type:")), 1); + filtersContainer.add(typeChooser, 2); + } + + protected final ActionListener typeChooserActionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent event) { + DropdownItem selected = (DropdownItem) typeChooser.getSelectedItem(); + if (typeFilter == null || !typeFilter.equals(selected)) { + typeFilter = selected.getFilterPredicate(); + if (contribTable.getCellEditor() != null) { + contribTable.getCellEditor().stopCellEditing(); + } + updateIndexFilter(filters, categoryFilter, typeFilter); + } + } + }; + + @Override + public void updateIndexFilter(String[] filters, Predicate... additionalFilters) { + if (additionalFilters.length == 1) { + additionalFilters = new Predicate[] { additionalFilters[0], typeFilter }; + } + super.updateIndexFilter(filters, additionalFilters); } public void setIndexer(LibrariesIndexer indexer) { this.indexer = indexer; categoryChooser.removeActionListener(categoryChooserActionListener); + typeChooser.removeActionListener(typeChooserActionListener); // TODO: Remove setIndexer and make getContribModel // return a FilteredAbstractTableModel @@ -93,8 +134,6 @@ public class LibraryManagerUI extends InstallerJDialog { categoryFilter = null; categoryChooser.removeAllItems(); - categoryChooser.addActionListener(categoryChooserActionListener); - // Load categories categoryChooser.addItem(new DropdownAllItem()); categoryChooser.addItem(new DropdownInstalledContributionItem()); @@ -104,9 +143,21 @@ public class LibraryManagerUI extends InstallerJDialog { categoryChooser.addItem(new DropdownLibraryOfCategoryItem(category)); } - // Enable categories combo only if there are two or more choices - int count = categoryChooser.getItemCount(); - categoryChooser.setEnabled(count > 1); + categoryChooser.setEnabled(categoryChooser.getItemCount() > 1); + + categoryChooser.addActionListener(categoryChooserActionListener); + categoryChooser.setSelectedIndex(0); + + typeFilter = null; + typeChooser.removeAllItems(); + typeChooser.addItem(new DropdownAllItem()); + Collection types = indexer.getIndex().getTypes(); + for (String type : types) { + typeChooser.addItem(new DropdownLibraryOfTypeItem(type)); + } + typeChooser.setEnabled(typeChooser.getItemCount() > 1); + typeChooser.addActionListener(typeChooserActionListener); + typeChooser.setSelectedIndex(1); filterField.setEnabled(contribModel.getRowCount() > 0); diff --git a/app/src/cc/arduino/contributions/packages/ui/ContributionIndexTableModel.java b/app/src/cc/arduino/contributions/packages/ui/ContributionIndexTableModel.java index c0fc5da08..ca364be06 100644 --- a/app/src/cc/arduino/contributions/packages/ui/ContributionIndexTableModel.java +++ b/app/src/cc/arduino/contributions/packages/ui/ContributionIndexTableModel.java @@ -33,6 +33,7 @@ import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.packages.ContributionsIndex; import cc.arduino.contributions.ui.FilteredAbstractTableModel; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import java.util.ArrayList; import java.util.LinkedList; @@ -136,11 +137,12 @@ public class ContributionIndexTableModel extends FilteredAbstractTableModel categoryFilter, String filters[]) { + public void updateIndexFilter(String filters[], Predicate... additionalFilters) { contributions.clear(); + Predicate filter = Predicates.and(additionalFilters); for (ContributedPackage pack : index.getPackages()) { for (ContributedPlatform platform : pack.getPlatforms()) { - if (!categoryFilter.apply(platform)) { + if (!filter.apply(platform)) { continue; } if (!stringContainsAll(platform.getName(), filters)) diff --git a/app/src/cc/arduino/contributions/ui/FilteredAbstractTableModel.java b/app/src/cc/arduino/contributions/ui/FilteredAbstractTableModel.java index 651c7ea87..e09cfb2a7 100644 --- a/app/src/cc/arduino/contributions/ui/FilteredAbstractTableModel.java +++ b/app/src/cc/arduino/contributions/ui/FilteredAbstractTableModel.java @@ -34,6 +34,6 @@ import javax.swing.table.AbstractTableModel; public abstract class FilteredAbstractTableModel extends AbstractTableModel { - abstract public void updateIndexFilter(Predicate categoryFilter, String[] filters); + abstract public void updateIndexFilter(String[] filters, Predicate... additionalFilters); } diff --git a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java index d4b60c034..a95d1c434 100644 --- a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java +++ b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java @@ -28,8 +28,11 @@ */ package cc.arduino.contributions.ui; +import cc.arduino.contributions.packages.ui.ContributionIndexTableModel; import cc.arduino.contributions.ui.listeners.AbstractKeyListener; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; import processing.app.Base; import processing.app.Theme; @@ -42,6 +45,9 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; import static cc.arduino.contributions.packages.ui.ContributionIndexTableModel.DESCRIPTION_COL; import static processing.app.I18n._; @@ -50,13 +56,10 @@ public abstract class InstallerJDialog extends JDialog { // Toolbar on top of the window: // - Categories drop-down menu - protected final JLabel categoryLabel; protected final JComboBox categoryChooser; - protected final Component categoryStrut1; - protected final Component categoryStrut2; - protected final Component categoryStrut3; // - Search text-field protected final FilterJTextField filterField; + protected final JPanel filtersContainer; // Currently selected category and filters protected Predicate categoryFilter; protected String[] filters; @@ -65,7 +68,7 @@ public abstract class InstallerJDialog extends JDialog { // Real contribution table protected JTable contribTable; // Model behind the table - protected FilteredAbstractTableModel contribModel; + protected FilteredAbstractTableModel contribModel; abstract protected FilteredAbstractTableModel createContribModel(); @@ -90,12 +93,6 @@ public abstract class InstallerJDialog extends JDialog { pane.setLayout(new BorderLayout()); { - categoryStrut1 = Box.createHorizontalStrut(5); - categoryStrut2 = Box.createHorizontalStrut(5); - categoryStrut3 = Box.createHorizontalStrut(5); - - categoryLabel = new JLabel(_("Category:")); - categoryChooser = new JComboBox(); categoryChooser.setMaximumRowCount(20); categoryChooser.setEnabled(false); @@ -107,20 +104,20 @@ public abstract class InstallerJDialog extends JDialog { if (contribTable.getCellEditor() != null) { contribTable.getCellEditor().stopCellEditing(); } - contribModel.updateIndexFilter(categoryFilter, filters); + updateIndexFilter(filters, categoryFilter); } }; - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - panel.add(categoryStrut1); - panel.add(categoryLabel); - panel.add(categoryStrut2); - panel.add(categoryChooser); - panel.add(categoryStrut3); - panel.add(filterField); - panel.setBorder(new EmptyBorder(7, 7, 7, 7)); - pane.add(panel, BorderLayout.NORTH); + filtersContainer = new JPanel(); + filtersContainer.setLayout(new BoxLayout(filtersContainer, BoxLayout.X_AXIS)); + filtersContainer.add(Box.createHorizontalStrut(5)); + filtersContainer.add(new JLabel(_("Type:"))); + filtersContainer.add(Box.createHorizontalStrut(5)); + filtersContainer.add(categoryChooser); + filtersContainer.add(Box.createHorizontalStrut(5)); + filtersContainer.add(filterField); + filtersContainer.setBorder(new EmptyBorder(7, 7, 7, 7)); + pane.add(filtersContainer, BorderLayout.NORTH); } contribModel = createContribModel(); @@ -216,7 +213,7 @@ public abstract class InstallerJDialog extends JDialog { } setProgressVisible(false, ""); - setMinimumSize(new Dimension(600, 450)); + setMinimumSize(new Dimension(800, 450)); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); @@ -235,6 +232,11 @@ public abstract class InstallerJDialog extends JDialog { }); } + public void updateIndexFilter(String[] filters, Predicate... additionalFilters) { + Collection> notNullAdditionalFilters = Collections2.filter(Arrays.asList(additionalFilters), Predicates.notNull()); + contribModel.updateIndexFilter(filters, notNullAdditionalFilters.toArray(new Predicate[notNullAdditionalFilters.size()])); + } + public void setErrorMessage(String message) { errorMessage.setText("" + message + ""); errorMessageBox.setVisible(true); @@ -273,7 +275,7 @@ public abstract class InstallerJDialog extends JDialog { if (contribTable.getCellEditor() != null) { contribTable.getCellEditor().stopCellEditing(); } - contribModel.updateIndexFilter(categoryFilter, filters); + updateIndexFilter(filters, categoryFilter); } } }; diff --git a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java index 76e030a90..0e33a309e 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java @@ -62,6 +62,8 @@ public abstract class ContributedLibrary extends DownloadableContribution { public abstract List getArchitectures(); + public abstract List getTypes(); + public abstract List getRequires(); private boolean readOnly; diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java index 27661fd03..b38e882c4 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java @@ -62,4 +62,18 @@ public abstract class LibrariesIndex { return categories; } + + public List getTypes() { + Collection typesAccumulator = new HashSet(); + for (ContributedLibrary lib : getLibraries()) { + if (lib.getTypes() != null) { + typesAccumulator.addAll(lib.getTypes()); + } + } + + List types = new LinkedList(typesAccumulator); + Collections.sort(types); + + return types; + } } diff --git a/arduino-core/src/processing/app/packages/UserLibrary.java b/arduino-core/src/processing/app/packages/UserLibrary.java index f1db366c6..07965fc65 100644 --- a/arduino-core/src/processing/app/packages/UserLibrary.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -190,6 +190,11 @@ public class UserLibrary extends ContributedLibrary { return category; } + @Override + public List getTypes() { + return Arrays.asList("Contributed"); + } + @Override public String getLicense() { return license;