blob: 1ca1e1e8539f995c742e18011374f6fc1ab9f59e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.java.disco;
import eu.hansolo.jdktools.Architecture;
import eu.hansolo.jdktools.ArchiveType;
import eu.hansolo.jdktools.Latest;
import eu.hansolo.jdktools.LibCType;
import eu.hansolo.jdktools.OperatingSystem;
import eu.hansolo.jdktools.PackageType;
import eu.hansolo.jdktools.TermOfSupport;
import eu.hansolo.jdktools.versioning.VersionNumber;
import io.foojay.api.discoclient.pkg.Distribution;
import io.foojay.api.discoclient.pkg.Pkg;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLabel;
import org.checkerframework.checker.guieffect.qual.UIEffect;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
@NbBundle.Messages({
"QuickPanel.searching=Searching...",
"QuickPanel.error=No matching JDK found."
})
public class QuickPanel extends javax.swing.JPanel {
private final DefaultComboBoxModel<Distribution> distrosModel = new DefaultComboBoxModel<>();
private final SelectPackagePanel parentPanel;
private Pkg pkg;
private boolean ignoreChanges;
@Deprecated
public QuickPanel() {
this(null);
}
QuickPanel(SelectPackagePanel parentPanel) {
this.parentPanel = parentPanel;
initComponents();
distributionComboBox.setRenderer(new DistributionListCellRenderer());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.JLabel versionLabel = new javax.swing.JLabel();
versions = new javax.swing.JSlider();
javax.swing.JLabel distributionLabel = new javax.swing.JLabel();
distributionComboBox = new javax.swing.JComboBox<>();
pkgLabel = new javax.swing.JLabel();
pkgInfo = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(versionLabel, org.openide.util.NbBundle.getMessage(QuickPanel.class, "QuickPanel.versionLabel.text")); // NOI18N
versions.setMinorTickSpacing(1);
versions.setPaintLabels(true);
versions.setPaintTicks(true);
versions.setSnapToTicks(true);
versions.setInverted(true);
versions.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
versionsStateChanged(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(distributionLabel, org.openide.util.NbBundle.getMessage(QuickPanel.class, "QuickPanel.distributionLabel.text")); // NOI18N
distributionComboBox.setModel(createDistrosModel());
distributionComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
distributionComboBoxActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(pkgLabel, org.openide.util.NbBundle.getMessage(QuickPanel.class, "QuickPanel.pkgLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(pkgInfo, "<PKG_INFO>"); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(versionLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(versions, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(distributionLabel)
.addComponent(pkgLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pkgInfo)
.addComponent(distributionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(23, 23, 23)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(versionLabel)
.addComponent(versions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(distributionLabel)
.addComponent(distributionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(pkgLabel)
.addComponent(pkgInfo))
.addContainerGap(102, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void distributionComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_distributionComboBoxActionPerformed
updatePackage();
}//GEN-LAST:event_distributionComboBoxActionPerformed
private void versionsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_versionsStateChanged
if (!versions.getValueIsAdjusting()) {
updatePackage();
}
}//GEN-LAST:event_versionsStateChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox<Distribution> distributionComboBox;
private javax.swing.JLabel pkgInfo;
private javax.swing.JLabel pkgLabel;
private javax.swing.JSlider versions;
// End of variables declaration//GEN-END:variables
private ComboBoxModel<Distribution> createDistrosModel() {
return distrosModel;
}
public void updateDistributions(List<Distribution> distributions, Distribution defaultDist) {
ignoreChanges = true;
distrosModel.removeAllElements();
distributions.stream()
.sorted(Comparator.comparing(Distribution::getUiString))
.forEachOrdered(distrosModel::addElement);
distributionComboBox.setSelectedItem(defaultDist);
ignoreChanges = false;
}
//The `versions` slider holds *the index* in versionsJDKs and
//this model holds the actual JDKs and the mapping between
static class VersionsModel {
private final List<Integer> versionJDKs;
private final Map<Integer, TermOfSupport> lts;
private final int currentJdk;
private VersionsModel(List<Integer> jdks, Map<Integer, TermOfSupport> lts, int currentJdk) {
this.versionJDKs = new ArrayList<>(jdks);
//quick panel shows only maintained JDKs
versionJDKs.removeIf(v -> !lts.containsKey(v));
versionJDKs.removeIf(v -> v < 8 || v > currentJdk);
this.lts = lts;
this.currentJdk = currentJdk;
}
public int getMinimum() {
return 0;
}
public int getMaximum() {
return versionJDKs.size() - 1;
}
public int getDefaultValue() {
return versionJDKs.indexOf(LTSes.latest(lts));
}
@UIEffect
@NonNull
public Hashtable<Integer, JLabel> createLabels() {
Hashtable<Integer, JLabel> labels = new Hashtable<>();
for (Integer v : versionJDKs) {
boolean isLTS = lts.get(v) == TermOfSupport.LTS;
JLabel label = new JLabel();
StringJoiner info = new StringJoiner(", ", " (", ")");
info.setEmptyValue("");
if (v == currentJdk) {
info.add("latest");
}
if (isLTS) {
info.add("LTS");
//these decorations do nothing on macOS...
Font font = label.getFont();
label.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
label.setToolTipText("Long Term Support");
}
label.setText(v.toString() + info.toString());
labels.put(versionJDKs.indexOf(v), label);
}
return labels;
}
private int getJDK(int index) {
return versionJDKs.get(index);
}
private int indexOf(int version) {
return versionJDKs.indexOf(version);
}
}
@MonotonicNonNull
private VersionsModel versionsModel;
void setVersions(List<Integer> jdks, Map<Integer, TermOfSupport> lts, int current) {
ignoreChanges = true;
versionsModel = new VersionsModel(jdks, lts, current);
versions.setMaximum(versionsModel.getMaximum());
versions.setMinimum(versionsModel.getMinimum());
versions.setLabelTable(versionsModel.createLabels());
versions.setValue(versionsModel.getDefaultValue());
ignoreChanges = false;
}
void initFocus() {
versions.requestFocusInWindow();
updatePackage();
}
void switchFocus(Distribution distribution, Integer version) {
ignoreChanges = true;
if (distribution != null) {
distributionComboBox.setSelectedItem(distribution);
}
if (version != null) {
int versionIdx = versionsModel.indexOf(version);
if (versionIdx >= 0) {
versions.setValue(versionIdx);
}
}
ignoreChanges = false;
initFocus();
}
Distribution getSelectedDistribution() {
return (Distribution) distributionComboBox.getSelectedItem();
}
Integer getSelectedVersion() {
return versionsModel.getJDK(versions.getValue());
}
Pkg getSelectedPackage() {
return pkg;
}
private void updatePackage() {
if (ignoreChanges) {
return;
}
pkg = null;
parentPanel.fireValidityChange();
pkgInfo.setText(Bundle.QuickPanel_searching());
Distribution distribution = (Distribution) distributionComboBox.getSelectedItem();
VersionNumber version = new VersionNumber(versionsModel.getJDK(versions.getValue()));
OperatingSystem operatingSystem = OS.getOperatingSystem();
Architecture architecture = OS.getArchitecture();
SwingWorker2.submit(() -> {
List<Pkg> pkgs = Client.getInstance().getPkgs(distribution,
version,
Latest.AVAILABLE,
operatingSystem,
architecture,
ArchiveType.NONE,
PackageType.JDK,
false,
false);
return pkgs.stream()
.filter(p -> validatePackage(operatingSystem, p))
.findFirst();
}).then(p -> {
if (p.isPresent()) {
pkg = p.get();
pkgInfo.setText(pkg.getFileName());
} else {
pkg = null;
pkgInfo.setText(Bundle.QuickPanel_error());
}
parentPanel.fireValidityChange();
}).handle(ex -> {
Exceptions.printStackTrace(ex);
pkg = null;
pkgInfo.setText(Bundle.QuickPanel_error());
}).execute();
}
private boolean validatePackage(OperatingSystem os, Pkg p) {
switch (os) {
case MACOS:
return ArchiveType.ZIP == p.getArchiveType() || ArchiveType.TAR_GZ == p.getArchiveType();
case LINUX:
return (ArchiveType.ZIP == p.getArchiveType() || ArchiveType.TAR_GZ == p.getArchiveType())
&& (LibCType.MUSL != p.getLibCType());
case WINDOWS:
default:
return ArchiveType.ZIP == p.getArchiveType();
}
}
}