From 6370a74632b6ff23e94cedea6049d1a51443695b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 24 Dec 2015 19:47:57 +0100 Subject: [PATCH] Split TableCellRenderes from TableCellEditors This rationalization helps to better follow the swing abstractions of table models and increase separation of concerns. (WIP: ContributedPlatforms needs a similar refactoring that will be done in the next commits) --- .../ui/ContributedLibraryTableCell.java | 243 +++++++++++ .../ui/ContributedLibraryTableCellEditor.java | 187 +++++++++ .../ContributedLibraryTableCellRenderer.java | 380 +----------------- .../libraries/ui/LibraryManagerUI.java | 35 +- .../contributions/ui/InstallerJDialog.java | 47 ++- .../contributions/ui/InstallerTableCell.java | 18 +- 6 files changed, 502 insertions(+), 408 deletions(-) create mode 100644 app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java create mode 100644 app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java new file mode 100644 index 000000000..b6f18a604 --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCell.java @@ -0,0 +1,243 @@ +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 ContributedLibraryTableCell { + + protected final JPanel panel; + protected final JButton installButton; + protected final Component installButtonPlaceholder; + protected final JComboBox downgradeChooser; + protected final JComboBox versionToInstallChooser; + protected final JButton downgradeButton; + protected final JPanel buttonsPanel; + protected final JPanel inactiveButtonsPanel; + protected final JLabel statusLabel; + + public ContributedLibraryTableCell() { + 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()); + + 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)); + } + + void update(JTable parentTable, 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; + + 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 = ""; + + // Library name... + desc += format("{0}", name); + if (installed != null && installed.isReadOnly()) { + desc += " Built-In "; + } + + // ...author... + desc += format("", midcolor); + if (author != null && !author.isEmpty()) { + desc += format(" by {0}", author); + } + + // ...version. + if (installed != null) { + String installedVer = installed.getParsedVersion(); + if (installedVer == null) { + desc += " " + tr("Version unknown"); + } else { + desc += " " + format(tr("Version {0}"), installedVer); + } + } + desc += ""; + + if (installed != null) { + desc += " INSTALLED"; + } + + desc += "
"; + + // Description + if (sentence != null) { + desc += format("{0} ", sentence); + if (paragraph != null && !paragraph.isEmpty()) + desc += format("{0}", paragraph); + desc += "
"; + } + if (author != null && !author.isEmpty()) { + desc += format("More info", website); + } + + desc += ""; + 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) { + panel.setBackground(parentTable.getSelectionBackground()); + panel.setForeground(parentTable.getSelectionForeground()); + } else { + panel.setBackground(parentTable.getBackground()); + panel.setForeground(parentTable.getForeground()); + } + } + + private static 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; + } + + +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java new file mode 100644 index 000000000..bb838c513 --- /dev/null +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java @@ -0,0 +1,187 @@ +/* + * 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.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 javax.swing.JComboBox; +import javax.swing.JTable; +import javax.swing.Timer; + +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 ContributedLibraryTableCell 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 ContributedLibraryTableCell(); + 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 releases = editorValue.getReleases().stream() + .filter(new OnlyUpstreamReleasePredicate()) + .collect(Collectors.toList()); + List uninstalledReleases = releases.stream() + .filter(new InstalledPredicate().negate()).collect(Collectors.toList()); + + List 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 uninstalledPreviousReleases = new LinkedList<>(); + final List 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.update(table, value, true, row, !installedBuiltIn.isEmpty()); + editorCell.panel.setBackground(new Color(218, 227, 227)); // #dae3e3 + return editorCell.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(); + } + editorCell.buttonsPanel.setVisible(enabled); + editorCell.inactiveButtonsPanel.setVisible(!enabled); + } + + public void enable(boolean enabled) { + editorCell.installButton.setEnabled(enabled); + } + + public void setStatus(String status) { + editorCell.statusLabel.setText(status); + } + + public void invalidate() { + editorCell.panel.invalidate(); + } + + + protected void onRemove(ContributedLibrary selected) { + // Empty + } + + protected void onInstall(ContributedLibrary selected, + ContributedLibrary installed) { + // Empty + } + +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellRenderer.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellRenderer.java index ae3b1f31c..5fae977de 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellRenderer.java +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellRenderer.java @@ -29,279 +29,27 @@ 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 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 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.Timer; -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.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; -import processing.app.Base; +import javax.swing.table.TableCellRenderer; @SuppressWarnings("serial") -public class ContributedLibraryTableCellRenderer extends InstallerTableCell { - - private class Cell { - private final JPanel panel; - private final JButton installButton; - private final Component installButtonPlaceholder; - private final JComboBox downgradeChooser; - private final JComboBox versionToInstallChooser; - private final JButton downgradeButton; - private final JPanel buttonsPanel; - private final JPanel inactiveButtonsPanel; - private final JLabel statusLabel; - - public Cell() { - 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()); - - 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 void update(JTable parentTable, 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; - - 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 = ""; - - // Library name... - desc += format("{0}", name); - if (installed != null && installed.isReadOnly()) { - desc += " Built-In "; - } - - // ...author... - desc += format("", midcolor); - if (author != null && !author.isEmpty()) { - desc += format(" by {0}", author); - } - - // ...version. - if (installed != null) { - String installedVer = installed.getParsedVersion(); - if (installedVer == null) { - desc += " " + tr("Version unknown"); - } else { - desc += " " + format(tr("Version {0}"), installedVer); - } - } - desc += ""; - - if (installed != null) { - desc += " INSTALLED"; - } - - desc += "
"; - - // Description - if (sentence != null) { - desc += format("{0} ", sentence); - if (paragraph != null && !paragraph.isEmpty()) - desc += format("{0}", paragraph); - desc += "
"; - } - if (author != null && !author.isEmpty()) { - desc += format("More info", website); - } - - desc += ""; - 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()); - } - } - } - - private static 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 class ContributedLibraryTableCellRenderer implements TableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - Cell cell = new Cell(); + ContributedLibraryTableCell cell = new ContributedLibraryTableCell(); cell.installButton.setEnabled(false); cell.buttonsPanel.setVisible(false); cell.inactiveButtonsPanel.setVisible(true); + cell.update(table, value, isSelected, row, false); + if (row % 2 == 0) { cell.panel.setBackground(new Color(236, 241, 241)); // #ecf1f1 } else { @@ -317,122 +65,4 @@ public class ContributedLibraryTableCellRenderer extends InstallerTableCell { return cell.panel; } - private ContributedLibraryReleases editorValue; - private Cell 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 Cell(); - 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 releases = editorValue.getReleases().stream() - .filter(new OnlyUpstreamReleasePredicate()) - .collect(Collectors.toList()); - List uninstalledReleases = releases.stream() - .filter(new InstalledPredicate().negate()).collect(Collectors.toList()); - - List 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 uninstalledPreviousReleases = new LinkedList<>(); - final List 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.update(table, value, true, row, !installedBuiltIn.isEmpty()); - editorCell.panel.setBackground(new Color(218, 227, 227)); // #dae3e3 - return editorCell.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(); - } - editorCell.buttonsPanel.setVisible(enabled); - editorCell.inactiveButtonsPanel.setVisible(!enabled); - } - - public void enable(boolean enabled) { - editorCell.installButton.setEnabled(enabled); - } - - public void setStatus(String status) { - editorCell.statusLabel.setText(status); - } - - public void invalidate() { - editorCell.panel.invalidate(); - } - } diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index 64210818d..943c21fdd 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -29,16 +29,10 @@ package cc.arduino.contributions.libraries.ui; -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.*; -import cc.arduino.utils.Progress; -import processing.app.BaseNoGui; +import static processing.app.I18n.tr; -import javax.swing.*; -import java.awt.*; +import java.awt.Dialog; +import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; @@ -46,7 +40,24 @@ import java.util.Collections; import java.util.LinkedList; 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") public class LibraryManagerUI extends InstallerJDialog { @@ -65,13 +76,13 @@ public class LibraryManagerUI extends InstallerJDialog { } @Override - protected InstallerTableCell createCellRenderer() { + protected TableCellRenderer createCellRenderer() { return new ContributedLibraryTableCellRenderer(); } @Override protected InstallerTableCell createCellEditor() { - return new ContributedLibraryTableCellRenderer() { + return new ContributedLibraryTableCellEditor() { @Override protected void onInstall(ContributedLibrary selectedLibrary, ContributedLibrary installedLibrary) { if (selectedLibrary.isReadOnly()) { diff --git a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java index 255d6f407..14c53b025 100644 --- a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java +++ b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java @@ -29,21 +29,44 @@ package cc.arduino.contributions.ui; -import cc.arduino.contributions.ui.listeners.AbstractKeyListener; -import processing.app.Base; -import processing.app.Theme; +import static cc.arduino.contributions.packages.ui.ContributionIndexTableModel.DESCRIPTION_COL; +import static processing.app.I18n.tr; -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +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.stream.Stream; -import static cc.arduino.contributions.packages.ui.ContributionIndexTableModel.DESCRIPTION_COL; -import static processing.app.I18n.tr; +import javax.swing.Box; +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 extends JDialog { @@ -67,7 +90,7 @@ public abstract class InstallerJDialog extends JDialog { abstract protected FilteredAbstractTableModel createContribModel(); - abstract protected InstallerTableCell createCellRenderer(); + abstract protected TableCellRenderer createCellRenderer(); abstract protected InstallerTableCell createCellEditor(); diff --git a/app/src/cc/arduino/contributions/ui/InstallerTableCell.java b/app/src/cc/arduino/contributions/ui/InstallerTableCell.java index e45655d2f..bbf62ebad 100644 --- a/app/src/cc/arduino/contributions/ui/InstallerTableCell.java +++ b/app/src/cc/arduino/contributions/ui/InstallerTableCell.java @@ -29,21 +29,21 @@ 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.TableCellRenderer; 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); jTextPane.setPreferredSize(minimumDimension); jTextPane.setSize(minimumDimension);