blob: f7a998fc70feebdcdc09dbc1469326c7fa22cd17 [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.project.ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.java.queries.SourceLevelQuery.Profile;
import org.openide.util.NbBundle;
/**
*
* @author Tomas Zezula
*/
class FixProfile extends javax.swing.JPanel {
private final JButton okOption;
private final LibsModel libsModel;
private Profile reqProfile;
/**
* Creates new form FixProfile
*/
FixProfile(
@NonNull final JButton okOption,
@NonNull final Profile currentProfile,
@NonNull final Collection<? extends ProfileProblemsProviderImpl.Reference> state) {
assert okOption != null;
assert currentProfile != null;
assert state != null;
this.okOption = okOption;
this.libsModel = new LibsModel (currentProfile, state);
libsModel.addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent lde) {
checkOkOption();
}
@Override
public void intervalRemoved(ListDataEvent lde) {
checkOkOption();
}
@Override
public void contentsChanged(ListDataEvent lde) {
checkOkOption();
}
});
this.reqProfile = ProfileProblemsProviderImpl.requiredProfile(state, currentProfile);
initComponents();
remove.setEnabled(false);
brokenLibs.setModel(libsModel);
brokenLibs.setCellRenderer(new LibsRenderer(brokenLibs));
brokenLibs.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
brokenLibs.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent lse) {
remove.setEnabled(brokenLibs.getSelectedIndex() != -1);
}
});
brokenLibs.setSelectedIndex(0);
profiles.setRenderer(new ProfilesRenderer());
changeProfile.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
libsModel.updateProfile(changeProfile.isSelected());
checkOkOption();
}
});
updateProfiles();
checkOkOption();
}
boolean shouldUpdateProfile() {
return changeProfile.isSelected();
}
@CheckForNull
Profile getProfile() {
final Object selObj = profiles.getSelectedItem();
if (selObj instanceof Profile) {
return (Profile) selObj;
} else {
return null;
}
}
@NonNull
Collection<? extends ProfileProblemsProviderImpl.Reference> getRootsToRemove() {
return libsModel.getRemovedRooots();
}
private void updateProfiles() {
profiles.removeAllItems();
for (Profile profile : Profile.values()) {
if (profile.compareTo(reqProfile) >= 0) {
profiles.addItem(profile);
}
}
profiles.setSelectedItem(reqProfile);
}
private void checkOkOption() {
okOption.setEnabled(libsModel.getSize() == 0);
}
private static final class ProfilesRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(
@NonNull final JList jlist,
@NullAllowed Object o,
final int i,
final boolean bln,
final boolean bln1) {
if (o instanceof Profile) {
o = ((Profile)o).getDisplayName();
}
return super.getListCellRendererComponent(jlist, o, i, bln, bln1);
}
}
private static final class LibsRenderer extends DefaultListCellRenderer {
private static final int LIGHTER_COLOR_COMPONENT = 80;
private final JLabel root;
private final JLabel profile;
private final JPanel container;
private Color fgColor;
private Color fgColorLighter;
private Color bgColor;
private Color bgSelectionColor;
private Color fgSelectionColor;
LibsRenderer(@NonNull final JList list) {
this.root = new JLabel();
this.root.setHorizontalAlignment(LEFT);
this.root.setOpaque(false);
this.root.setFont(list.getFont());
this.profile = new JLabel();
this.profile.setHorizontalAlignment(RIGHT);
this.profile.setOpaque(false);
this.profile.setFont(list.getFont());
this.container = new JPanel();
this.container.setLayout(new BorderLayout());
this.container.add (this.root, BorderLayout.WEST);
this.container.add (this.profile, BorderLayout.EAST);
fgColor = list.getForeground();
fgColorLighter = new Color(
Math.min(255, fgColor.getRed() + LIGHTER_COLOR_COMPONENT),
Math.min(255, fgColor.getGreen() + LIGHTER_COLOR_COMPONENT),
Math.min(255, fgColor.getBlue() + LIGHTER_COLOR_COMPONENT));
bgColor = new Color(list.getBackground().getRGB());
bgSelectionColor = list.getSelectionBackground();
fgSelectionColor = list.getSelectionForeground();
}
@NbBundle.Messages({
"FMT_RootWithProfile={0} ({1})",
"MSG_InvalidProfile=<Invalid>"
})
@Override
public Component getListCellRendererComponent(
@NonNull final JList jlist,
@NullAllowed Object o,
final int i,
final boolean isSelected,
final boolean hasFocus) {
if (isSelected) {
root.setForeground(fgSelectionColor);
profile.setForeground(fgSelectionColor);
container.setBackground(bgSelectionColor);
} else {
root.setForeground(fgColor);
profile.setForeground(fgColorLighter);
container.setBackground(bgColor);
}
if (o instanceof ProfileProblemsProviderImpl.Reference) {
final ProfileProblemsProviderImpl.Reference e = (ProfileProblemsProviderImpl.Reference) o;
root.setText(e.getDisplayName());
root.setIcon(e.getIcon());
final Profile requiredProfile = e.getRequiredProfile();
if (requiredProfile == null) {
profile.setText(String.format(
"<html><font color=\"#A40000\">%s", //NOI18N
Bundle.MSG_InvalidProfile()));
} else {
profile.setText(requiredProfile.getDisplayName());
}
container.setToolTipText(e.getToolTipText());
} else {
root.setText(""); //NOI18N
root.setIcon(null);
profile.setText(""); //NOI18N
container.setToolTipText(null);
}
return container;
}
}
private static final class LibsModel extends AbstractListModel {
private final Profile currentProfile;
private final Collection<? extends ProfileProblemsProviderImpl.Reference> state;
private final Set<ProfileProblemsProviderImpl.Reference> toRemove;
private final List<ProfileProblemsProviderImpl.Reference> data;
private boolean updated;
LibsModel(
@NonNull final Profile currentProfile,
@NonNull Collection<? extends ProfileProblemsProviderImpl.Reference> state) {
this.currentProfile = currentProfile;
this.state = state;
this.toRemove = new HashSet<ProfileProblemsProviderImpl.Reference>();
this.data = new ArrayList<ProfileProblemsProviderImpl.Reference>();
refresh();
}
@Override
public int getSize() {
return data.size();
}
@Override
public Object getElementAt(int i) {
if (i<0 || i>=data.size()) {
throw new IndexOutOfBoundsException(
String.format(
"Index: %d, Size: %d", //NOI18N
i,
data.size()));
}
return data.get(i);
}
void removeRoots(@NonNull final Collection<? extends ProfileProblemsProviderImpl.Reference> roots) {
final int oldSize = getSize();
toRemove.addAll(roots);
refresh();
final int newSize = getSize();
fireContentsChanged(this, 0, Math.max(oldSize, newSize));
};
@NonNull
Profile requiredProfile() {
return ProfileProblemsProviderImpl.requiredProfile(data, currentProfile);
}
void updateProfile(final boolean update) {
final int oldSize = getSize();
updated = update;
refresh();
final int newSize = getSize();
fireContentsChanged(this, 0, Math.max(oldSize, newSize));
}
@NonNull
Collection<? extends ProfileProblemsProviderImpl.Reference> getRemovedRooots() {
return Collections.unmodifiableCollection(toRemove);
}
private void refresh() {
data.clear();
for (ProfileProblemsProviderImpl.Reference ref : state) {
if (!toRemove.contains(ref) &&
!(updated && ref.getRequiredProfile() != null)) {
data.add(ref);
}
}
}
}
/**
* 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() {
jLabel1 = new javax.swing.JLabel();
remove = new javax.swing.JButton();
changeProfile = new javax.swing.JCheckBox();
profiles = new javax.swing.JComboBox();
jScrollPane1 = new javax.swing.JScrollPane();
brokenLibs = new javax.swing.JList();
jLabel1.setLabelFor(brokenLibs);
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_BrokenLibs")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(remove, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_remove")); // NOI18N
remove.setToolTipText(org.openide.util.NbBundle.getMessage(FixProfile.class, "TIP_FixProfile_Remove")); // NOI18N
remove.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeLibrary(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(changeProfile, org.openide.util.NbBundle.getMessage(FixProfile.class, "LBL_FixProfile_changeProfile")); // NOI18N
jScrollPane1.setViewportView(brokenLibs);
brokenLibs.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_BrokenLibs")); // 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(jLabel1)
.addGap(0, 202, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(changeProfile)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(profiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(jScrollPane1))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(remove)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(remove)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 212, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(changeProfile)
.addComponent(profiles, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
jLabel1.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(FixProfile.class, "FixProfile.jLabel1.AccessibleContext.accessibleName")); // NOI18N
changeProfile.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_changeProfile")); // NOI18N
profiles.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(FixProfile.class, "AN_FixProfile_Profiles")); // NOI18N
profiles.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(FixProfile.class, "AD_FixProfile_Profiles")); // NOI18N
}// </editor-fold>//GEN-END:initComponents
private void removeLibrary(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeLibrary
final Object[] selection = brokenLibs.getSelectedValues();
final Set<ProfileProblemsProviderImpl.Reference> rootsToRemove = new HashSet<ProfileProblemsProviderImpl.Reference>();
for (Object e : selection) {
rootsToRemove.add((ProfileProblemsProviderImpl.Reference)e);
}
libsModel.removeRoots(rootsToRemove);
if (libsModel.getSize() > 0) {
brokenLibs.setSelectedIndex(0);
}
reqProfile = libsModel.requiredProfile();
updateProfiles();
}//GEN-LAST:event_removeLibrary
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JList brokenLibs;
private javax.swing.JCheckBox changeProfile;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JComboBox profiles;
private javax.swing.JButton remove;
// End of variables declaration//GEN-END:variables
}