/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed 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 com.intellij.ide.plugins;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.ui.BooleanTableCellEditor;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.ui.JBColor;
import com.intellij.util.Function;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: stathik
* Date: Dec 26, 2003
* Time: 3:51:58 PM
* To change this template use Options | File Templates.
*/
public class InstalledPluginsTableModel extends PluginTableModel {
public static Map<PluginId, Integer> NewVersions2Plugins = new HashMap<PluginId, Integer>();
public static Set<PluginId> updatedPlugins = new HashSet<PluginId>();
private final Map<PluginId, Boolean> myEnabled = new HashMap<PluginId, Boolean>();
private final Map<PluginId, Set<PluginId>> myDependentToRequiredListMap = new HashMap<PluginId, Set<PluginId>>();
private static final String ENABLED_DISABLED = "All plugins";
private static final String ENABLED = "Enabled plugins";
private static final String DISABLED = "Disabled plugins";
public static final String[] ENABLED_VALUES = new String[]{ENABLED_DISABLED, ENABLED, DISABLED};
private String myEnabledFilter = ENABLED_DISABLED;
private static final Set<IdeaPluginDescriptor> myInstalled = new HashSet<IdeaPluginDescriptor>();
public InstalledPluginsTableModel() {
super.columns = new ColumnInfo[]{new MyPluginManagerColumnInfo(), new EnabledPluginInfo()};
view = new ArrayList<IdeaPluginDescriptor>(Arrays.asList(PluginManager.getPlugins()));
view.addAll(myInstalled);
reset(view);
for (Iterator<IdeaPluginDescriptor> iterator = view.iterator(); iterator.hasNext(); ) {
@NonNls final String s = iterator.next().getPluginId().getIdString();
if (PluginManagerCore.CORE_PLUGIN_ID.equals(s)) iterator.remove();
}
setSortKey(new RowSorter.SortKey(getNameColumn(), SortOrder.ASCENDING));
}
public boolean appendOrUpdateDescriptor(IdeaPluginDescriptor descriptor) {
final PluginId descrId = descriptor.getPluginId();
final IdeaPluginDescriptor existing = PluginManager.getPlugin(descrId);
if (existing != null) {
updateExistingPlugin(descriptor, existing);
return true;
}
else if (!myInstalled.contains(descriptor)) {
myInstalled.add(descriptor);
view.add(descriptor);
setEnabled(descriptor, true);
fireTableDataChanged();
return true;
}
return false;
}
public static void updateExistingPlugin(IdeaPluginDescriptor descriptor, @Nullable IdeaPluginDescriptor existing) {
if (existing != null) {
updateExistingPluginInfo(descriptor, existing);
updatedPlugins.add(existing.getPluginId());
}
}
public static int getCheckboxColumn() {
return 1;
}
@Override
public int getNameColumn() {
return 0;
}
private void reset(final List<IdeaPluginDescriptor> list) {
for (IdeaPluginDescriptor ideaPluginDescriptor : list) {
setEnabled(ideaPluginDescriptor);
}
updatePluginDependencies();
}
private void setEnabled(IdeaPluginDescriptor ideaPluginDescriptor) {
setEnabled(ideaPluginDescriptor, ideaPluginDescriptor.isEnabled());
}
private void setEnabled(IdeaPluginDescriptor ideaPluginDescriptor, final boolean enabled) {
final Collection<String> disabledPlugins = PluginManager.getDisabledPlugins();
final PluginId pluginId = ideaPluginDescriptor.getPluginId();
if (!enabled && !disabledPlugins.contains(pluginId.toString())) {
myEnabled.put(pluginId, null);
}
else {
myEnabled.put(pluginId, enabled);
}
}
public Map<PluginId, Set<PluginId>> getDependentToRequiredListMap() {
return myDependentToRequiredListMap;
}
protected void updatePluginDependencies() {
myDependentToRequiredListMap.clear();
final int rowCount = getRowCount();
for (int i = 0; i < rowCount; i++) {
final IdeaPluginDescriptor descriptor = getObjectAt(i);
final PluginId pluginId = descriptor.getPluginId();
myDependentToRequiredListMap.remove(pluginId);
if (descriptor instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)descriptor).isDeleted()) continue;
final Boolean enabled = myEnabled.get(pluginId);
if (enabled == null || enabled.booleanValue()) {
PluginManager.checkDependants(descriptor, new Function<PluginId, IdeaPluginDescriptor>() {
@Override
@Nullable
public IdeaPluginDescriptor fun(final PluginId pluginId) {
return PluginManager.getPlugin(pluginId);
}
}, new Condition<PluginId>() {
@Override
public boolean value(final PluginId dependantPluginId) {
final Boolean enabled = myEnabled.get(dependantPluginId);
if ((enabled == null && !updatedPlugins.contains(dependantPluginId)) ||
(enabled != null && !enabled.booleanValue())) {
Set<PluginId> required = myDependentToRequiredListMap.get(pluginId);
if (required == null) {
required = new HashSet<PluginId>();
myDependentToRequiredListMap.put(pluginId, required);
}
required.add(dependantPluginId);
//return false;
}
return true;
}
}
);
if (enabled == null && !myDependentToRequiredListMap.containsKey(pluginId) && !PluginManager.isIncompatible(descriptor)) {
myEnabled.put(pluginId, true);
}
}
}
}
@Override
public void updatePluginsList(List<IdeaPluginDescriptor> list) {
// For each downloadable plugin we need to know whether its counterpart
// is already installed, and if yes compare the difference in versions:
// availability of newer versions will be indicated separately.
for (IdeaPluginDescriptor descr : list) {
PluginId descrId = descr.getPluginId();
IdeaPluginDescriptor existing = PluginManager.getPlugin(descrId);
if (existing != null) {
if (descr instanceof PluginNode) {
updateExistingPluginInfo(descr, existing);
}
else {
view.add(descr);
setEnabled(descr);
}
}
}
for (IdeaPluginDescriptor descriptor : myInstalled) {
if (!view.contains(descriptor)) {
view.add(descriptor);
}
}
fireTableDataChanged();
}
@Override
protected ArrayList<IdeaPluginDescriptor> toProcess() {
ArrayList<IdeaPluginDescriptor> toProcess = super.toProcess();
for (IdeaPluginDescriptor descriptor : myInstalled) {
if (!toProcess.contains(descriptor)) {
toProcess.add(descriptor);
}
}
return toProcess;
}
@Override
public void filter(final List<IdeaPluginDescriptor> filtered) {
view.clear();
for (IdeaPluginDescriptor descriptor : filtered) {
view.add(descriptor);
}
super.filter(filtered);
}
private static void updateExistingPluginInfo(IdeaPluginDescriptor descr, IdeaPluginDescriptor existing) {
int state = StringUtil.compareVersionNumbers(descr.getVersion(), existing.getVersion());
final PluginId pluginId = existing.getPluginId();
final String idString = pluginId.getIdString();
final JDOMExternalizableStringList installedPlugins = PluginManagerUISettings.getInstance().getInstalledPlugins();
if (!installedPlugins.contains(idString) && !((IdeaPluginDescriptorImpl)existing).isDeleted()) {
installedPlugins.add(idString);
}
final PluginManagerUISettings updateSettings = PluginManagerUISettings.getInstance();
if (state > 0 && !PluginManager.isIncompatible(descr) && !updatedPlugins.contains(descr.getPluginId())) {
NewVersions2Plugins.put(pluginId, 1);
if (!updateSettings.myOutdatedPlugins.contains(idString)) {
updateSettings.myOutdatedPlugins.add(idString);
}
final IdeaPluginDescriptorImpl plugin = (IdeaPluginDescriptorImpl)existing;
plugin.setDownloadsCount(descr.getDownloads());
plugin.setVendor(descr.getVendor());
plugin.setVendorEmail(descr.getVendorEmail());
plugin.setVendorUrl(descr.getVendorUrl());
plugin.setUrl(descr.getUrl());
}
else {
updateSettings.myOutdatedPlugins.remove(idString);
if (NewVersions2Plugins.remove(pluginId) != null) {
updatedPlugins.add(pluginId);
}
}
}
public void enableRows(IdeaPluginDescriptor[] ideaPluginDescriptors, Boolean value) {
for (IdeaPluginDescriptor ideaPluginDescriptor : ideaPluginDescriptors) {
final PluginId currentPluginId = ideaPluginDescriptor.getPluginId();
final Boolean enabled = myEnabled.get(currentPluginId) == null ? Boolean.FALSE : value;
myEnabled.put(currentPluginId, enabled);
}
updatePluginDependencies();
warnAboutMissedDependencies(value, ideaPluginDescriptors);
hideNotApplicablePlugins(value, ideaPluginDescriptors);
}
private void hideNotApplicablePlugins(Boolean value, final IdeaPluginDescriptor... ideaPluginDescriptors) {
if (!value && ENABLED.equals(myEnabledFilter) || (value && DISABLED.equals(myEnabledFilter))) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (IdeaPluginDescriptor ideaPluginDescriptor : ideaPluginDescriptors) {
view.remove(ideaPluginDescriptor);
filtered.add(ideaPluginDescriptor);
}
fireTableDataChanged();
}
});
}
}
public static boolean hasNewerVersion(PluginId descr) {
return !wasUpdated(descr) &&
(NewVersions2Plugins.containsKey(descr) || PluginManagerUISettings.getInstance().myOutdatedPlugins.contains(descr.getIdString()));
}
public static boolean wasUpdated(PluginId descr) {
return updatedPlugins.contains(descr);
}
public boolean isEnabled(final PluginId pluginId) {
final Boolean enabled = myEnabled.get(pluginId);
return enabled != null && enabled.booleanValue();
}
public boolean isDisabled(final PluginId pluginId) {
final Boolean enabled = myEnabled.get(pluginId);
return enabled != null && !enabled.booleanValue();
}
public Map<PluginId, Boolean> getEnabledMap() {
return myEnabled;
}
public String getEnabledFilter() {
return myEnabledFilter;
}
public void setEnabledFilter(String enabledFilter, String filter) {
myEnabledFilter = enabledFilter;
filter(filter);
}
@Override
public boolean isPluginDescriptorAccepted(IdeaPluginDescriptor descriptor) {
if (!myEnabledFilter.equals(ENABLED_DISABLED)) {
final boolean enabled = isEnabled(descriptor.getPluginId());
if (enabled && myEnabledFilter.equals(DISABLED)) return false;
if (!enabled && myEnabledFilter.equals(ENABLED)) return false;
}
return true;
}
private class EnabledPluginInfo extends ColumnInfo<IdeaPluginDescriptor, Boolean> {
public EnabledPluginInfo() {
super(/*IdeBundle.message("plugin.manager.enable.column.title")*/"");
}
@Override
public Boolean valueOf(IdeaPluginDescriptor ideaPluginDescriptor) {
return myEnabled.get(ideaPluginDescriptor.getPluginId());
}
@Override
public boolean isCellEditable(final IdeaPluginDescriptor ideaPluginDescriptor) {
return true;
}
@Override
public Class getColumnClass() {
return Boolean.class;
}
@Override
public TableCellEditor getEditor(final IdeaPluginDescriptor o) {
return new BooleanTableCellEditor();
}
@Override
public TableCellRenderer getRenderer(final IdeaPluginDescriptor ideaPluginDescriptor) {
return new BooleanTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return super.getTableCellRendererComponent(table, value == null ? Boolean.TRUE : value, isSelected, hasFocus, row, column);
}
};
}
@Override
public void setValue(final IdeaPluginDescriptor ideaPluginDescriptor, Boolean value) {
final PluginId currentPluginId = ideaPluginDescriptor.getPluginId();
final Boolean enabled = myEnabled.get(currentPluginId) == null ? Boolean.FALSE : value;
myEnabled.put(currentPluginId, enabled);
updatePluginDependencies();
warnAboutMissedDependencies(enabled, ideaPluginDescriptor);
hideNotApplicablePlugins(value, ideaPluginDescriptor);
}
@Override
public Comparator<IdeaPluginDescriptor> getComparator() {
return new Comparator<IdeaPluginDescriptor>() {
@Override
public int compare(final IdeaPluginDescriptor o1, final IdeaPluginDescriptor o2) {
final Boolean enabled1 = myEnabled.get(o1.getPluginId());
final Boolean enabled2 = myEnabled.get(o2.getPluginId());
if (enabled1 != null && enabled1.booleanValue()) {
if (enabled2 != null && enabled2.booleanValue()) {
return 0;
}
return 1;
}
else {
if (enabled2 == null || !enabled2.booleanValue()) {
return 0;
}
return -1;
}
}
};
}
@Override
public int getWidth(JTable table) {
return new JCheckBox().getPreferredSize().width;
}
}
private void warnAboutMissedDependencies(final Boolean newVal, final IdeaPluginDescriptor... ideaPluginDescriptors) {
final Set<PluginId> deps = new HashSet<PluginId>();
final List<IdeaPluginDescriptor> descriptorsToCheckDependencies = new ArrayList<IdeaPluginDescriptor>();
if (newVal) {
Collections.addAll(descriptorsToCheckDependencies, ideaPluginDescriptors);
}
else {
descriptorsToCheckDependencies.addAll(getAllPlugins());
descriptorsToCheckDependencies.removeAll(Arrays.asList(ideaPluginDescriptors));
for (Iterator<IdeaPluginDescriptor> iterator = descriptorsToCheckDependencies.iterator(); iterator.hasNext(); ) {
IdeaPluginDescriptor descriptor = iterator.next();
final Boolean enabled = myEnabled.get(descriptor.getPluginId());
if (enabled == null || !enabled.booleanValue()) {
iterator.remove();
}
}
}
for (final IdeaPluginDescriptor ideaPluginDescriptor : descriptorsToCheckDependencies) {
PluginManager.checkDependants(ideaPluginDescriptor, new Function<PluginId, IdeaPluginDescriptor>() {
@Override
@Nullable
public IdeaPluginDescriptor fun(final PluginId pluginId) {
return PluginManager.getPlugin(pluginId);
}
}, new Condition<PluginId>() {
@Override
public boolean value(final PluginId pluginId) {
Boolean enabled = myEnabled.get(pluginId);
if (enabled == null) {
return false;
}
if (newVal && !enabled.booleanValue()) {
deps.add(pluginId);
}
if (!newVal) {
if (ideaPluginDescriptor instanceof IdeaPluginDescriptorImpl &&
((IdeaPluginDescriptorImpl)ideaPluginDescriptor).isDeleted()) {
return true;
}
final PluginId pluginDescriptorId = ideaPluginDescriptor.getPluginId();
for (IdeaPluginDescriptor descriptor : ideaPluginDescriptors) {
if (pluginId.equals(descriptor.getPluginId())) {
deps.add(pluginDescriptorId);
break;
}
}
}
return true;
}
}
);
}
if (!deps.isEmpty()) {
final String listOfSelectedPlugins = StringUtil.join(ideaPluginDescriptors, new Function<IdeaPluginDescriptor, String>() {
@Override
public String fun(IdeaPluginDescriptor pluginDescriptor) {
return pluginDescriptor.getName();
}
}, ", ");
final Set<IdeaPluginDescriptor> pluginDependencies = new HashSet<IdeaPluginDescriptor>();
final String listOfDependencies = StringUtil.join(deps, new Function<PluginId, String>() {
@Override
public String fun(final PluginId pluginId) {
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(pluginId);
assert pluginDescriptor != null;
pluginDependencies.add(pluginDescriptor);
return pluginDescriptor.getName();
}
}, "<br>");
final String message = !newVal
? "<html>The following plugins <br>" +
listOfDependencies +
"<br>are enabled and depend" +
(deps.size() == 1 ? "s" : "") +
" on selected plugins. " +
"<br>Would you like to disable them too?</html>"
: "<html>The following plugins on which " + listOfSelectedPlugins + " depend" + (ideaPluginDescriptors.length == 1 ? "s" : "") +
" are disabled:<br>" + listOfDependencies + "<br>Would you like to enable them?</html>";
if (Messages.showOkCancelDialog(message, newVal ? "Enable Dependant Plugins" : "Disable Plugins with Dependency on this", Messages.getQuestionIcon()) ==
Messages.OK) {
for (PluginId pluginId : deps) {
myEnabled.put(pluginId, newVal);
}
updatePluginDependencies();
hideNotApplicablePlugins(newVal, pluginDependencies.toArray(new IdeaPluginDescriptor[pluginDependencies.size()]));
}
}
}
private class InstalledPluginsTableRenderer extends DefaultTableCellRenderer {
private JLabel myNameLabel = new JLabel();
private JLabel myBundledLabel = new JLabel();
private JPanel myPanel = new JPanel(new BorderLayout());
private final IdeaPluginDescriptor myPluginDescriptor;
public InstalledPluginsTableRenderer(IdeaPluginDescriptor pluginDescriptor) {
myPluginDescriptor = pluginDescriptor;
myNameLabel.setFont(PluginManagerColumnInfo.getNameFont());
myBundledLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
myPanel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 1));
myNameLabel.setOpaque(true);
myPanel.add(myNameLabel, BorderLayout.WEST);
myPanel.add(myBundledLabel, BorderLayout.EAST);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final Component orig = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (myPluginDescriptor != null) {
myNameLabel.setText(myPluginDescriptor.getName());
final PluginId pluginId = myPluginDescriptor.getPluginId();
final String idString = pluginId.getIdString();
if (myPluginDescriptor.isBundled()) {
myBundledLabel.setText("Bundled");
}
else {
if (PluginManagerUISettings.getInstance().getInstalledPlugins().contains(idString)) {
myBundledLabel.setText("From repository");
}
else {
myBundledLabel.setText("Custom");
}
}
if (myPluginDescriptor instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)myPluginDescriptor).isDeleted()) {
myNameLabel.setIcon(AllIcons.Actions.Clean);
}
else if (hasNewerVersion(pluginId)) {
myNameLabel.setIcon(AllIcons.Nodes.Pluginobsolete);
myPanel.setToolTipText("Newer version of the plugin is available");
}
else {
myNameLabel.setIcon(AllIcons.Nodes.Plugin);
}
final Color fg = orig.getForeground();
final Color bg = orig.getBackground();
final Color grayedFg = isSelected ? fg : Color.GRAY;
myPanel.setBackground(bg);
myNameLabel.setBackground(bg);
myBundledLabel.setBackground(bg);
myNameLabel.setForeground(fg);
final boolean wasUpdated = wasUpdated(pluginId);
if (wasUpdated || PluginManager.getPlugin(pluginId) == null) {
if (!isSelected) {
myNameLabel.setForeground(FileStatus.COLOR_ADDED);
}
if (wasUpdated) {
myPanel.setToolTipText("Plugin was updated to the newest version. Changes will be available after restart");
}
else {
myPanel.setToolTipText("Plugin will be activated after restart.");
}
}
myBundledLabel.setForeground(grayedFg);
final Set<PluginId> required = myDependentToRequiredListMap.get(pluginId);
if (required != null && required.size() > 0) {
myNameLabel.setForeground(JBColor.RED);
final StringBuilder s = new StringBuilder();
if (myEnabled.get(pluginId) == null) {
s.append("Plugin was not loaded.\n");
}
if (required.contains(PluginId.getId("com.intellij.modules.ultimate"))) {
s.append("The plugin requires IntelliJ IDEA Ultimate");
}
else {
s.append("Required plugin").append(required.size() == 1 ? " \"" : "s \"");
s.append(StringUtil.join(required, new Function<PluginId, String>() {
@Override
public String fun(final PluginId id) {
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id);
return plugin == null ? id.getIdString() : plugin.getName();
}
}, ","));
s.append(required.size() == 1 ? "\" is not enabled." : "\" are not enabled.");
}
myPanel.setToolTipText(s.toString());
}
if (PluginManager.isIncompatible(myPluginDescriptor)) {
myPanel.setToolTipText(IdeBundle.message("plugin.manager.incompatible.tooltip.warning", ApplicationNamesInfo.getInstance().getFullProductName()));
myNameLabel.setForeground(JBColor.RED);
}
}
return myPanel;
}
}
private class MyPluginManagerColumnInfo extends PluginManagerColumnInfo {
public MyPluginManagerColumnInfo() {
super(PluginManagerColumnInfo.COLUMN_NAME, InstalledPluginsTableModel.this);
}
@Override
public TableCellRenderer getRenderer(final IdeaPluginDescriptor pluginDescriptor) {
return new PluginsTableRenderer(pluginDescriptor, false);
}
@Override
protected boolean isSortByName() {
return true;
}
@Override
public Comparator<IdeaPluginDescriptor> getComparator() {
final Comparator<IdeaPluginDescriptor> comparator = super.getColumnComparator();
return new Comparator<IdeaPluginDescriptor>() {
@Override
public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) {
if (isSortByStatus()) {
final boolean incompatible1 = PluginManager.isIncompatible(o1);
final boolean incompatible2 = PluginManager.isIncompatible(o2);
if (incompatible1) {
if (incompatible2) return comparator.compare(o1, o2);
return -1;
}
if (incompatible2) return 1;
final boolean hasNewerVersion1 = hasNewerVersion(o1.getPluginId());
final boolean hasNewerVersion2 = hasNewerVersion(o2.getPluginId());
if (hasNewerVersion1) {
if (hasNewerVersion2) return comparator.compare(o1, o2);
return -1;
}
if (hasNewerVersion2) return 1;
final boolean wasUpdated1 = wasUpdated(o1.getPluginId());
final boolean wasUpdated2 = wasUpdated(o2.getPluginId());
if (wasUpdated1) {
if (wasUpdated2) return comparator.compare(o1, o2);
return -1;
}
if (wasUpdated2) return 1;
if (o1 instanceof PluginNode) {
if (o2 instanceof PluginNode) return comparator.compare(o1, o2);
return -1;
}
if (o2 instanceof PluginNode) return 1;
final boolean deleted1 = o1 instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)o1).isDeleted();
final boolean deleted2 = o2 instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)o2).isDeleted();
if (deleted1) {
if (deleted2) return comparator.compare(o1, o2);
return -1;
}
if (deleted2) return 1;
final boolean enabled1 = isEnabled(o1.getPluginId());
final boolean enabled2 = isEnabled(o2.getPluginId());
if (enabled1 && !enabled2) return -1;
if (enabled2 && !enabled1) return 1;
}
return comparator.compare(o1, o2);
}
};
}
@Override
public int getWidth(JTable table) {
return super.getWidth(table);
}
}
}