diff --git a/app/src/cc/arduino/contributions/libraries/filters/InstalledLibraryPredicate.java b/app/src/cc/arduino/contributions/libraries/filters/InstalledLibraryPredicate.java new file mode 100644 index 000000000..8312d06d0 --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/filters/InstalledLibraryPredicate.java @@ -0,0 +1,39 @@ +package cc.arduino.contributions.libraries.filters; + +import cc.arduino.contributions.libraries.ContributedLibrary; +import cc.arduino.contributions.libraries.LibrariesIndex; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; + +import java.util.Collection; + +public class InstalledLibraryPredicate implements Predicate { + + private final LibrariesIndex index; + + public InstalledLibraryPredicate(LibrariesIndex index) { + this.index = index; + } + + @Override + public boolean apply(ContributedLibrary input) { + if (input.isInstalled()) { + return true; + } + + Collection installed = Collections2.filter(index.find(input.getName()), new Predicate() { + @Override + public boolean apply(ContributedLibrary input) { + return input.isInstalled(); + } + }); + + return !installed.isEmpty(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InstalledLibraryPredicate; + } + +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java index 3f16a3ccc..35bdf6558 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java @@ -33,6 +33,7 @@ import cc.arduino.contributions.filters.InstalledPredicate; import cc.arduino.contributions.libraries.ContributedLibrary; import cc.arduino.contributions.libraries.ContributedLibraryComparator; import cc.arduino.contributions.libraries.filters.BuiltInPredicate; +import cc.arduino.contributions.libraries.filters.InstalledLibraryPredicate; import cc.arduino.contributions.libraries.filters.OnlyUpstreamReleasePredicate; import cc.arduino.contributions.ui.InstallerTableCell; import cc.arduino.contributions.ui.listeners.DelegatingKeyListener; @@ -65,6 +66,7 @@ import static processing.app.I18n.format; @SuppressWarnings("serial") public class ContributedLibraryTableCell extends InstallerTableCell { + private final LibraryManagerUI indexer; private JPanel panel; private JButton installButton; private Component installButtonPlaceholder; @@ -75,7 +77,9 @@ public class ContributedLibraryTableCell extends InstallerTableCell { private JPanel inactiveButtonsPanel; private JLabel statusLabel; - public ContributedLibraryTableCell() { + public ContributedLibraryTableCell(LibraryManagerUI indexer) { + this.indexer = indexer; + { installButton = new JButton(_("Install")); installButton.addActionListener(new ActionListener() { diff --git a/app/src/cc/arduino/contributions/libraries/ui/DropdownInstalledLibraryItem.java b/app/src/cc/arduino/contributions/libraries/ui/DropdownInstalledLibraryItem.java new file mode 100644 index 000000000..5bf8c7fa7 --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/ui/DropdownInstalledLibraryItem.java @@ -0,0 +1,27 @@ +package cc.arduino.contributions.libraries.ui; + +import cc.arduino.contributions.libraries.ContributedLibrary; +import cc.arduino.contributions.libraries.LibrariesIndex; +import cc.arduino.contributions.libraries.filters.InstalledLibraryPredicate; +import cc.arduino.contributions.ui.DropdownItem; +import com.google.common.base.Predicate; + +import static processing.app.I18n._; + +public class DropdownInstalledLibraryItem implements DropdownItem { + + private final LibrariesIndex index; + + public DropdownInstalledLibraryItem(LibrariesIndex index) { + this.index = index; + } + + public String toString() { + return _("Installed"); + } + + @Override + public Predicate getFilterPredicate() { + return new InstalledLibraryPredicate(index); + } +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index 388d27ff0..39dd31e84 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -39,7 +39,6 @@ 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._; @@ -62,12 +61,12 @@ public class LibraryManagerUI extends InstallerJDialog { @Override protected InstallerTableCell createCellRenderer() { - return new ContributedLibraryTableCell(); + return new ContributedLibraryTableCell(this); } @Override protected InstallerTableCell createCellEditor() { - return new ContributedLibraryTableCell() { + return new ContributedLibraryTableCell(this) { @Override protected void onInstall(ContributedLibrary selectedLibrary, ContributedLibrary installedLibrary) { if (selectedLibrary.isReadOnly()) { @@ -150,7 +149,7 @@ public class LibraryManagerUI extends InstallerJDialog { typeFilter = null; typeChooser.removeAllItems(); typeChooser.addItem(new DropdownAllItem()); - typeChooser.addItem(new DropdownInstalledContributionItem()); + typeChooser.addItem(new DropdownInstalledLibraryItem(indexer.getIndex())); Collection types = indexer.getIndex().getTypes(); for (String type : types) { typeChooser.addItem(new DropdownLibraryOfTypeItem(type)); @@ -169,6 +168,10 @@ public class LibraryManagerUI extends InstallerJDialog { }; } + public LibrariesIndexer getIndexer() { + return indexer; + } + public void setProgress(Progress progress) { progressBar.setValue(progress); } diff --git a/app/src/cc/arduino/contributions/ui/DropdownInstalledContributionItem.java b/app/src/cc/arduino/contributions/ui/DropdownInstalledContributionItem.java deleted file mode 100644 index 625c191bc..000000000 --- a/app/src/cc/arduino/contributions/ui/DropdownInstalledContributionItem.java +++ /dev/null @@ -1,20 +0,0 @@ -package cc.arduino.contributions.ui; - -import cc.arduino.contributions.filters.InstalledPredicate; -import cc.arduino.contributions.packages.DownloadableContribution; -import cc.arduino.contributions.ui.DropdownItem; -import com.google.common.base.Predicate; - -import static processing.app.I18n._; - -public class DropdownInstalledContributionItem implements DropdownItem { - - public String toString() { - return _("Installed"); - } - - @Override - public Predicate getFilterPredicate() { - return new InstalledPredicate(); - } -} diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java index b38e882c4..4d097e515 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java @@ -26,18 +26,32 @@ * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. */ + package cc.arduino.contributions.libraries; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; + import java.util.*; public abstract class LibrariesIndex { public abstract List getLibraries(); + public List find(final String name) { + return new LinkedList(Collections2.filter(getLibraries(), new Predicate() { + @Override + public boolean apply(ContributedLibrary contributedLibrary) { + return name.equals(contributedLibrary.getName()); + } + })); + } + public ContributedLibrary find(String name, String version) { - for (ContributedLibrary lib : getLibraries()) { - if (lib.getName().equals(name) && lib.getVersion().equals(version)) + for (ContributedLibrary lib : find(name)) { + if (lib.getVersion().equals(version)) { return lib; + } } return null; } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index 86cfcbd1f..c1c9969ec 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -28,14 +28,9 @@ */ package cc.arduino.contributions.libraries; -import static processing.app.I18n._; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.module.mrbean.MrBeanModule; import processing.app.BaseNoGui; import processing.app.I18n; import processing.app.helpers.FileUtils; @@ -44,9 +39,14 @@ import processing.app.packages.LegacyUserLibrary; import processing.app.packages.LibraryList; import processing.app.packages.UserLibrary; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.module.mrbean.MrBeanModule; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; + +import static processing.app.I18n._; public class LibrariesIndexer { @@ -60,7 +60,7 @@ public class LibrariesIndexer { public LibrariesIndexer(File preferencesFolder) { indexFile = new File(preferencesFolder, "library_index.json"); stagingFolder = new File(preferencesFolder, "staging" + File.separator + - "libraries"); + "libraries"); } public void parseIndex() throws IOException { @@ -109,9 +109,9 @@ public class LibrariesIndexer { for (File subfolder : list) { if (!BaseNoGui.isSanitaryName(subfolder.getName())) { String mess = I18n.format(_("The library \"{0}\" cannot be used.\n" - + "Library names must contain only basic letters and numbers.\n" - + "(ASCII only and no spaces, and it cannot start with a number)"), - subfolder.getName()); + + "Library names must contain only basic letters and numbers.\n" + + "(ASCII only and no spaces, and it cannot start with a number)"), + subfolder.getName()); BaseNoGui.showMessage(_("Ignoring bad library name"), mess); continue; } @@ -119,21 +119,18 @@ public class LibrariesIndexer { try { scanLibrary(subfolder); } catch (IOException e) { - System.out.println(I18n.format(_("Invalid library found in {0}: {1}"), - subfolder, e.getMessage())); + System.out.println(I18n.format(_("Invalid library found in {0}: {1}"), subfolder, e.getMessage())); } } } private void scanLibrary(File folder) throws IOException { - boolean readOnly = !FileUtils - .isSubDirectory(sketchbookLibrariesFolder, folder); + boolean readOnly = !FileUtils.isSubDirectory(sketchbookLibrariesFolder, folder); // A library is considered "legacy" if it doesn't contains // a file called "library.properties" File check = new File(folder, "library.properties"); if (!check.exists() || !check.isFile()) { - // Create a legacy library and exit LegacyUserLibrary lib = LegacyUserLibrary.create(folder); lib.setReadOnly(readOnly); @@ -148,12 +145,20 @@ public class LibrariesIndexer { // Check if we can find the same library in the index // and mark it as installed - String libName = folder.getName(); // XXX: lib.getName()? - ContributedLibrary foundLib = index.find(libName, lib.getVersion()); + ContributedLibrary foundLib = index.find(lib.getName(), lib.getVersion()); if (foundLib != null) { foundLib.setInstalled(true); foundLib.setInstalledFolder(folder); foundLib.setReadOnly(readOnly); + lib.setTypes(foundLib.getTypes()); + } + + if (lib.isReadOnly() && lib.getTypes() == null && !lib.getDeclaredTypes().isEmpty()) { + lib.setTypes(lib.getDeclaredTypes()); + } + + if (lib.getTypes() == null) { + lib.setTypes(Arrays.asList("Contributed")); } } diff --git a/arduino-core/src/processing/app/packages/UserLibrary.java b/arduino-core/src/processing/app/packages/UserLibrary.java index b50b5cccf..53df74596 100644 --- a/arduino-core/src/processing/app/packages/UserLibrary.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -28,17 +28,18 @@ */ package processing.app.packages; +import cc.arduino.contributions.libraries.ContributedLibrary; +import cc.arduino.contributions.libraries.ContributedLibraryReference; +import processing.app.helpers.FileUtils; +import processing.app.helpers.PreferencesMap; + import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedList; import java.util.List; -import processing.app.helpers.FileUtils; -import processing.app.helpers.PreferencesMap; -import cc.arduino.contributions.libraries.ContributedLibrary; -import cc.arduino.contributions.libraries.ContributedLibraryReference; - public class UserLibrary extends ContributedLibrary { private String name; @@ -51,15 +52,17 @@ public class UserLibrary extends ContributedLibrary { private String category; private String license; private List architectures; + private List types; + private List declaredTypes; private static final List MANDATORY_PROPERTIES = Arrays - .asList(new String[] { "name", "version", "author", "maintainer", - "sentence", "paragraph", "url" }); + .asList(new String[]{"name", "version", "author", "maintainer", + "sentence", "paragraph", "url"}); - private static final List CATEGORIES = Arrays.asList(new String[] { - "Display", "Communication", "Signal Input/Output", "Sensors", - "Device Control", "Timing", "Data Storage", "Data Processing", "Other", - "Uncategorized" }); + private static final List CATEGORIES = Arrays.asList(new String[]{ + "Display", "Communication", "Signal Input/Output", "Sensors", + "Device Control", "Timing", "Data Storage", "Data Processing", "Other", + "Uncategorized"}); public static UserLibrary create(File libFolder) throws IOException { // Parse metadata @@ -72,16 +75,16 @@ public class UserLibrary extends ContributedLibrary { // Compatibility with 1.5 rev.1 libraries: // "email" field changed to "maintainer" - if (!properties.containsKey("maintainer") && - properties.containsKey("email")) + if (!properties.containsKey("maintainer") && properties.containsKey("email")) { properties.put("maintainer", properties.get("email")); + } // Compatibility with 1.5 rev.1 libraries: // "arch" folder no longer supported File archFolder = new File(libFolder, "arch"); if (archFolder.isDirectory()) throw new IOException("'arch' folder is no longer supported! See " - + "http://goo.gl/gfFJzU for more information"); + + "http://goo.gl/gfFJzU for more information"); // Check mandatory properties for (String p : MANDATORY_PROPERTIES) @@ -99,7 +102,7 @@ public class UserLibrary extends ContributedLibrary { File utilFolder = new File(libFolder, "utility"); if (utilFolder.exists() && utilFolder.isDirectory()) { throw new IOException( - "Library can't use both 'src' and 'utility' folders."); + "Library can't use both 'src' and 'utility' folders."); } } else { // Layout with source code on library's root and "utility" folders @@ -110,8 +113,7 @@ public class UserLibrary extends ContributedLibrary { for (File file : libFolder.listFiles()) { if (file.isDirectory()) { if (FileUtils.isSCCSOrHiddenFile(file)) { - System.out.println("WARNING: Spurious " + file.getName() + - " folder in '" + properties.get("name") + "' library"); + System.out.println("WARNING: Spurious " + file.getName() + " folder in '" + properties.get("name") + "' library"); continue; } } @@ -131,12 +133,22 @@ public class UserLibrary extends ContributedLibrary { if (!CATEGORIES.contains(category)) { category = "Uncategorized"; System.out.println("WARNING: Category '" + category + "' in library " + - properties.get("name") + " is not valid. Setting to 'Uncategorized'"); + properties.get("name") + " is not valid. Setting to 'Uncategorized'"); } String license = properties.get("license"); - if (license == null) + if (license == null) { license = "Unspecified"; + } + + String types = properties.get("types"); + if (types == null) { + types = "Contributed"; + } + List typesList = new LinkedList(); + for (String type : types.split(",")) { + typesList.add(type.trim()); + } UserLibrary res = new UserLibrary(); res.setInstalledFolder(libFolder); @@ -152,6 +164,7 @@ public class UserLibrary extends ContributedLibrary { res.license = license.trim(); res.architectures = archs; res.layout = layout; + res.declaredTypes = typesList; return res; } @@ -192,7 +205,11 @@ public class UserLibrary extends ContributedLibrary { @Override public List getTypes() { - return Arrays.asList("Contributed"); + return types; + } + + public void setTypes(List types) { + this.types = types; } @Override @@ -244,20 +261,24 @@ public class UserLibrary extends ContributedLibrary { return null; } + public List getDeclaredTypes() { + return declaredTypes; + } + protected enum LibraryLayout { FLAT, RECURSIVE - }; + } protected LibraryLayout layout; public File getSrcFolder() { switch (layout) { - case FLAT: - return getInstalledFolder(); - case RECURSIVE: - return new File(getInstalledFolder(), "src"); - default: - return null; // Keep compiler happy :-( + case FLAT: + return getInstalledFolder(); + case RECURSIVE: + return new File(getInstalledFolder(), "src"); + default: + return null; // Keep compiler happy :-( } } diff --git a/hardware/arduino/avr/libraries/EEPROM/library.properties b/hardware/arduino/avr/libraries/EEPROM/library.properties index 955a0ae42..765aa41a2 100644 --- a/hardware/arduino/avr/libraries/EEPROM/library.properties +++ b/hardware/arduino/avr/libraries/EEPROM/library.properties @@ -6,3 +6,5 @@ sentence=Enables reading and writing to the permanent board storage. For all Ard paragraph= url=http://arduino.cc/en/Reference/EEPROM architectures=avr +types=Arduino + diff --git a/hardware/arduino/avr/libraries/SPI/library.properties b/hardware/arduino/avr/libraries/SPI/library.properties index 6f1ae2016..07af86961 100644 --- a/hardware/arduino/avr/libraries/SPI/library.properties +++ b/hardware/arduino/avr/libraries/SPI/library.properties @@ -6,3 +6,5 @@ sentence=Enables the communication with devices that use the Serial Peripheral I paragraph= url=http://arduino.cc/en/Reference/SPI architectures=avr +types=Arduino + diff --git a/hardware/arduino/avr/libraries/SoftwareSerial/library.properties b/hardware/arduino/avr/libraries/SoftwareSerial/library.properties index a69b54df0..8b433d94a 100644 --- a/hardware/arduino/avr/libraries/SoftwareSerial/library.properties +++ b/hardware/arduino/avr/libraries/SoftwareSerial/library.properties @@ -6,3 +6,5 @@ sentence=Enables serial communication on digital pins. For all Arduino boards, B paragraph= url=http://arduino.cc/en/Reference/SoftwareSerial architectures=avr +types=Arduino + diff --git a/hardware/arduino/avr/libraries/Wire/library.properties b/hardware/arduino/avr/libraries/Wire/library.properties index 3246a7509..32c074525 100644 --- a/hardware/arduino/avr/libraries/Wire/library.properties +++ b/hardware/arduino/avr/libraries/Wire/library.properties @@ -6,3 +6,5 @@ sentence=Allows the communication between devices or sensors connected via Two W paragraph= url=http://arduino.cc/en/Reference/Wire architectures=avr +types=Arduino + diff --git a/hardware/arduino/sam/libraries/SPI/library.properties b/hardware/arduino/sam/libraries/SPI/library.properties index 830fdd8e6..d3d378872 100644 --- a/hardware/arduino/sam/libraries/SPI/library.properties +++ b/hardware/arduino/sam/libraries/SPI/library.properties @@ -6,3 +6,5 @@ sentence=Enables the communication with devices that use the Serial Peripheral I paragraph= url=http://arduino.cc/en/Reference/SPI architectures=sam +types=Arduino + diff --git a/hardware/arduino/sam/libraries/Wire/library.properties b/hardware/arduino/sam/libraries/Wire/library.properties index 0a5281fb8..aabdececc 100644 --- a/hardware/arduino/sam/libraries/Wire/library.properties +++ b/hardware/arduino/sam/libraries/Wire/library.properties @@ -6,3 +6,5 @@ sentence=Allows the communication between devices or sensors connected via Two W paragraph= url=http://arduino.cc/en/Reference/Wire architectures=sam +types=Arduino +