mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-01 12:24:14 +01:00
Merge branch 'fix-atk-update-deadlock'
This commit is contained in:
commit
00ba7aa68c
@ -1,403 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Arduino.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
|
||||||
*
|
|
||||||
* Arduino is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* As a special exception, you may use this file as part of a free software
|
|
||||||
* library without restriction. Specifically, if other files instantiate
|
|
||||||
* templates or use macros or inline functions from this file, or you compile
|
|
||||||
* this file and link it with other files to produce an executable, this
|
|
||||||
* file does not by itself cause the resulting executable to be covered by
|
|
||||||
* the GNU General Public License. This exception does not however
|
|
||||||
* invalidate any other reasons why the executable file might be covered by
|
|
||||||
* the GNU General Public License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cc.arduino.contributions.libraries.ui;
|
|
||||||
|
|
||||||
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
|
||||||
import cc.arduino.contributions.VersionComparator;
|
|
||||||
import cc.arduino.contributions.filters.BuiltInPredicate;
|
|
||||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
|
||||||
import cc.arduino.contributions.libraries.ContributedLibrary;
|
|
||||||
import cc.arduino.contributions.libraries.filters.OnlyUpstreamReleasePredicate;
|
|
||||||
import cc.arduino.contributions.ui.InstallerTableCell;
|
|
||||||
import cc.arduino.contributions.ui.listeners.DelegatingKeyListener;
|
|
||||||
import cc.arduino.utils.ReverseComparator;
|
|
||||||
import processing.app.Base;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
import javax.swing.event.HyperlinkEvent;
|
|
||||||
import javax.swing.text.Document;
|
|
||||||
import javax.swing.text.html.HTMLDocument;
|
|
||||||
import javax.swing.text.html.StyleSheet;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static processing.app.I18n.format;
|
|
||||||
import static processing.app.I18n.tr;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class ContributedLibraryTableCell extends InstallerTableCell {
|
|
||||||
|
|
||||||
private final JPanel panel;
|
|
||||||
private final JButton installButton;
|
|
||||||
private final Component installButtonPlaceholder;
|
|
||||||
private JComboBox downgradeChooser;
|
|
||||||
private final JComboBox versionToInstallChooser;
|
|
||||||
private final JButton downgradeButton;
|
|
||||||
private final JPanel buttonsPanel;
|
|
||||||
private final JPanel inactiveButtonsPanel;
|
|
||||||
private final JLabel statusLabel;
|
|
||||||
|
|
||||||
public ContributedLibraryTableCell() {
|
|
||||||
{
|
|
||||||
installButton = new JButton(tr("Install"));
|
|
||||||
installButton.addActionListener(e -> onInstall(editorValue.getSelected(), editorValue.getInstalled()));
|
|
||||||
int width = installButton.getPreferredSize().width;
|
|
||||||
installButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
downgradeButton = new JButton(tr("Install"));
|
|
||||||
downgradeButton.addActionListener(e -> {
|
|
||||||
ContributedLibrary selected = (ContributedLibrary) downgradeChooser.getSelectedItem();
|
|
||||||
onInstall(selected, editorValue.getInstalled());
|
|
||||||
});
|
|
||||||
|
|
||||||
downgradeChooser = new JComboBox();
|
|
||||||
downgradeChooser.addItem("-");
|
|
||||||
downgradeChooser.setMaximumSize(downgradeChooser.getPreferredSize());
|
|
||||||
downgradeChooser.addItemListener(e -> {
|
|
||||||
Object selectVersionItem = downgradeChooser.getItemAt(0);
|
|
||||||
boolean disableDowngrade = (e.getItem() == selectVersionItem);
|
|
||||||
downgradeButton.setEnabled(!disableDowngrade);
|
|
||||||
});
|
|
||||||
|
|
||||||
versionToInstallChooser = new JComboBox();
|
|
||||||
versionToInstallChooser.addItem("-");
|
|
||||||
versionToInstallChooser.setMaximumSize(versionToInstallChooser.getPreferredSize());
|
|
||||||
versionToInstallChooser.addItemListener(e -> editorValue.select((ContributedLibrary) versionToInstallChooser.getSelectedItem()));
|
|
||||||
|
|
||||||
panel = new JPanel();
|
|
||||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
|
||||||
|
|
||||||
makeNewDescription(panel);
|
|
||||||
|
|
||||||
{
|
|
||||||
buttonsPanel = new JPanel();
|
|
||||||
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
|
|
||||||
buttonsPanel.setOpaque(false);
|
|
||||||
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(7));
|
|
||||||
buttonsPanel.add(downgradeChooser);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(downgradeButton);
|
|
||||||
|
|
||||||
buttonsPanel.add(Box.createHorizontalGlue());
|
|
||||||
|
|
||||||
buttonsPanel.add(versionToInstallChooser);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(installButton);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(15));
|
|
||||||
|
|
||||||
panel.add(buttonsPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
inactiveButtonsPanel = new JPanel();
|
|
||||||
inactiveButtonsPanel.setLayout(new BoxLayout(inactiveButtonsPanel, BoxLayout.X_AXIS));
|
|
||||||
inactiveButtonsPanel.setOpaque(false);
|
|
||||||
|
|
||||||
int height = installButton.getMinimumSize().height;
|
|
||||||
inactiveButtonsPanel.add(Box.createVerticalStrut(height));
|
|
||||||
inactiveButtonsPanel.add(Box.createGlue());
|
|
||||||
|
|
||||||
statusLabel = new JLabel(" ");
|
|
||||||
inactiveButtonsPanel.add(statusLabel);
|
|
||||||
inactiveButtonsPanel.add(Box.createHorizontalStrut(15));
|
|
||||||
|
|
||||||
panel.add(inactiveButtonsPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.add(Box.createVerticalStrut(15));
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTextPane makeNewDescription(JPanel panel) {
|
|
||||||
if (panel.getComponentCount() > 0) {
|
|
||||||
panel.remove(0);
|
|
||||||
}
|
|
||||||
JTextPane description = new JTextPane();
|
|
||||||
description.setInheritsPopupMenu(true);
|
|
||||||
Insets margin = description.getMargin();
|
|
||||||
margin.bottom = 0;
|
|
||||||
description.setMargin(margin);
|
|
||||||
description.setContentType("text/html");
|
|
||||||
Document doc = description.getDocument();
|
|
||||||
if (doc instanceof HTMLDocument) {
|
|
||||||
HTMLDocument html = (HTMLDocument) doc;
|
|
||||||
StyleSheet stylesheet = html.getStyleSheet();
|
|
||||||
stylesheet.addRule("body { margin: 0; padding: 0;"
|
|
||||||
+ "font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"
|
|
||||||
+ "font-size: 100%;" + "font-size: 0.95em; }");
|
|
||||||
}
|
|
||||||
description.setOpaque(false);
|
|
||||||
description.setBorder(new EmptyBorder(4, 7, 7, 7));
|
|
||||||
description.setHighlighter(null);
|
|
||||||
description.setEditable(false);
|
|
||||||
description.addHyperlinkListener(e -> {
|
|
||||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
|
||||||
Base.openURL(e.getDescription());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
description.addKeyListener(new DelegatingKeyListener(parentTable));
|
|
||||||
panel.add(description, 0);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onRemove(ContributedLibrary selected) {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onInstall(ContributedLibrary selected, ContributedLibrary installed) {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
|
||||||
boolean isSelected,
|
|
||||||
boolean hasFocus, int row,
|
|
||||||
int column) {
|
|
||||||
parentTable = table;
|
|
||||||
setEnabled(false);
|
|
||||||
Component component = getUpdatedCellComponent(value, isSelected, row, false);
|
|
||||||
if (row % 2 == 0) {
|
|
||||||
component.setBackground(new Color(236, 241, 241)); //#ecf1f1
|
|
||||||
} else {
|
|
||||||
component.setBackground(new Color(255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
int height = new Double(component.getPreferredSize().getHeight()).intValue();
|
|
||||||
if (table.getRowHeight(row) < height) {
|
|
||||||
table.setRowHeight(row, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContributedLibraryReleases editorValue;
|
|
||||||
private JTable parentTable;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getCellEditorValue() {
|
|
||||||
return editorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getTableCellEditorComponent(JTable table, Object value,
|
|
||||||
boolean isSelected, int row,
|
|
||||||
int column) {
|
|
||||||
parentTable = table;
|
|
||||||
editorValue = (ContributedLibraryReleases) value;
|
|
||||||
setEnabled(true);
|
|
||||||
|
|
||||||
final ContributedLibrary installed = editorValue.getInstalled();
|
|
||||||
|
|
||||||
List<ContributedLibrary> releases = editorValue.getReleases().stream().filter(new OnlyUpstreamReleasePredicate()).collect(Collectors.toList());
|
|
||||||
List<ContributedLibrary> uninstalledReleases = releases.stream().filter(new InstalledPredicate().negate()).collect(Collectors.toList());
|
|
||||||
|
|
||||||
List<ContributedLibrary> installedBuiltIn = releases.stream().filter(new InstalledPredicate()).filter(new BuiltInPredicate()).collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (installed != null && !installedBuiltIn.contains(installed)) {
|
|
||||||
uninstalledReleases.addAll(installedBuiltIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(uninstalledReleases, new ReverseComparator<>(new DownloadableContributionVersionComparator()));
|
|
||||||
|
|
||||||
downgradeChooser.removeAllItems();
|
|
||||||
downgradeChooser.addItem(tr("Select version"));
|
|
||||||
|
|
||||||
final List<ContributedLibrary> uninstalledPreviousReleases = new LinkedList<>();
|
|
||||||
final List<ContributedLibrary> uninstalledNewerReleases = new LinkedList<>();
|
|
||||||
|
|
||||||
final VersionComparator versionComparator = new VersionComparator();
|
|
||||||
uninstalledReleases.stream().forEach(input -> {
|
|
||||||
if (installed == null || versionComparator.greaterThan(installed.getParsedVersion(), input.getParsedVersion())) {
|
|
||||||
uninstalledPreviousReleases.add(input);
|
|
||||||
} else {
|
|
||||||
uninstalledNewerReleases.add(input);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
uninstalledNewerReleases.forEach(downgradeChooser::addItem);
|
|
||||||
uninstalledPreviousReleases.forEach(downgradeChooser::addItem);
|
|
||||||
|
|
||||||
downgradeChooser.setVisible(installed != null && (!uninstalledPreviousReleases.isEmpty() || uninstalledNewerReleases.size() > 1));
|
|
||||||
downgradeButton.setVisible(installed != null && (!uninstalledPreviousReleases.isEmpty() || uninstalledNewerReleases.size() > 1));
|
|
||||||
|
|
||||||
versionToInstallChooser.removeAllItems();
|
|
||||||
uninstalledReleases.forEach(versionToInstallChooser::addItem);
|
|
||||||
versionToInstallChooser.setVisible(installed == null && uninstalledReleases.size() > 1);
|
|
||||||
|
|
||||||
Component component = getUpdatedCellComponent(value, true, row, !installedBuiltIn.isEmpty());
|
|
||||||
component.setBackground(new Color(218, 227, 227)); //#dae3e3
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getUpdatedCellComponent(Object value, boolean isSelected, int row, boolean hasBuiltInRelease) {
|
|
||||||
ContributedLibraryReleases releases = (ContributedLibraryReleases) value;
|
|
||||||
|
|
||||||
JTextPane description = makeNewDescription(panel);
|
|
||||||
|
|
||||||
//FIXME: happens on macosx, don't know why
|
|
||||||
if (releases == null) {
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContributedLibrary selected = releases.getSelected();
|
|
||||||
ContributedLibrary installed = releases.getInstalled();
|
|
||||||
|
|
||||||
boolean installable, upgradable;
|
|
||||||
if (installed == null) {
|
|
||||||
installable = true;
|
|
||||||
upgradable = false;
|
|
||||||
} else {
|
|
||||||
installable = false;
|
|
||||||
upgradable = new DownloadableContributionVersionComparator().compare(selected, installed) > 0;
|
|
||||||
}
|
|
||||||
if (installable) {
|
|
||||||
installButton.setText(tr("Install"));
|
|
||||||
}
|
|
||||||
if (upgradable) {
|
|
||||||
installButton.setText(tr("Update"));
|
|
||||||
}
|
|
||||||
installButton.setVisible(installable || upgradable);
|
|
||||||
installButtonPlaceholder.setVisible(!(installable || upgradable));
|
|
||||||
|
|
||||||
String name = selected.getName();
|
|
||||||
String author = selected.getAuthor();
|
|
||||||
// String maintainer = selectedLib.getMaintainer();
|
|
||||||
String website = selected.getWebsite();
|
|
||||||
String sentence = selected.getSentence();
|
|
||||||
String paragraph = selected.getParagraph();
|
|
||||||
// String availableVer = selectedLib.getVersion();
|
|
||||||
// String url = selected.getUrl();
|
|
||||||
|
|
||||||
String midcolor = isSelected ? "#000000" : "#888888";
|
|
||||||
|
|
||||||
String desc = "<html><body>";
|
|
||||||
|
|
||||||
// Library name...
|
|
||||||
desc += format("<b>{0}</b>", name);
|
|
||||||
if (installed != null && installed.isReadOnly()) {
|
|
||||||
desc += " Built-In ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...author...
|
|
||||||
desc += format("<font color=\"{0}\">", midcolor);
|
|
||||||
if (author != null && !author.isEmpty()) {
|
|
||||||
desc += format(" by <b>{0}</b>", author);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...version.
|
|
||||||
if (installed != null) {
|
|
||||||
String installedVer = installed.getParsedVersion();
|
|
||||||
if (installedVer == null) {
|
|
||||||
desc += " " + tr("Version unknown");
|
|
||||||
} else {
|
|
||||||
desc += " " + format(tr("Version <b>{0}</b>"), installedVer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc += "</font>";
|
|
||||||
|
|
||||||
if (installed != null) {
|
|
||||||
desc += " <strong><font color=\"#00979D\">INSTALLED</font></strong>";
|
|
||||||
}
|
|
||||||
|
|
||||||
desc += "<br/>";
|
|
||||||
|
|
||||||
// Description
|
|
||||||
if (sentence != null) {
|
|
||||||
desc += format("<b>{0}</b> ", sentence);
|
|
||||||
if (paragraph != null && !paragraph.isEmpty())
|
|
||||||
desc += format("{0}", paragraph);
|
|
||||||
desc += "<br />";
|
|
||||||
}
|
|
||||||
if (author != null && !author.isEmpty()) {
|
|
||||||
desc += format("<a href=\"{0}\">More info</a>", website);
|
|
||||||
}
|
|
||||||
|
|
||||||
desc += "</body></html>";
|
|
||||||
description.setText(desc);
|
|
||||||
description.setBackground(Color.WHITE);
|
|
||||||
|
|
||||||
// for modelToView to work, the text area has to be sized. It doesn't
|
|
||||||
// matter if it's visible or not.
|
|
||||||
|
|
||||||
// See:
|
|
||||||
// http://stackoverflow.com/questions/3081210/how-to-set-jtextarea-to-have-height-that-matches-the-size-of-a-text-it-contains
|
|
||||||
int width = parentTable.getBounds().width;
|
|
||||||
setJTextPaneDimensionToFitContainedText(description, width);
|
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
panel.setBackground(parentTable.getSelectionBackground());
|
|
||||||
panel.setForeground(parentTable.getSelectionForeground());
|
|
||||||
} else {
|
|
||||||
panel.setBackground(parentTable.getBackground());
|
|
||||||
panel.setForeground(parentTable.getForeground());
|
|
||||||
}
|
|
||||||
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Timer enabler = new Timer(100, new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
enable(true);
|
|
||||||
enabler.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
enable(false);
|
|
||||||
if (enabled) {
|
|
||||||
enabler.start();
|
|
||||||
} else {
|
|
||||||
enabler.stop();
|
|
||||||
}
|
|
||||||
buttonsPanel.setVisible(enabled);
|
|
||||||
inactiveButtonsPanel.setVisible(!enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enable(boolean enabled) {
|
|
||||||
installButton.setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(String status) {
|
|
||||||
statusLabel.setText(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
panel.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.libraries.ui;
|
||||||
|
|
||||||
|
import static processing.app.I18n.tr;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
||||||
|
import cc.arduino.contributions.VersionComparator;
|
||||||
|
import cc.arduino.contributions.filters.BuiltInPredicate;
|
||||||
|
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||||
|
import cc.arduino.contributions.libraries.ContributedLibrary;
|
||||||
|
import cc.arduino.contributions.libraries.filters.OnlyUpstreamReleasePredicate;
|
||||||
|
import cc.arduino.contributions.ui.InstallerTableCell;
|
||||||
|
import cc.arduino.utils.ReverseComparator;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ContributedLibraryTableCellEditor extends InstallerTableCell {
|
||||||
|
|
||||||
|
private ContributedLibraryReleases editorValue;
|
||||||
|
private ContributedLibraryTableCellJPanel editorCell;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCellEditorValue() {
|
||||||
|
return editorValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTableCellEditorComponent(JTable table, Object value,
|
||||||
|
boolean isSelected, int row,
|
||||||
|
int column) {
|
||||||
|
editorValue = (ContributedLibraryReleases) value;
|
||||||
|
|
||||||
|
editorCell = new ContributedLibraryTableCellJPanel(table, value, true);
|
||||||
|
editorCell.installButton
|
||||||
|
.addActionListener(e -> onInstall(editorValue.getSelected(),
|
||||||
|
editorValue.getInstalled()));
|
||||||
|
editorCell.downgradeButton.addActionListener(e -> {
|
||||||
|
JComboBox chooser = editorCell.downgradeChooser;
|
||||||
|
ContributedLibrary lib = (ContributedLibrary) chooser.getSelectedItem();
|
||||||
|
onInstall(lib, editorValue.getInstalled());
|
||||||
|
});
|
||||||
|
editorCell.versionToInstallChooser.addItemListener(e -> editorValue
|
||||||
|
.select((ContributedLibrary) editorCell.versionToInstallChooser
|
||||||
|
.getSelectedItem()));
|
||||||
|
|
||||||
|
setEnabled(true);
|
||||||
|
|
||||||
|
final ContributedLibrary installed = editorValue.getInstalled();
|
||||||
|
|
||||||
|
List<ContributedLibrary> releases = editorValue.getReleases().stream()
|
||||||
|
.filter(new OnlyUpstreamReleasePredicate())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<ContributedLibrary> uninstalledReleases = releases.stream()
|
||||||
|
.filter(new InstalledPredicate().negate()).collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<ContributedLibrary> installedBuiltIn = releases.stream()
|
||||||
|
.filter(new InstalledPredicate()).filter(new BuiltInPredicate())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (installed != null && !installedBuiltIn.contains(installed)) {
|
||||||
|
uninstalledReleases.addAll(installedBuiltIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(uninstalledReleases, new ReverseComparator<>(
|
||||||
|
new DownloadableContributionVersionComparator()));
|
||||||
|
|
||||||
|
editorCell.downgradeChooser.removeAllItems();
|
||||||
|
editorCell.downgradeChooser.addItem(tr("Select version"));
|
||||||
|
|
||||||
|
final List<ContributedLibrary> uninstalledPreviousReleases = new LinkedList<>();
|
||||||
|
final List<ContributedLibrary> uninstalledNewerReleases = new LinkedList<>();
|
||||||
|
|
||||||
|
final VersionComparator versionComparator = new VersionComparator();
|
||||||
|
uninstalledReleases.stream().forEach(input -> {
|
||||||
|
if (installed == null
|
||||||
|
|| versionComparator.greaterThan(installed.getParsedVersion(),
|
||||||
|
input.getParsedVersion())) {
|
||||||
|
uninstalledPreviousReleases.add(input);
|
||||||
|
} else {
|
||||||
|
uninstalledNewerReleases.add(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
uninstalledNewerReleases.forEach(editorCell.downgradeChooser::addItem);
|
||||||
|
uninstalledPreviousReleases.forEach(editorCell.downgradeChooser::addItem);
|
||||||
|
|
||||||
|
editorCell.downgradeChooser
|
||||||
|
.setVisible(installed != null
|
||||||
|
&& (!uninstalledPreviousReleases.isEmpty()
|
||||||
|
|| uninstalledNewerReleases.size() > 1));
|
||||||
|
editorCell.downgradeButton
|
||||||
|
.setVisible(installed != null
|
||||||
|
&& (!uninstalledPreviousReleases.isEmpty()
|
||||||
|
|| uninstalledNewerReleases.size() > 1));
|
||||||
|
|
||||||
|
editorCell.versionToInstallChooser.removeAllItems();
|
||||||
|
uninstalledReleases.forEach(editorCell.versionToInstallChooser::addItem);
|
||||||
|
editorCell.versionToInstallChooser
|
||||||
|
.setVisible(installed == null && uninstalledReleases.size() > 1);
|
||||||
|
|
||||||
|
editorCell.setBackground(new Color(218, 227, 227)); // #dae3e3
|
||||||
|
return editorCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
editorCell.setButtonsVisible(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
editorCell.statusLabel.setText(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRemove(ContributedLibrary selected) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onInstall(ContributedLibrary selected,
|
||||||
|
ContributedLibrary installed) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,244 @@
|
|||||||
|
package cc.arduino.contributions.libraries.ui;
|
||||||
|
|
||||||
|
import static processing.app.I18n.format;
|
||||||
|
import static processing.app.I18n.tr;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Insets;
|
||||||
|
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.event.HyperlinkEvent;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.html.HTMLDocument;
|
||||||
|
import javax.swing.text.html.StyleSheet;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
||||||
|
import cc.arduino.contributions.libraries.ContributedLibrary;
|
||||||
|
import cc.arduino.contributions.ui.InstallerTableCell;
|
||||||
|
import processing.app.Base;
|
||||||
|
|
||||||
|
public class ContributedLibraryTableCellJPanel extends JPanel {
|
||||||
|
|
||||||
|
final JButton installButton;
|
||||||
|
final Component installButtonPlaceholder;
|
||||||
|
final JComboBox downgradeChooser;
|
||||||
|
final JComboBox versionToInstallChooser;
|
||||||
|
final JButton downgradeButton;
|
||||||
|
final JPanel buttonsPanel;
|
||||||
|
final JPanel inactiveButtonsPanel;
|
||||||
|
final JLabel statusLabel;
|
||||||
|
|
||||||
|
public ContributedLibraryTableCellJPanel(JTable parentTable, Object value,
|
||||||
|
boolean isSelected) {
|
||||||
|
super();
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
installButton = new JButton(tr("Install"));
|
||||||
|
int width = installButton.getPreferredSize().width;
|
||||||
|
installButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
||||||
|
|
||||||
|
downgradeButton = new JButton(tr("Install"));
|
||||||
|
|
||||||
|
downgradeChooser = new JComboBox();
|
||||||
|
downgradeChooser.addItem("-");
|
||||||
|
downgradeChooser.setMaximumSize(downgradeChooser.getPreferredSize());
|
||||||
|
downgradeChooser.addItemListener(e -> {
|
||||||
|
Object selectVersionItem = downgradeChooser.getItemAt(0);
|
||||||
|
boolean disableDowngrade = (e.getItem() == selectVersionItem);
|
||||||
|
downgradeButton.setEnabled(!disableDowngrade);
|
||||||
|
});
|
||||||
|
|
||||||
|
versionToInstallChooser = new JComboBox();
|
||||||
|
versionToInstallChooser.addItem("-");
|
||||||
|
versionToInstallChooser
|
||||||
|
.setMaximumSize(versionToInstallChooser.getPreferredSize());
|
||||||
|
|
||||||
|
makeNewDescription();
|
||||||
|
|
||||||
|
buttonsPanel = new JPanel();
|
||||||
|
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
|
||||||
|
buttonsPanel.setOpaque(false);
|
||||||
|
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(7));
|
||||||
|
buttonsPanel.add(downgradeChooser);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(downgradeButton);
|
||||||
|
|
||||||
|
buttonsPanel.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
buttonsPanel.add(versionToInstallChooser);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(installButton);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(15));
|
||||||
|
|
||||||
|
add(buttonsPanel);
|
||||||
|
|
||||||
|
inactiveButtonsPanel = new JPanel();
|
||||||
|
inactiveButtonsPanel
|
||||||
|
.setLayout(new BoxLayout(inactiveButtonsPanel, BoxLayout.X_AXIS));
|
||||||
|
inactiveButtonsPanel.setOpaque(false);
|
||||||
|
|
||||||
|
int height = installButton.getMinimumSize().height;
|
||||||
|
inactiveButtonsPanel.add(Box.createVerticalStrut(height));
|
||||||
|
inactiveButtonsPanel.add(Box.createGlue());
|
||||||
|
|
||||||
|
statusLabel = new JLabel(" ");
|
||||||
|
inactiveButtonsPanel.add(statusLabel);
|
||||||
|
inactiveButtonsPanel.add(Box.createHorizontalStrut(15));
|
||||||
|
|
||||||
|
add(inactiveButtonsPanel);
|
||||||
|
|
||||||
|
add(Box.createVerticalStrut(15));
|
||||||
|
|
||||||
|
ContributedLibraryReleases releases = (ContributedLibraryReleases) value;
|
||||||
|
JTextPane description = makeNewDescription();
|
||||||
|
|
||||||
|
// FIXME: happens on macosx, don't know why
|
||||||
|
if (releases == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ContributedLibrary selected = releases.getSelected();
|
||||||
|
ContributedLibrary installed = releases.getInstalled();
|
||||||
|
|
||||||
|
boolean installable, upgradable;
|
||||||
|
if (installed == null) {
|
||||||
|
installable = true;
|
||||||
|
upgradable = false;
|
||||||
|
} else {
|
||||||
|
installable = false;
|
||||||
|
upgradable = new DownloadableContributionVersionComparator()
|
||||||
|
.compare(selected, installed) > 0;
|
||||||
|
}
|
||||||
|
if (installable) {
|
||||||
|
installButton.setText(tr("Install"));
|
||||||
|
}
|
||||||
|
if (upgradable) {
|
||||||
|
installButton.setText(tr("Update"));
|
||||||
|
}
|
||||||
|
installButton.setVisible(installable || upgradable);
|
||||||
|
installButtonPlaceholder.setVisible(!(installable || upgradable));
|
||||||
|
|
||||||
|
String name = selected.getName();
|
||||||
|
String author = selected.getAuthor();
|
||||||
|
// String maintainer = selectedLib.getMaintainer();
|
||||||
|
String website = selected.getWebsite();
|
||||||
|
String sentence = selected.getSentence();
|
||||||
|
String paragraph = selected.getParagraph();
|
||||||
|
// String availableVer = selectedLib.getVersion();
|
||||||
|
// String url = selected.getUrl();
|
||||||
|
|
||||||
|
String midcolor = isSelected ? "#000000" : "#888888";
|
||||||
|
|
||||||
|
String desc = "<html><body>";
|
||||||
|
|
||||||
|
// Library name...
|
||||||
|
desc += format("<b>{0}</b>", name);
|
||||||
|
if (installed != null && installed.isReadOnly()) {
|
||||||
|
desc += " Built-In ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...author...
|
||||||
|
desc += format("<font color=\"{0}\">", midcolor);
|
||||||
|
if (author != null && !author.isEmpty()) {
|
||||||
|
desc += format(" by <b>{0}</b>", author);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...version.
|
||||||
|
if (installed != null) {
|
||||||
|
String installedVer = installed.getParsedVersion();
|
||||||
|
if (installedVer == null) {
|
||||||
|
desc += " " + tr("Version unknown");
|
||||||
|
} else {
|
||||||
|
desc += " " + format(tr("Version <b>{0}</b>"), installedVer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desc += "</font>";
|
||||||
|
|
||||||
|
if (installed != null) {
|
||||||
|
desc += " <strong><font color=\"#00979D\">INSTALLED</font></strong>";
|
||||||
|
}
|
||||||
|
|
||||||
|
desc += "<br/>";
|
||||||
|
|
||||||
|
// Description
|
||||||
|
if (sentence != null) {
|
||||||
|
desc += format("<b>{0}</b> ", sentence);
|
||||||
|
if (paragraph != null && !paragraph.isEmpty())
|
||||||
|
desc += format("{0}", paragraph);
|
||||||
|
desc += "<br />";
|
||||||
|
}
|
||||||
|
if (author != null && !author.isEmpty()) {
|
||||||
|
desc += format("<a href=\"{0}\">More info</a>", website);
|
||||||
|
}
|
||||||
|
|
||||||
|
desc += "</body></html>";
|
||||||
|
description.setText(desc);
|
||||||
|
description.setBackground(Color.WHITE);
|
||||||
|
|
||||||
|
// for modelToView to work, the text area has to be sized. It doesn't
|
||||||
|
// matter if it's visible or not.
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// http://stackoverflow.com/questions/3081210/how-to-set-jtextarea-to-have-height-that-matches-the-size-of-a-text-it-contains
|
||||||
|
InstallerTableCell
|
||||||
|
.setJTextPaneDimensionToFitContainedText(description,
|
||||||
|
parentTable.getBounds().width);
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
setBackground(parentTable.getSelectionBackground());
|
||||||
|
setForeground(parentTable.getSelectionForeground());
|
||||||
|
} else {
|
||||||
|
setBackground(parentTable.getBackground());
|
||||||
|
setForeground(parentTable.getForeground());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JTextPane makeNewDescription() {
|
||||||
|
if (getComponentCount() > 0) {
|
||||||
|
remove(0);
|
||||||
|
}
|
||||||
|
JTextPane description = new JTextPane();
|
||||||
|
description.setInheritsPopupMenu(true);
|
||||||
|
Insets margin = description.getMargin();
|
||||||
|
margin.bottom = 0;
|
||||||
|
description.setMargin(margin);
|
||||||
|
description.setContentType("text/html");
|
||||||
|
Document doc = description.getDocument();
|
||||||
|
if (doc instanceof HTMLDocument) {
|
||||||
|
HTMLDocument html = (HTMLDocument) doc;
|
||||||
|
StyleSheet stylesheet = html.getStyleSheet();
|
||||||
|
stylesheet.addRule("body { margin: 0; padding: 0;"
|
||||||
|
+ "font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"
|
||||||
|
+ "font-size: 100%;" + "font-size: 0.95em; }");
|
||||||
|
}
|
||||||
|
description.setOpaque(false);
|
||||||
|
description.setBorder(new EmptyBorder(4, 7, 7, 7));
|
||||||
|
description.setHighlighter(null);
|
||||||
|
description.setEditable(false);
|
||||||
|
description.addHyperlinkListener(e -> {
|
||||||
|
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
|
Base.openURL(e.getDescription());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// description.addKeyListener(new DelegatingKeyListener(parentTable));
|
||||||
|
add(description, 0);
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonsVisible(boolean enabled) {
|
||||||
|
installButton.setEnabled(enabled);
|
||||||
|
buttonsPanel.setVisible(enabled);
|
||||||
|
inactiveButtonsPanel.setVisible(!enabled);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.libraries.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ContributedLibraryTableCellRenderer implements TableCellRenderer {
|
||||||
|
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||||
|
boolean isSelected,
|
||||||
|
boolean hasFocus, int row,
|
||||||
|
int column) {
|
||||||
|
ContributedLibraryTableCellJPanel cell = new ContributedLibraryTableCellJPanel(table,
|
||||||
|
value, isSelected);
|
||||||
|
cell.setButtonsVisible(false);
|
||||||
|
|
||||||
|
if (row % 2 == 0) {
|
||||||
|
cell.setBackground(new Color(236, 241, 241)); // #ecf1f1
|
||||||
|
} else {
|
||||||
|
cell.setBackground(new Color(255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
int height = new Double(cell.getPreferredSize().getHeight()).intValue();
|
||||||
|
if (table.getRowHeight(row) < height) {
|
||||||
|
table.setRowHeight(row, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -41,20 +41,20 @@ import java.util.function.Predicate;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class LibrariesIndexTableModel extends FilteredAbstractTableModel<ContributedLibrary> {
|
public class LibrariesIndexTableModel
|
||||||
|
extends FilteredAbstractTableModel<ContributedLibrary> {
|
||||||
public final static int DESCRIPTION_COL = 0;
|
|
||||||
|
|
||||||
private final List<ContributedLibraryReleases> contributions = new ArrayList<>();
|
private final List<ContributedLibraryReleases> contributions = new ArrayList<>();
|
||||||
|
|
||||||
private final String[] columnNames = {"Description"};
|
private final String[] columnNames = { "Description" };
|
||||||
|
|
||||||
private final Class<?>[] columnTypes = {ContributedPlatform.class};
|
private final Class<?>[] columnTypes = { ContributedPlatform.class };
|
||||||
|
|
||||||
Predicate<ContributedLibrary> selectedCategoryFilter = null;
|
Predicate<ContributedLibrary> selectedCategoryFilter = null;
|
||||||
String selectedFilters[] = null;
|
String selectedFilters[] = null;
|
||||||
|
|
||||||
public void updateIndexFilter(String filters[], Stream<Predicate<ContributedLibrary>> additionalFilters) {
|
public void updateIndexFilter(String filters[],
|
||||||
|
Stream<Predicate<ContributedLibrary>> additionalFilters) {
|
||||||
selectedCategoryFilter = additionalFilters.reduce(Predicate::and).get();
|
selectedCategoryFilter = additionalFilters.reduce(Predicate::and).get();
|
||||||
selectedFilters = filters;
|
selectedFilters = filters;
|
||||||
update();
|
update();
|
||||||
@ -67,7 +67,7 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel<Contrib
|
|||||||
* @param string
|
* @param string
|
||||||
* @param filters
|
* @param filters
|
||||||
* @return <b>true<b> if all the strings in <b>set</b> are contained in
|
* @return <b>true<b> if all the strings in <b>set</b> are contained in
|
||||||
* <b>string</b>.
|
* <b>string</b>.
|
||||||
*/
|
*/
|
||||||
private boolean stringContainsAll(String string, String filters[]) {
|
private boolean stringContainsAll(String string, String filters[]) {
|
||||||
if (string == null) {
|
if (string == null) {
|
||||||
@ -120,9 +120,7 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel<Contrib
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object value, int row, int col) {
|
public void setValueAt(Object value, int row, int col) {
|
||||||
if (col == DESCRIPTION_COL) {
|
fireTableCellUpdated(row, col);
|
||||||
fireTableCellUpdated(row, col);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -131,15 +129,12 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel<Contrib
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ContributedLibraryReleases contribution = contributions.get(row);
|
ContributedLibraryReleases contribution = contributions.get(row);
|
||||||
if (col == DESCRIPTION_COL) {
|
return contribution;// .getSelected();
|
||||||
return contribution;// .getSelected();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCellEditable(int row, int col) {
|
public boolean isCellEditable(int row, int col) {
|
||||||
return col == DESCRIPTION_COL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContributedLibraryReleases getReleases(int row) {
|
public ContributedLibraryReleases getReleases(int row) {
|
||||||
@ -160,7 +155,8 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel<Contrib
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String compoundTargetSearchText = lib.getName() + "\n" + lib.getParagraph() + "\n" + lib.getSentence();
|
String compoundTargetSearchText = lib.getName() + "\n" + lib.getParagraph()
|
||||||
|
+ "\n" + lib.getSentence();
|
||||||
if (!stringContainsAll(compoundTargetSearchText, selectedFilters)) {
|
if (!stringContainsAll(compoundTargetSearchText, selectedFilters)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -196,9 +192,12 @@ public class LibrariesIndexTableModel extends FilteredAbstractTableModel<Contrib
|
|||||||
|
|
||||||
private void updateContributions() {
|
private void updateContributions() {
|
||||||
contributions.clear();
|
contributions.clear();
|
||||||
BaseNoGui.librariesIndexer.getIndex().getLibraries().forEach(this::applyFilterToLibrary);
|
BaseNoGui.librariesIndexer.getIndex().getLibraries()
|
||||||
BaseNoGui.librariesIndexer.getInstalledLibraries().forEach(this::applyFilterToLibrary);
|
.forEach(this::applyFilterToLibrary);
|
||||||
Collections.sort(contributions, new ContributedLibraryReleasesComparator("Arduino"));
|
BaseNoGui.librariesIndexer.getInstalledLibraries()
|
||||||
|
.forEach(this::applyFilterToLibrary);
|
||||||
|
Collections.sort(contributions,
|
||||||
|
new ContributedLibraryReleasesComparator("Arduino"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,10 @@
|
|||||||
|
|
||||||
package cc.arduino.contributions.libraries.ui;
|
package cc.arduino.contributions.libraries.ui;
|
||||||
|
|
||||||
import cc.arduino.contributions.DownloadableContribution;
|
import static processing.app.I18n.tr;
|
||||||
import cc.arduino.contributions.libraries.ContributedLibrary;
|
|
||||||
import cc.arduino.contributions.libraries.LibraryInstaller;
|
|
||||||
import cc.arduino.contributions.libraries.LibraryTypeComparator;
|
|
||||||
import cc.arduino.contributions.ui.*;
|
|
||||||
import cc.arduino.utils.Progress;
|
|
||||||
import processing.app.BaseNoGui;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import java.awt.Dialog;
|
||||||
import java.awt.*;
|
import java.awt.Frame;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -46,7 +40,24 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static processing.app.I18n.tr;
|
import javax.swing.Box;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContribution;
|
||||||
|
import cc.arduino.contributions.libraries.ContributedLibrary;
|
||||||
|
import cc.arduino.contributions.libraries.LibraryInstaller;
|
||||||
|
import cc.arduino.contributions.libraries.LibraryTypeComparator;
|
||||||
|
import cc.arduino.contributions.ui.DropdownAllItem;
|
||||||
|
import cc.arduino.contributions.ui.DropdownItem;
|
||||||
|
import cc.arduino.contributions.ui.FilteredAbstractTableModel;
|
||||||
|
import cc.arduino.contributions.ui.InstallerJDialog;
|
||||||
|
import cc.arduino.contributions.ui.InstallerJDialogUncaughtExceptionHandler;
|
||||||
|
import cc.arduino.contributions.ui.InstallerTableCell;
|
||||||
|
import cc.arduino.utils.Progress;
|
||||||
|
import processing.app.BaseNoGui;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class LibraryManagerUI extends InstallerJDialog<ContributedLibrary> {
|
public class LibraryManagerUI extends InstallerJDialog<ContributedLibrary> {
|
||||||
@ -60,18 +71,14 @@ public class LibraryManagerUI extends InstallerJDialog<ContributedLibrary> {
|
|||||||
return new LibrariesIndexTableModel();
|
return new LibrariesIndexTableModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private LibrariesIndexTableModel getContribModel() {
|
|
||||||
return (LibrariesIndexTableModel) contribModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InstallerTableCell createCellRenderer() {
|
protected TableCellRenderer createCellRenderer() {
|
||||||
return new ContributedLibraryTableCell();
|
return new ContributedLibraryTableCellRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InstallerTableCell createCellEditor() {
|
protected InstallerTableCell createCellEditor() {
|
||||||
return new ContributedLibraryTableCell() {
|
return new ContributedLibraryTableCellEditor() {
|
||||||
@Override
|
@Override
|
||||||
protected void onInstall(ContributedLibrary selectedLibrary, ContributedLibrary installedLibrary) {
|
protected void onInstall(ContributedLibrary selectedLibrary, ContributedLibrary installedLibrary) {
|
||||||
if (selectedLibrary.isReadOnly()) {
|
if (selectedLibrary.isReadOnly()) {
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.packages.ui;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
|
||||||
|
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||||
|
import cc.arduino.contributions.packages.ContributedPackage;
|
||||||
|
import cc.arduino.contributions.packages.ContributedPlatform;
|
||||||
|
|
||||||
|
public class ContributedPlatformReleases {
|
||||||
|
|
||||||
|
public final ContributedPackage packager;
|
||||||
|
public final String arch;
|
||||||
|
public final List<ContributedPlatform> releases;
|
||||||
|
public final List<String> versions;
|
||||||
|
public ContributedPlatform selected = null;
|
||||||
|
|
||||||
|
public ContributedPlatformReleases(ContributedPlatform platform) {
|
||||||
|
packager = platform.getParentPackage();
|
||||||
|
arch = platform.getArchitecture();
|
||||||
|
releases = new LinkedList<>();
|
||||||
|
versions = new LinkedList<>();
|
||||||
|
add(platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldContain(ContributedPlatform platform) {
|
||||||
|
if (platform.getParentPackage() != packager)
|
||||||
|
return false;
|
||||||
|
return platform.getArchitecture().equals(arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ContributedPlatform platform) {
|
||||||
|
releases.add(platform);
|
||||||
|
String version = platform.getParsedVersion();
|
||||||
|
if (version != null) {
|
||||||
|
versions.add(version);
|
||||||
|
}
|
||||||
|
selected = getLatest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContributedPlatform getInstalled() {
|
||||||
|
List<ContributedPlatform> installedReleases = releases.stream()
|
||||||
|
.filter(new InstalledPredicate()).collect(Collectors.toList());
|
||||||
|
Collections
|
||||||
|
.sort(installedReleases,
|
||||||
|
new DownloadableContributionBuiltInAtTheBottomComparator());
|
||||||
|
|
||||||
|
if (installedReleases.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return installedReleases.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContributedPlatform getLatest() {
|
||||||
|
return ContributionIndexTableModel.getLatestOf(releases);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContributedPlatform getSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void select(ContributedPlatform value) {
|
||||||
|
for (ContributedPlatform plat : releases) {
|
||||||
|
if (plat == value) {
|
||||||
|
selected = plat;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,407 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Arduino.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
|
||||||
*
|
|
||||||
* Arduino is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* As a special exception, you may use this file as part of a free software
|
|
||||||
* library without restriction. Specifically, if other files instantiate
|
|
||||||
* templates or use macros or inline functions from this file, or you compile
|
|
||||||
* this file and link it with other files to produce an executable, this
|
|
||||||
* file does not by itself cause the resulting executable to be covered by
|
|
||||||
* the GNU General Public License. This exception does not however
|
|
||||||
* invalidate any other reasons why the executable file might be covered by
|
|
||||||
* the GNU General Public License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cc.arduino.contributions.packages.ui;
|
|
||||||
|
|
||||||
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
|
||||||
import cc.arduino.contributions.VersionComparator;
|
|
||||||
import cc.arduino.contributions.filters.BuiltInPredicate;
|
|
||||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
|
||||||
import cc.arduino.contributions.packages.ContributedBoard;
|
|
||||||
import cc.arduino.contributions.packages.ContributedHelp;
|
|
||||||
import cc.arduino.contributions.packages.ContributedPlatform;
|
|
||||||
import cc.arduino.contributions.ui.InstallerTableCell;
|
|
||||||
import cc.arduino.contributions.ui.listeners.DelegatingKeyListener;
|
|
||||||
import cc.arduino.utils.ReverseComparator;
|
|
||||||
import processing.app.Base;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
import javax.swing.event.HyperlinkEvent;
|
|
||||||
import javax.swing.text.Document;
|
|
||||||
import javax.swing.text.html.HTMLDocument;
|
|
||||||
import javax.swing.text.html.StyleSheet;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static processing.app.I18n.format;
|
|
||||||
import static processing.app.I18n.tr;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class ContributedPlatformTableCell extends InstallerTableCell {
|
|
||||||
|
|
||||||
private final JPanel panel;
|
|
||||||
private final JButton installButton;
|
|
||||||
private final JButton removeButton;
|
|
||||||
private final Component removeButtonPlaceholder;
|
|
||||||
private final Component installButtonPlaceholder;
|
|
||||||
private JComboBox downgradeChooser;
|
|
||||||
private final JComboBox versionToInstallChooser;
|
|
||||||
private final JButton downgradeButton;
|
|
||||||
private final JPanel buttonsPanel;
|
|
||||||
private final JPanel inactiveButtonsPanel;
|
|
||||||
private final JLabel statusLabel;
|
|
||||||
|
|
||||||
public ContributedPlatformTableCell() {
|
|
||||||
{
|
|
||||||
installButton = new JButton(tr("Install"));
|
|
||||||
installButton.addActionListener(e -> onInstall(editorValue.getSelected(), editorValue.getInstalled()));
|
|
||||||
int width = installButton.getPreferredSize().width;
|
|
||||||
installButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
removeButton = new JButton(tr("Remove"));
|
|
||||||
removeButton.addActionListener(e -> onRemove(editorValue.getInstalled()));
|
|
||||||
int width = removeButton.getPreferredSize().width;
|
|
||||||
removeButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
downgradeButton = new JButton(tr("Install"));
|
|
||||||
downgradeButton.addActionListener(e -> {
|
|
||||||
ContributedPlatform selected = (ContributedPlatform) downgradeChooser.getSelectedItem();
|
|
||||||
onInstall(selected, editorValue.getInstalled());
|
|
||||||
});
|
|
||||||
|
|
||||||
downgradeChooser = new JComboBox();
|
|
||||||
downgradeChooser.addItem("-");
|
|
||||||
downgradeChooser.setMaximumSize(downgradeChooser.getPreferredSize());
|
|
||||||
downgradeChooser.addItemListener(e -> {
|
|
||||||
Object selectVersionItem = downgradeChooser.getItemAt(0);
|
|
||||||
boolean disableDowngrade = (e.getItem() == selectVersionItem);
|
|
||||||
downgradeButton.setEnabled(!disableDowngrade);
|
|
||||||
});
|
|
||||||
|
|
||||||
versionToInstallChooser = new JComboBox();
|
|
||||||
versionToInstallChooser.addItem("-");
|
|
||||||
versionToInstallChooser.setMaximumSize(versionToInstallChooser.getPreferredSize());
|
|
||||||
versionToInstallChooser.addItemListener(e -> editorValue.select((ContributedPlatform) versionToInstallChooser.getSelectedItem()));
|
|
||||||
|
|
||||||
panel = new JPanel();
|
|
||||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
|
||||||
|
|
||||||
makeNewDescription(panel);
|
|
||||||
|
|
||||||
{
|
|
||||||
buttonsPanel = new JPanel();
|
|
||||||
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
|
|
||||||
buttonsPanel.setOpaque(false);
|
|
||||||
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(7));
|
|
||||||
buttonsPanel.add(downgradeChooser);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(downgradeButton);
|
|
||||||
|
|
||||||
buttonsPanel.add(Box.createHorizontalGlue());
|
|
||||||
|
|
||||||
buttonsPanel.add(versionToInstallChooser);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(installButton);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(removeButton);
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(5));
|
|
||||||
buttonsPanel.add(Box.createHorizontalStrut(15));
|
|
||||||
|
|
||||||
panel.add(buttonsPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
inactiveButtonsPanel = new JPanel();
|
|
||||||
inactiveButtonsPanel.setLayout(new BoxLayout(inactiveButtonsPanel, BoxLayout.X_AXIS));
|
|
||||||
inactiveButtonsPanel.setOpaque(false);
|
|
||||||
|
|
||||||
int height = installButton.getMinimumSize().height;
|
|
||||||
inactiveButtonsPanel.add(Box.createVerticalStrut(height));
|
|
||||||
inactiveButtonsPanel.add(Box.createGlue());
|
|
||||||
|
|
||||||
statusLabel = new JLabel(" ");
|
|
||||||
inactiveButtonsPanel.add(statusLabel);
|
|
||||||
inactiveButtonsPanel.add(Box.createHorizontalStrut(15));
|
|
||||||
|
|
||||||
panel.add(inactiveButtonsPanel);
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.add(Box.createVerticalStrut(15));
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTextPane makeNewDescription(JPanel panel) {
|
|
||||||
if (panel.getComponentCount() > 0) {
|
|
||||||
panel.remove(0);
|
|
||||||
}
|
|
||||||
JTextPane description = new JTextPane();
|
|
||||||
description.setInheritsPopupMenu(true);
|
|
||||||
Insets margin = description.getMargin();
|
|
||||||
margin.bottom = 0;
|
|
||||||
description.setMargin(margin);
|
|
||||||
description.setContentType("text/html");
|
|
||||||
Document doc = description.getDocument();
|
|
||||||
if (doc instanceof HTMLDocument) {
|
|
||||||
HTMLDocument html = (HTMLDocument) doc;
|
|
||||||
StyleSheet stylesheet = html.getStyleSheet();
|
|
||||||
stylesheet.addRule("body { margin: 0; padding: 0;"
|
|
||||||
+ "font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"
|
|
||||||
+ "font-size: 100%;" + "font-size: 0.95em; }");
|
|
||||||
}
|
|
||||||
description.setOpaque(false);
|
|
||||||
description.setBorder(new EmptyBorder(4, 7, 7, 7));
|
|
||||||
description.setHighlighter(null);
|
|
||||||
description.setEditable(false);
|
|
||||||
description.addHyperlinkListener(e -> {
|
|
||||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
|
||||||
Base.openURL(e.getDescription());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
description.addKeyListener(new DelegatingKeyListener(parentTable));
|
|
||||||
panel.add(description, 0);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onRemove(ContributedPlatform contributedPlatform) {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onInstall(ContributedPlatform contributedPlatform, ContributedPlatform installed) {
|
|
||||||
// Empty
|
|
||||||
}
|
|
||||||
|
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
|
||||||
boolean isSelected,
|
|
||||||
boolean hasFocus, int row,
|
|
||||||
int column) {
|
|
||||||
parentTable = table;
|
|
||||||
setEnabled(false);
|
|
||||||
Component component = getUpdatedCellComponent(value, isSelected, row, false);
|
|
||||||
if (row % 2 == 0) {
|
|
||||||
component.setBackground(new Color(236, 241, 241)); //#ecf1f1
|
|
||||||
} else {
|
|
||||||
component.setBackground(new Color(255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
int height = new Double(component.getPreferredSize().getHeight()).intValue();
|
|
||||||
if (table.getRowHeight(row) < height) {
|
|
||||||
table.setRowHeight(row, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContributionIndexTableModel.ContributedPlatformReleases editorValue;
|
|
||||||
private JTable parentTable;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getCellEditorValue() {
|
|
||||||
return editorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component getTableCellEditorComponent(JTable table, Object value,
|
|
||||||
boolean isSelected, int row,
|
|
||||||
int column) {
|
|
||||||
parentTable = table;
|
|
||||||
editorValue = (ContributionIndexTableModel.ContributedPlatformReleases) value;
|
|
||||||
setEnabled(true);
|
|
||||||
|
|
||||||
final ContributedPlatform installed = editorValue.getInstalled();
|
|
||||||
|
|
||||||
java.util.List<ContributedPlatform> releases = new LinkedList<>(editorValue.releases);
|
|
||||||
java.util.List<ContributedPlatform> uninstalledReleases = releases.stream().filter(new InstalledPredicate().negate()).collect(Collectors.toList());
|
|
||||||
|
|
||||||
java.util.List<ContributedPlatform> installedBuiltIn = releases.stream().filter(new InstalledPredicate()).filter(new BuiltInPredicate()).collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (installed != null && !installedBuiltIn.contains(installed)) {
|
|
||||||
uninstalledReleases.addAll(installedBuiltIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(uninstalledReleases, new ReverseComparator<>(new DownloadableContributionVersionComparator()));
|
|
||||||
|
|
||||||
downgradeChooser.removeAllItems();
|
|
||||||
downgradeChooser.addItem(tr("Select version"));
|
|
||||||
|
|
||||||
final java.util.List<ContributedPlatform> uninstalledPreviousReleases = new LinkedList<>();
|
|
||||||
final java.util.List<ContributedPlatform> uninstalledNewerReleases = new LinkedList<>();
|
|
||||||
|
|
||||||
final VersionComparator versionComparator = new VersionComparator();
|
|
||||||
uninstalledReleases.stream().forEach(input -> {
|
|
||||||
if (installed == null || versionComparator.greaterThan(installed.getParsedVersion(), input.getParsedVersion())) {
|
|
||||||
uninstalledPreviousReleases.add(input);
|
|
||||||
} else {
|
|
||||||
uninstalledNewerReleases.add(input);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
uninstalledNewerReleases.forEach(downgradeChooser::addItem);
|
|
||||||
uninstalledPreviousReleases.forEach(downgradeChooser::addItem);
|
|
||||||
|
|
||||||
downgradeChooser.setVisible(installed != null && (!uninstalledPreviousReleases.isEmpty() || uninstalledNewerReleases.size() > 1));
|
|
||||||
downgradeButton.setVisible(installed != null && (!uninstalledPreviousReleases.isEmpty() || uninstalledNewerReleases.size() > 1));
|
|
||||||
|
|
||||||
versionToInstallChooser.removeAllItems();
|
|
||||||
uninstalledReleases.forEach(versionToInstallChooser::addItem);
|
|
||||||
versionToInstallChooser.setVisible(installed == null && uninstalledReleases.size() > 1);
|
|
||||||
|
|
||||||
Component component = getUpdatedCellComponent(value, true, row, !installedBuiltIn.isEmpty());
|
|
||||||
component.setBackground(new Color(218, 227, 227)); //#dae3e3
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getUpdatedCellComponent(Object value, boolean isSelected, int row, boolean hasBuiltInRelease) {
|
|
||||||
ContributionIndexTableModel.ContributedPlatformReleases releases = (ContributionIndexTableModel.ContributedPlatformReleases) value;
|
|
||||||
|
|
||||||
JTextPane description = makeNewDescription(panel);
|
|
||||||
|
|
||||||
//FIXME: happens on macosx, don't know why
|
|
||||||
if (releases == null) {
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContributedPlatform selected = releases.getSelected();
|
|
||||||
ContributedPlatform installed = releases.getInstalled();
|
|
||||||
|
|
||||||
boolean removable, installable, upgradable;
|
|
||||||
if (installed == null) {
|
|
||||||
installable = true;
|
|
||||||
removable = false;
|
|
||||||
upgradable = false;
|
|
||||||
} else {
|
|
||||||
installable = false;
|
|
||||||
removable = !installed.isReadOnly() && !hasBuiltInRelease;
|
|
||||||
upgradable = new DownloadableContributionVersionComparator().compare(selected, installed) > 0;
|
|
||||||
}
|
|
||||||
if (installable) {
|
|
||||||
installButton.setText(tr("Install"));
|
|
||||||
}
|
|
||||||
if (upgradable) {
|
|
||||||
installButton.setText(tr("Update"));
|
|
||||||
}
|
|
||||||
installButton.setVisible(installable || upgradable);
|
|
||||||
installButtonPlaceholder.setVisible(!(installable || upgradable));
|
|
||||||
removeButton.setVisible(removable);
|
|
||||||
removeButtonPlaceholder.setVisible(!removable);
|
|
||||||
|
|
||||||
String desc = "<html><body>";
|
|
||||||
desc += "<b>" + selected.getName() + "</b>";
|
|
||||||
if (installed != null && installed.isReadOnly()) {
|
|
||||||
desc += " Built-In ";
|
|
||||||
}
|
|
||||||
|
|
||||||
String author = selected.getParentPackage().getMaintainer();
|
|
||||||
if (author != null && !author.isEmpty()) {
|
|
||||||
desc += " " + format("by <b>{0}</b>", author);
|
|
||||||
}
|
|
||||||
if (installed != null) {
|
|
||||||
desc += " " + format(tr("version <b>{0}</b>"), installed.getParsedVersion()) + " <strong><font color=\"#00979D\">INSTALLED</font></strong>";
|
|
||||||
}
|
|
||||||
desc += "<br />";
|
|
||||||
|
|
||||||
desc += tr("Boards included in this package:") + "<br />";
|
|
||||||
for (ContributedBoard board : selected.getBoards()) {
|
|
||||||
desc += board.getName() + ", ";
|
|
||||||
}
|
|
||||||
if (desc.lastIndexOf(',') != -1) {
|
|
||||||
desc = desc.substring(0, desc.lastIndexOf(',')) + ".<br />";
|
|
||||||
}
|
|
||||||
|
|
||||||
ContributedHelp help = null;
|
|
||||||
if (selected.getHelp() != null) {
|
|
||||||
help = selected.getHelp();
|
|
||||||
} else if (selected.getParentPackage().getHelp() != null) {
|
|
||||||
help = selected.getParentPackage().getHelp();
|
|
||||||
}
|
|
||||||
if (help != null) {
|
|
||||||
String url = help.getOnline();
|
|
||||||
if (url != null && !url.isEmpty()) {
|
|
||||||
desc += " " + format("<a href=\"{0}\">Online help</a><br/>", url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = selected.getParentPackage().getWebsiteURL();
|
|
||||||
if (url != null && !url.isEmpty()) {
|
|
||||||
desc += " " + format("<a href=\"{0}\">More info</a>", url);
|
|
||||||
}
|
|
||||||
|
|
||||||
desc += "</body></html>";
|
|
||||||
description.setText(desc);
|
|
||||||
description.setBackground(Color.WHITE);
|
|
||||||
|
|
||||||
// for modelToView to work, the text area has to be sized. It doesn't
|
|
||||||
// matter if it's visible or not.
|
|
||||||
|
|
||||||
// See:
|
|
||||||
// http://stackoverflow.com/questions/3081210/how-to-set-jtextarea-to-have-height-that-matches-the-size-of-a-text-it-contains
|
|
||||||
int width = parentTable.getBounds().width;
|
|
||||||
setJTextPaneDimensionToFitContainedText(description, width);
|
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
panel.setBackground(parentTable.getSelectionBackground());
|
|
||||||
panel.setForeground(parentTable.getSelectionForeground());
|
|
||||||
} else {
|
|
||||||
panel.setBackground(parentTable.getBackground());
|
|
||||||
panel.setForeground(parentTable.getForeground());
|
|
||||||
}
|
|
||||||
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Timer enabler = new Timer(100, new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
enable(true);
|
|
||||||
enabler.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
enable(false);
|
|
||||||
if (enabled) {
|
|
||||||
enabler.start();
|
|
||||||
} else {
|
|
||||||
enabler.stop();
|
|
||||||
}
|
|
||||||
buttonsPanel.setVisible(enabled);
|
|
||||||
inactiveButtonsPanel.setVisible(!enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enable(boolean enabled) {
|
|
||||||
installButton.setEnabled(enabled);
|
|
||||||
removeButton.setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(String status) {
|
|
||||||
statusLabel.setText(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
panel.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.packages.ui;
|
||||||
|
|
||||||
|
import static processing.app.I18n.tr;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.JTable;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
||||||
|
import cc.arduino.contributions.VersionComparator;
|
||||||
|
import cc.arduino.contributions.filters.BuiltInPredicate;
|
||||||
|
import cc.arduino.contributions.filters.InstalledPredicate;
|
||||||
|
import cc.arduino.contributions.packages.ContributedPlatform;
|
||||||
|
import cc.arduino.contributions.ui.InstallerTableCell;
|
||||||
|
import cc.arduino.utils.ReverseComparator;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ContributedPlatformTableCellEditor extends InstallerTableCell {
|
||||||
|
|
||||||
|
private ContributedPlatformTableCellJPanel cell;
|
||||||
|
private ContributedPlatformReleases value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCellEditorValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTableCellEditorComponent(JTable table, Object _value,
|
||||||
|
boolean isSelected, int row,
|
||||||
|
int column) {
|
||||||
|
value = (ContributedPlatformReleases) _value;
|
||||||
|
|
||||||
|
cell = new ContributedPlatformTableCellJPanel();
|
||||||
|
cell.installButton.addActionListener(e -> onInstall(value.getSelected(),
|
||||||
|
value.getInstalled()));
|
||||||
|
cell.removeButton.addActionListener(e -> onRemove(value.getInstalled()));
|
||||||
|
cell.downgradeButton.addActionListener(e -> {
|
||||||
|
ContributedPlatform selected = (ContributedPlatform) cell.downgradeChooser
|
||||||
|
.getSelectedItem();
|
||||||
|
onInstall(selected, value.getInstalled());
|
||||||
|
});
|
||||||
|
cell.versionToInstallChooser.addItemListener(e -> value
|
||||||
|
.select((ContributedPlatform) cell.versionToInstallChooser
|
||||||
|
.getSelectedItem()));
|
||||||
|
|
||||||
|
setEnabled(true);
|
||||||
|
|
||||||
|
final ContributedPlatform installed = value.getInstalled();
|
||||||
|
|
||||||
|
List<ContributedPlatform> releases = new LinkedList<>(value.releases);
|
||||||
|
List<ContributedPlatform> uninstalledReleases = releases.stream()
|
||||||
|
.filter(new InstalledPredicate().negate()).collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<ContributedPlatform> installedBuiltIn = releases.stream()
|
||||||
|
.filter(new InstalledPredicate()).filter(new BuiltInPredicate())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (installed != null && !installedBuiltIn.contains(installed)) {
|
||||||
|
uninstalledReleases.addAll(installedBuiltIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(uninstalledReleases, new ReverseComparator<>(
|
||||||
|
new DownloadableContributionVersionComparator()));
|
||||||
|
|
||||||
|
cell.downgradeChooser.removeAllItems();
|
||||||
|
cell.downgradeChooser.addItem(tr("Select version"));
|
||||||
|
|
||||||
|
final List<ContributedPlatform> uninstalledPreviousReleases = new LinkedList<>();
|
||||||
|
final List<ContributedPlatform> uninstalledNewerReleases = new LinkedList<>();
|
||||||
|
|
||||||
|
final VersionComparator versionComparator = new VersionComparator();
|
||||||
|
uninstalledReleases.stream().forEach(input -> {
|
||||||
|
if (installed == null
|
||||||
|
|| versionComparator.greaterThan(installed.getParsedVersion(),
|
||||||
|
input.getParsedVersion())) {
|
||||||
|
uninstalledPreviousReleases.add(input);
|
||||||
|
} else {
|
||||||
|
uninstalledNewerReleases.add(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
uninstalledNewerReleases.forEach(cell.downgradeChooser::addItem);
|
||||||
|
uninstalledPreviousReleases.forEach(cell.downgradeChooser::addItem);
|
||||||
|
|
||||||
|
boolean downgradeVisible = installed != null
|
||||||
|
&& (!uninstalledPreviousReleases.isEmpty()
|
||||||
|
|| uninstalledNewerReleases.size() > 1);
|
||||||
|
cell.downgradeChooser.setVisible(downgradeVisible);
|
||||||
|
cell.downgradeButton.setVisible(downgradeVisible);
|
||||||
|
|
||||||
|
cell.versionToInstallChooser.removeAllItems();
|
||||||
|
uninstalledReleases.forEach(cell.versionToInstallChooser::addItem);
|
||||||
|
cell.versionToInstallChooser
|
||||||
|
.setVisible(installed == null && uninstalledReleases.size() > 1);
|
||||||
|
|
||||||
|
cell.update(table, _value, true, !installedBuiltIn.isEmpty());
|
||||||
|
cell.setBackground(new Color(218, 227, 227)); // #dae3e3
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
cell.setButtonsVisible(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
cell.statusLabel.setText(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onRemove(ContributedPlatform contributedPlatform) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onInstall(ContributedPlatform contributedPlatform,
|
||||||
|
ContributedPlatform installed) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.packages.ui;
|
||||||
|
|
||||||
|
import static processing.app.I18n.format;
|
||||||
|
import static processing.app.I18n.tr;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Insets;
|
||||||
|
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.event.HyperlinkEvent;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.html.HTMLDocument;
|
||||||
|
import javax.swing.text.html.StyleSheet;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.DownloadableContributionVersionComparator;
|
||||||
|
import cc.arduino.contributions.packages.ContributedBoard;
|
||||||
|
import cc.arduino.contributions.packages.ContributedHelp;
|
||||||
|
import cc.arduino.contributions.packages.ContributedPlatform;
|
||||||
|
import cc.arduino.contributions.ui.InstallerTableCell;
|
||||||
|
import processing.app.Base;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ContributedPlatformTableCellJPanel extends JPanel {
|
||||||
|
|
||||||
|
final JButton installButton;
|
||||||
|
final JButton removeButton;
|
||||||
|
final Component removeButtonPlaceholder;
|
||||||
|
final Component installButtonPlaceholder;
|
||||||
|
final JComboBox downgradeChooser;
|
||||||
|
final JComboBox versionToInstallChooser;
|
||||||
|
final JButton downgradeButton;
|
||||||
|
final JPanel buttonsPanel;
|
||||||
|
final JPanel inactiveButtonsPanel;
|
||||||
|
final JLabel statusLabel;
|
||||||
|
|
||||||
|
public ContributedPlatformTableCellJPanel() {
|
||||||
|
super();
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
{
|
||||||
|
installButton = new JButton(tr("Install"));
|
||||||
|
int width = installButton.getPreferredSize().width;
|
||||||
|
installButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
removeButton = new JButton(tr("Remove"));
|
||||||
|
int width = removeButton.getPreferredSize().width;
|
||||||
|
removeButtonPlaceholder = Box.createRigidArea(new Dimension(width, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
downgradeButton = new JButton(tr("Install"));
|
||||||
|
|
||||||
|
downgradeChooser = new JComboBox();
|
||||||
|
downgradeChooser.addItem("-");
|
||||||
|
downgradeChooser.setMaximumSize(downgradeChooser.getPreferredSize());
|
||||||
|
downgradeChooser.addItemListener(e -> {
|
||||||
|
Object selectVersionItem = downgradeChooser.getItemAt(0);
|
||||||
|
boolean disableDowngrade = (e.getItem() == selectVersionItem);
|
||||||
|
downgradeButton.setEnabled(!disableDowngrade);
|
||||||
|
});
|
||||||
|
|
||||||
|
versionToInstallChooser = new JComboBox();
|
||||||
|
versionToInstallChooser.addItem("-");
|
||||||
|
versionToInstallChooser
|
||||||
|
.setMaximumSize(versionToInstallChooser.getPreferredSize());
|
||||||
|
|
||||||
|
makeNewDescription();
|
||||||
|
|
||||||
|
buttonsPanel = new JPanel();
|
||||||
|
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
|
||||||
|
buttonsPanel.setOpaque(false);
|
||||||
|
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(7));
|
||||||
|
buttonsPanel.add(downgradeChooser);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(downgradeButton);
|
||||||
|
|
||||||
|
buttonsPanel.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
buttonsPanel.add(versionToInstallChooser);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(installButton);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(removeButton);
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(5));
|
||||||
|
buttonsPanel.add(Box.createHorizontalStrut(15));
|
||||||
|
|
||||||
|
add(buttonsPanel);
|
||||||
|
|
||||||
|
inactiveButtonsPanel = new JPanel();
|
||||||
|
inactiveButtonsPanel
|
||||||
|
.setLayout(new BoxLayout(inactiveButtonsPanel, BoxLayout.X_AXIS));
|
||||||
|
inactiveButtonsPanel.setOpaque(false);
|
||||||
|
|
||||||
|
int height = installButton.getMinimumSize().height;
|
||||||
|
inactiveButtonsPanel.add(Box.createVerticalStrut(height));
|
||||||
|
inactiveButtonsPanel.add(Box.createGlue());
|
||||||
|
|
||||||
|
statusLabel = new JLabel(" ");
|
||||||
|
inactiveButtonsPanel.add(statusLabel);
|
||||||
|
inactiveButtonsPanel.add(Box.createHorizontalStrut(15));
|
||||||
|
|
||||||
|
add(inactiveButtonsPanel);
|
||||||
|
|
||||||
|
add(Box.createVerticalStrut(15));
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(JTable parentTable, Object value, boolean isSelected,
|
||||||
|
boolean hasBuiltInRelease) {
|
||||||
|
ContributedPlatformReleases releases = (ContributedPlatformReleases) value;
|
||||||
|
|
||||||
|
JTextPane description = makeNewDescription();
|
||||||
|
|
||||||
|
// FIXME: happens on macosx, don't know why
|
||||||
|
if (releases == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContributedPlatform selected = releases.getSelected();
|
||||||
|
ContributedPlatform installed = releases.getInstalled();
|
||||||
|
|
||||||
|
boolean removable, installable, upgradable;
|
||||||
|
if (installed == null) {
|
||||||
|
installable = true;
|
||||||
|
removable = false;
|
||||||
|
upgradable = false;
|
||||||
|
} else {
|
||||||
|
installable = false;
|
||||||
|
removable = !installed.isReadOnly() && !hasBuiltInRelease;
|
||||||
|
upgradable = new DownloadableContributionVersionComparator()
|
||||||
|
.compare(selected, installed) > 0;
|
||||||
|
}
|
||||||
|
if (installable) {
|
||||||
|
installButton.setText(tr("Install"));
|
||||||
|
}
|
||||||
|
if (upgradable) {
|
||||||
|
installButton.setText(tr("Update"));
|
||||||
|
}
|
||||||
|
installButton.setVisible(installable || upgradable);
|
||||||
|
installButtonPlaceholder.setVisible(!(installable || upgradable));
|
||||||
|
removeButton.setVisible(removable);
|
||||||
|
removeButtonPlaceholder.setVisible(!removable);
|
||||||
|
|
||||||
|
String desc = "<html><body>";
|
||||||
|
desc += "<b>" + selected.getName() + "</b>";
|
||||||
|
if (installed != null && installed.isReadOnly()) {
|
||||||
|
desc += " Built-In ";
|
||||||
|
}
|
||||||
|
|
||||||
|
String author = selected.getParentPackage().getMaintainer();
|
||||||
|
if (author != null && !author.isEmpty()) {
|
||||||
|
desc += " " + format("by <b>{0}</b>", author);
|
||||||
|
}
|
||||||
|
if (installed != null) {
|
||||||
|
desc += " "
|
||||||
|
+ format(tr("version <b>{0}</b>"), installed.getParsedVersion())
|
||||||
|
+ " <strong><font color=\"#00979D\">INSTALLED</font></strong>";
|
||||||
|
}
|
||||||
|
desc += "<br />";
|
||||||
|
|
||||||
|
desc += tr("Boards included in this package:") + "<br />";
|
||||||
|
for (ContributedBoard board : selected.getBoards()) {
|
||||||
|
desc += board.getName() + ", ";
|
||||||
|
}
|
||||||
|
if (desc.lastIndexOf(',') != -1) {
|
||||||
|
desc = desc.substring(0, desc.lastIndexOf(',')) + ".<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
ContributedHelp help = null;
|
||||||
|
if (selected.getHelp() != null) {
|
||||||
|
help = selected.getHelp();
|
||||||
|
} else if (selected.getParentPackage().getHelp() != null) {
|
||||||
|
help = selected.getParentPackage().getHelp();
|
||||||
|
}
|
||||||
|
if (help != null) {
|
||||||
|
String url = help.getOnline();
|
||||||
|
if (url != null && !url.isEmpty()) {
|
||||||
|
desc += " " + format("<a href=\"{0}\">Online help</a><br/>", url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = selected.getParentPackage().getWebsiteURL();
|
||||||
|
if (url != null && !url.isEmpty()) {
|
||||||
|
desc += " " + format("<a href=\"{0}\">More info</a>", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
desc += "</body></html>";
|
||||||
|
description.setText(desc);
|
||||||
|
description.setBackground(Color.WHITE);
|
||||||
|
|
||||||
|
// for modelToView to work, the text area has to be sized. It doesn't
|
||||||
|
// matter if it's visible or not.
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// http://stackoverflow.com/questions/3081210/how-to-set-jtextarea-to-have-height-that-matches-the-size-of-a-text-it-contains
|
||||||
|
int width = parentTable.getBounds().width;
|
||||||
|
InstallerTableCell.setJTextPaneDimensionToFitContainedText(description,
|
||||||
|
width);
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
setBackground(parentTable.getSelectionBackground());
|
||||||
|
setForeground(parentTable.getSelectionForeground());
|
||||||
|
} else {
|
||||||
|
setBackground(parentTable.getBackground());
|
||||||
|
setForeground(parentTable.getForeground());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JTextPane makeNewDescription() {
|
||||||
|
if (getComponentCount() > 0) {
|
||||||
|
remove(0);
|
||||||
|
}
|
||||||
|
JTextPane description = new JTextPane();
|
||||||
|
description.setInheritsPopupMenu(true);
|
||||||
|
Insets margin = description.getMargin();
|
||||||
|
margin.bottom = 0;
|
||||||
|
description.setMargin(margin);
|
||||||
|
description.setContentType("text/html");
|
||||||
|
Document doc = description.getDocument();
|
||||||
|
if (doc instanceof HTMLDocument) {
|
||||||
|
HTMLDocument html = (HTMLDocument) doc;
|
||||||
|
StyleSheet stylesheet = html.getStyleSheet();
|
||||||
|
stylesheet.addRule("body { margin: 0; padding: 0;"
|
||||||
|
+ "font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"
|
||||||
|
+ "font-size: 100%;" + "font-size: 0.95em; }");
|
||||||
|
}
|
||||||
|
description.setOpaque(false);
|
||||||
|
description.setBorder(new EmptyBorder(4, 7, 7, 7));
|
||||||
|
description.setHighlighter(null);
|
||||||
|
description.setEditable(false);
|
||||||
|
description.addHyperlinkListener(e -> {
|
||||||
|
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
|
Base.openURL(e.getDescription());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(description, 0);
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonsVisible(boolean enabled) {
|
||||||
|
installButton.setEnabled(enabled);
|
||||||
|
removeButton.setEnabled(enabled);
|
||||||
|
buttonsPanel.setVisible(enabled);
|
||||||
|
inactiveButtonsPanel.setVisible(!enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cc.arduino.contributions.packages.ui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class ContributedPlatformTableCellRenderer implements TableCellRenderer {
|
||||||
|
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||||
|
boolean isSelected,
|
||||||
|
boolean hasFocus, int row,
|
||||||
|
int column) {
|
||||||
|
ContributedPlatformTableCellJPanel cell = new ContributedPlatformTableCellJPanel();
|
||||||
|
cell.setButtonsVisible(false);
|
||||||
|
cell.update(table, value, isSelected, false);
|
||||||
|
|
||||||
|
if (row % 2 == 0) {
|
||||||
|
cell.setBackground(new Color(236, 241, 241)); // #ecf1f1
|
||||||
|
} else {
|
||||||
|
cell.setBackground(new Color(255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
int height = new Double(cell.getPreferredSize().getHeight()).intValue();
|
||||||
|
if (table.getRowHeight(row) < height) {
|
||||||
|
table.setRowHeight(row, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,8 +29,6 @@
|
|||||||
|
|
||||||
package cc.arduino.contributions.packages.ui;
|
package cc.arduino.contributions.packages.ui;
|
||||||
|
|
||||||
import cc.arduino.contributions.DownloadableContributionBuiltInAtTheBottomComparator;
|
|
||||||
import cc.arduino.contributions.filters.InstalledPredicate;
|
|
||||||
import cc.arduino.contributions.packages.ContributedBoard;
|
import cc.arduino.contributions.packages.ContributedBoard;
|
||||||
import cc.arduino.contributions.packages.ContributedPackage;
|
import cc.arduino.contributions.packages.ContributedPackage;
|
||||||
import cc.arduino.contributions.packages.ContributedPlatform;
|
import cc.arduino.contributions.packages.ContributedPlatform;
|
||||||
@ -38,89 +36,30 @@ import cc.arduino.contributions.ui.FilteredAbstractTableModel;
|
|||||||
import processing.app.BaseNoGui;
|
import processing.app.BaseNoGui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class ContributionIndexTableModel extends FilteredAbstractTableModel<ContributedPlatform> {
|
public class ContributionIndexTableModel
|
||||||
|
extends FilteredAbstractTableModel<ContributedPlatform> {
|
||||||
public final static int DESCRIPTION_COL = 0;
|
|
||||||
|
|
||||||
public static class ContributedPlatformReleases {
|
|
||||||
public final ContributedPackage packager;
|
|
||||||
public final String arch;
|
|
||||||
public final List<ContributedPlatform> releases;
|
|
||||||
public final List<String> versions;
|
|
||||||
public ContributedPlatform selected = null;
|
|
||||||
|
|
||||||
public ContributedPlatformReleases(ContributedPlatform platform) {
|
|
||||||
this.packager = platform.getParentPackage();
|
|
||||||
this.arch = platform.getArchitecture();
|
|
||||||
this.releases = new LinkedList<>();
|
|
||||||
this.versions = new LinkedList<>();
|
|
||||||
add(platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldContain(ContributedPlatform platform) {
|
|
||||||
if (platform.getParentPackage() != packager)
|
|
||||||
return false;
|
|
||||||
return platform.getArchitecture().equals(arch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(ContributedPlatform platform) {
|
|
||||||
releases.add(platform);
|
|
||||||
String version = platform.getParsedVersion();
|
|
||||||
if (version != null) {
|
|
||||||
versions.add(version);
|
|
||||||
}
|
|
||||||
selected = getLatest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContributedPlatform getInstalled() {
|
|
||||||
List<ContributedPlatform> installedReleases = releases.stream().filter(new InstalledPredicate()).collect(Collectors.toList());
|
|
||||||
Collections.sort(installedReleases, new DownloadableContributionBuiltInAtTheBottomComparator());
|
|
||||||
|
|
||||||
if (installedReleases.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return installedReleases.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContributedPlatform getLatest() {
|
|
||||||
return getLatestOf(releases);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContributedPlatform getSelected() {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void select(ContributedPlatform value) {
|
|
||||||
for (ContributedPlatform plat : releases) {
|
|
||||||
if (plat == value) {
|
|
||||||
selected = plat;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<ContributedPlatformReleases> contributions = new ArrayList<>();
|
private final List<ContributedPlatformReleases> contributions = new ArrayList<>();
|
||||||
|
private final String[] columnNames = { "Description" };
|
||||||
|
private final Class<?>[] columnTypes = { ContributedPlatform.class };
|
||||||
|
|
||||||
private final String[] columnNames = {"Description"};
|
public void updateIndexFilter(String[] filters,
|
||||||
|
Stream<Predicate<ContributedPlatform>> additionalFilters) {
|
||||||
private final Class<?>[] columnTypes = {ContributedPlatform.class};
|
|
||||||
|
|
||||||
public void updateIndexFilter(String[] filters, Stream<Predicate<ContributedPlatform>> additionalFilters) {
|
|
||||||
contributions.clear();
|
contributions.clear();
|
||||||
Predicate<ContributedPlatform> filter = additionalFilters.reduce(Predicate::and).get();
|
Predicate<ContributedPlatform> filter = additionalFilters
|
||||||
|
.reduce(Predicate::and).get();
|
||||||
for (ContributedPackage pack : BaseNoGui.indexer.getPackages()) {
|
for (ContributedPackage pack : BaseNoGui.indexer.getPackages()) {
|
||||||
for (ContributedPlatform platform : pack.getPlatforms()) {
|
for (ContributedPlatform platform : pack.getPlatforms()) {
|
||||||
String compoundTargetSearchText = platform.getName() + "\n" + platform.getBoards().stream().map(ContributedBoard::getName).collect(Collectors.joining(" "));
|
String compoundTargetSearchText = platform.getName() + "\n"
|
||||||
|
+ platform.getBoards().stream()
|
||||||
|
.map(ContributedBoard::getName)
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
if (!filter.test(platform)) {
|
if (!filter.test(platform)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -139,7 +78,7 @@ public class ContributionIndexTableModel extends FilteredAbstractTableModel<Cont
|
|||||||
* @param string
|
* @param string
|
||||||
* @param set
|
* @param set
|
||||||
* @return <b>true<b> if all the strings in <b>set</b> are contained in
|
* @return <b>true<b> if all the strings in <b>set</b> are contained in
|
||||||
* <b>string</b>.
|
* <b>string</b>.
|
||||||
*/
|
*/
|
||||||
private boolean stringContainsAll(String string, String set[]) {
|
private boolean stringContainsAll(String string, String set[]) {
|
||||||
if (set == null)
|
if (set == null)
|
||||||
@ -184,9 +123,7 @@ public class ContributionIndexTableModel extends FilteredAbstractTableModel<Cont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object value, int row, int col) {
|
public void setValueAt(Object value, int row, int col) {
|
||||||
if (col == DESCRIPTION_COL) {
|
fireTableCellUpdated(row, col);
|
||||||
fireTableCellUpdated(row, col);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -195,15 +132,12 @@ public class ContributionIndexTableModel extends FilteredAbstractTableModel<Cont
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ContributedPlatformReleases contribution = contributions.get(row);
|
ContributedPlatformReleases contribution = contributions.get(row);
|
||||||
if (col == DESCRIPTION_COL) {
|
return contribution;// .getSelected();
|
||||||
return contribution;// .getSelected();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCellEditable(int row, int col) {
|
public boolean isCellEditable(int row, int col) {
|
||||||
return col == DESCRIPTION_COL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContributedPlatformReleases getReleases(int row) {
|
public ContributedPlatformReleases getReleases(int row) {
|
||||||
|
@ -38,6 +38,8 @@ import processing.app.BaseNoGui;
|
|||||||
import processing.app.I18n;
|
import processing.app.I18n;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -60,15 +62,16 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InstallerTableCell createCellRenderer() {
|
protected TableCellRenderer createCellRenderer() {
|
||||||
return new ContributedPlatformTableCell();
|
return new ContributedPlatformTableCellRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InstallerTableCell createCellEditor() {
|
protected InstallerTableCell createCellEditor() {
|
||||||
return new ContributedPlatformTableCell() {
|
return new ContributedPlatformTableCellEditor() {
|
||||||
@Override
|
@Override
|
||||||
protected void onInstall(ContributedPlatform selected, ContributedPlatform installed) {
|
protected void onInstall(ContributedPlatform selected,
|
||||||
|
ContributedPlatform installed) {
|
||||||
if (selected.isReadOnly()) {
|
if (selected.isReadOnly()) {
|
||||||
onRemovePressed(installed, false);
|
onRemovePressed(installed, false);
|
||||||
} else {
|
} else {
|
||||||
@ -84,12 +87,14 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ContributionManagerUI(Frame parent, ContributionInstaller installer) {
|
public ContributionManagerUI(Frame parent, ContributionInstaller installer) {
|
||||||
super(parent, tr("Boards Manager"), Dialog.ModalityType.APPLICATION_MODAL, tr("Unable to reach Arduino.cc due to possible network issues."));
|
super(parent, tr("Boards Manager"), Dialog.ModalityType.APPLICATION_MODAL,
|
||||||
|
tr("Unable to reach Arduino.cc due to possible network issues."));
|
||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUI() {
|
public void updateUI() {
|
||||||
DropdownItem<DownloadableContribution> previouslySelectedCategory = (DropdownItem<DownloadableContribution>) categoryChooser.getSelectedItem();
|
DropdownItem<DownloadableContribution> previouslySelectedCategory = (DropdownItem<DownloadableContribution>) categoryChooser
|
||||||
|
.getSelectedItem();
|
||||||
|
|
||||||
categoryChooser.removeActionListener(categoryChooserActionListener);
|
categoryChooser.removeActionListener(categoryChooserActionListener);
|
||||||
|
|
||||||
@ -138,7 +143,8 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
installerThread = new Thread(() -> {
|
installerThread = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
setProgressVisible(true, "");
|
setProgressVisible(true, "");
|
||||||
List<String> downloadedPackageIndexFiles = installer.updateIndex(this::setProgress);
|
List<String> downloadedPackageIndexFiles = installer
|
||||||
|
.updateIndex(this::setProgress);
|
||||||
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
|
installer.deleteUnknownFiles(downloadedPackageIndexFiles);
|
||||||
onIndexesUpdated();
|
onIndexesUpdated();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -148,11 +154,14 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
installerThread.setName("ContributionManager Update Thread");
|
installerThread.setName("ContributionManager Update Thread");
|
||||||
installerThread.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(this, noConnectionErrorMessage));
|
installerThread
|
||||||
|
.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(
|
||||||
|
this, noConnectionErrorMessage));
|
||||||
installerThread.start();
|
installerThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onInstallPressed(final ContributedPlatform platformToInstall, final ContributedPlatform platformToRemove) {
|
public void onInstallPressed(final ContributedPlatform platformToInstall,
|
||||||
|
final ContributedPlatform platformToRemove) {
|
||||||
clearErrorMessage();
|
clearErrorMessage();
|
||||||
installerThread = new Thread(() -> {
|
installerThread = new Thread(() -> {
|
||||||
List<String> errors = new LinkedList<>();
|
List<String> errors = new LinkedList<>();
|
||||||
@ -173,15 +182,24 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
installerThread.setName("ContributionManager Install Thread");
|
installerThread.setName("ContributionManager Install Thread");
|
||||||
installerThread.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(this, noConnectionErrorMessage));
|
installerThread
|
||||||
|
.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(
|
||||||
|
this, noConnectionErrorMessage));
|
||||||
installerThread.start();
|
installerThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRemovePressed(final ContributedPlatform platform, boolean showWarning) {
|
public void onRemovePressed(final ContributedPlatform platform,
|
||||||
|
boolean showWarning) {
|
||||||
clearErrorMessage();
|
clearErrorMessage();
|
||||||
|
|
||||||
if (showWarning) {
|
if (showWarning) {
|
||||||
int chosenOption = JOptionPane.showConfirmDialog(this, I18n.format(tr("Do you want to remove {0}?\nIf you do so you won't be able to use {0} any more."), platform.getName()), tr("Please confirm boards deletion"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
int chosenOption = JOptionPane
|
||||||
|
.showConfirmDialog(this,
|
||||||
|
I18n.format(tr("Do you want to remove {0}?\nIf you do so you won't be able to use {0} any more."),
|
||||||
|
platform.getName()),
|
||||||
|
tr("Please confirm boards deletion"),
|
||||||
|
JOptionPane.YES_NO_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE);
|
||||||
if (chosenOption != JOptionPane.YES_OPTION) {
|
if (chosenOption != JOptionPane.YES_OPTION) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -199,7 +217,9 @@ public class ContributionManagerUI extends InstallerJDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
installerThread.setName("ContributionManager Remove Thread");
|
installerThread.setName("ContributionManager Remove Thread");
|
||||||
installerThread.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(this, noConnectionErrorMessage));
|
installerThread
|
||||||
|
.setUncaughtExceptionHandler(new InstallerJDialogUncaughtExceptionHandler(
|
||||||
|
this, noConnectionErrorMessage));
|
||||||
installerThread.start();
|
installerThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,21 +29,43 @@
|
|||||||
|
|
||||||
package cc.arduino.contributions.ui;
|
package cc.arduino.contributions.ui;
|
||||||
|
|
||||||
import cc.arduino.contributions.ui.listeners.AbstractKeyListener;
|
import static processing.app.I18n.tr;
|
||||||
import processing.app.Base;
|
|
||||||
import processing.app.Theme;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import java.awt.BorderLayout;
|
||||||
import javax.swing.border.EmptyBorder;
|
import java.awt.Color;
|
||||||
import javax.swing.table.TableColumn;
|
import java.awt.Container;
|
||||||
import javax.swing.table.TableColumnModel;
|
import java.awt.Dimension;
|
||||||
import java.awt.*;
|
import java.awt.Frame;
|
||||||
import java.awt.event.*;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
|
import java.awt.event.FocusListener;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static cc.arduino.contributions.packages.ui.ContributionIndexTableModel.DESCRIPTION_COL;
|
import javax.swing.Box;
|
||||||
import static processing.app.I18n.tr;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTable;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.WindowConstants;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.table.TableCellRenderer;
|
||||||
|
import javax.swing.table.TableColumn;
|
||||||
|
import javax.swing.table.TableColumnModel;
|
||||||
|
|
||||||
|
import cc.arduino.contributions.ui.listeners.AbstractKeyListener;
|
||||||
|
import processing.app.Base;
|
||||||
|
import processing.app.Theme;
|
||||||
|
|
||||||
public abstract class InstallerJDialog<T> extends JDialog {
|
public abstract class InstallerJDialog<T> extends JDialog {
|
||||||
|
|
||||||
@ -67,7 +89,7 @@ public abstract class InstallerJDialog<T> extends JDialog {
|
|||||||
|
|
||||||
abstract protected FilteredAbstractTableModel<T> createContribModel();
|
abstract protected FilteredAbstractTableModel<T> createContribModel();
|
||||||
|
|
||||||
abstract protected InstallerTableCell createCellRenderer();
|
abstract protected TableCellRenderer createCellRenderer();
|
||||||
|
|
||||||
abstract protected InstallerTableCell createCellEditor();
|
abstract protected InstallerTableCell createCellEditor();
|
||||||
|
|
||||||
@ -142,7 +164,7 @@ public abstract class InstallerJDialog<T> extends JDialog {
|
|||||||
|
|
||||||
{
|
{
|
||||||
TableColumnModel tcm = contribTable.getColumnModel();
|
TableColumnModel tcm = contribTable.getColumnModel();
|
||||||
TableColumn col = tcm.getColumn(DESCRIPTION_COL);
|
TableColumn col = tcm.getColumn(0);
|
||||||
col.setCellRenderer(createCellRenderer());
|
col.setCellRenderer(createCellRenderer());
|
||||||
col.setCellEditor(createCellEditor());
|
col.setCellEditor(createCellEditor());
|
||||||
col.setResizable(true);
|
col.setResizable(true);
|
||||||
|
@ -29,21 +29,21 @@
|
|||||||
|
|
||||||
package cc.arduino.contributions.ui;
|
package cc.arduino.contributions.ui;
|
||||||
|
|
||||||
import javax.swing.*;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
|
import javax.swing.AbstractCellEditor;
|
||||||
|
import javax.swing.JTextPane;
|
||||||
import javax.swing.table.TableCellEditor;
|
import javax.swing.table.TableCellEditor;
|
||||||
import javax.swing.table.TableCellRenderer;
|
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
public abstract class InstallerTableCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
|
public abstract class InstallerTableCell extends AbstractCellEditor implements TableCellEditor {
|
||||||
|
|
||||||
public void setEnabled(boolean b) {
|
abstract public void setEnabled(boolean b);
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(String s) {
|
abstract public void setStatus(String s);
|
||||||
}
|
|
||||||
|
|
||||||
protected void setJTextPaneDimensionToFitContainedText(JTextPane jTextPane, int width) {
|
public static void setJTextPaneDimensionToFitContainedText(JTextPane jTextPane, int width) {
|
||||||
Dimension minimumDimension = new Dimension(width, 10);
|
Dimension minimumDimension = new Dimension(width, 10);
|
||||||
jTextPane.setPreferredSize(minimumDimension);
|
jTextPane.setPreferredSize(minimumDimension);
|
||||||
jTextPane.setSize(minimumDimension);
|
jTextPane.setSize(minimumDimension);
|
||||||
|
Loading…
Reference in New Issue
Block a user