/*
 * 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.module.graph;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Collections;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.core.spi.multiview.CloseOperationState;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.MultiViewElementCallback;
import org.netbeans.modules.java.graph.DependencyGraphScene;
import org.netbeans.modules.java.graph.GraphEdge;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileChangeAdapter;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileRenameEvent;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.Parameters;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;
import org.openide.windows.TopComponent;

/**
 *
 * @author Tomas Zezula
 */
final class GraphTopComponent extends TopComponent implements MultiViewElement, Runnable {

    @StaticResource
    private static final String ZOOM_IN_ICON = "org/netbeans/modules/java/module/graph/resources/zoomin.gif";   //NOI18N
    @StaticResource
    private static final String ZOOM_OUT_ICON = "org/netbeans/modules/java/module/graph/resources/zoomout.gif";
    @StaticResource
    private static final String PUBLIC_ICON = "org/netbeans/modules/java/module/graph/resources/public.gif";

    private static final RequestProcessor RP = new RequestProcessor(GraphTopComponent.class);

    private final RequestProcessor.Task refreshTask = RP.create(this);
    private final JScrollPane pane = new JScrollPane();
    private final ChangeSupport changeSupport;
    private boolean alreadyShown;
    private boolean needsRefresh;
    private MultiViewElementCallback callback;
    private EditorToolbar toolbar;
    private DependencyGraphScene<ModuleNode> scene;

    private Collection<? extends DependencyEdge> edges;
    
    private Timer timer = new Timer(500, new ActionListener() {
        @Override public void actionPerformed(ActionEvent arg0) {
            checkFindValue();
        }
    });
        
    /**
     * Creates new form GraphTopComponent
     */
    GraphTopComponent(@NonNull final Lookup lkp) {
        Parameters.notNull("lkp", lkp); //NOI18N
        changeSupport = new ChangeSupport(
                lkp.lookup(FileObject.class),
                () -> needsRefresh = true);
        associateLookup(lkp);
        initComponents();
        if( "Aqua".equals(UIManager.getLookAndFeel().getID()) ) { //NOI18N
            setBackground(UIManager.getColor("NbExplorerView.background")); //NOI18N
        }
        txtFind.getDocument().addDocumentListener(new DocumentListener() {
            @Override public void insertUpdate(DocumentEvent arg0) {
                timer.restart();
            }

            @Override public void removeUpdate(DocumentEvent arg0) {
                timer.restart();
            }

            @Override public void changedUpdate(DocumentEvent arg0) {
                timer.restart();
            }
        });
        
        jdkComboBox.setModel(new DefaultComboBoxModel(JDKVisibility.values()));
        jdkComboBox.setRenderer(new JDKRenderer());
        
        timer.setDelay(500);
        timer.setRepeats(false);
    }

    @Override
    public JComponent getVisualRepresentation() {
        return this;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        if (toolbar == null) {
            toolbar = new EditorToolbar();
            toolbar.setFloatable(false);
            toolbar.setRollover(true);

            toolbar.addSeparator();
            Dimension space = new Dimension(3, 0);
            toolbar.add(zoomIn);
            toolbar.addSeparator(space);
            toolbar.add(zoomOut);
            toolbar.addSeparator(space);
            toolbar.add(lblFind);
            toolbar.add(txtFind);
            toolbar.addSeparator(space);
            toolbar.add(lblPath);
            toolbar.add(maxPathSpinner);
            toolbar.addSeparator();
            toolbar.add(jdkLabel);
            toolbar.add(jdkComboBox);
            toolbar.addSeparator(space);
            toolbar.add(transitiveCheckBox);
//            toolbar.addSeparator(space);
//            toolbar.add(lblScopes);
//            toolbar.add(comScopes);
        }
        return toolbar;
    }

    @Override
    public void componentOpened() {
        super.componentOpened();
        pane.setWheelScrollingEnabled(true);
        add(pane, BorderLayout.CENTER);
        alreadyShown = false;
        needsRefresh = true;
    }

    @Override
    public void componentActivated() {
        super.componentActivated();
        if (needsRefresh) {
            refreshModel();
            needsRefresh = false;
            alreadyShown = true;
        }
    }

    @Override
    public void componentClosed() {
        super.componentClosed();
    }

    @Override
    public void componentDeactivated() {
        super.componentDeactivated();
    }

    @Override
    public void componentHidden() {
        super.componentHidden();
    }

    @Override
    public void componentShowing() {
        super.componentShowing();
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback callback) {
        this.callback = callback;
    }

    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }

    public void run() {
        final FileObject moduleInfo = getLookup().lookup(FileObject.class);
        assert moduleInfo != null;
        final DependencyCalculator calc = new DependencyCalculator(moduleInfo);
        final Collection<? extends ModuleNode> nodes = calc.getNodes();
        final Collection<? extends DependencyEdge> edges = calc.getEdges();
        SwingUtilities.invokeLater(()->displayScene(nodes, edges));
    }

    @NonNull
    JScrollPane getScrollPane () {
        return pane;
    }

    /**
     * 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() {

        jComboBox1 = new javax.swing.JComboBox<>();
        jPanel1 = new javax.swing.JPanel();
        jToolBar1 = new javax.swing.JToolBar();
        zoomIn = new javax.swing.JButton();
        zoomOut = new javax.swing.JButton();
        lblFind = new javax.swing.JLabel();
        txtFind = new javax.swing.JTextField();
        lblPath = new javax.swing.JLabel();
        maxPathSpinner = new javax.swing.JSpinner();
        jdkLabel = new javax.swing.JLabel();
        jdkComboBox = new javax.swing.JComboBox<>();
        transitiveCheckBox = new javax.swing.JCheckBox();

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));

        setLayout(new java.awt.BorderLayout());

        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        zoomIn.setIcon(ImageUtilities.loadImageIcon(ZOOM_IN_ICON, true));
        org.openide.awt.Mnemonics.setLocalizedText(zoomIn, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.zoomIn.text")); // NOI18N
        zoomIn.setFocusable(false);
        zoomIn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        zoomIn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        zoomIn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                zoomIn(evt);
            }
        });
        jToolBar1.add(zoomIn);

        zoomOut.setIcon(ImageUtilities.loadImageIcon(ZOOM_OUT_ICON, true));
        org.openide.awt.Mnemonics.setLocalizedText(zoomOut, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.zoomOut.text")); // NOI18N
        zoomOut.setFocusable(false);
        zoomOut.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        zoomOut.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        zoomOut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                zoomOut(evt);
            }
        });
        jToolBar1.add(zoomOut);

        jPanel1.add(jToolBar1);

        org.openide.awt.Mnemonics.setLocalizedText(lblFind, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.lblFind.text")); // NOI18N
        jPanel1.add(lblFind);

        txtFind.setMaximumSize(new java.awt.Dimension(200, 22));
        txtFind.setMinimumSize(new java.awt.Dimension(50, 19));
        txtFind.setPreferredSize(new java.awt.Dimension(150, 22));
        txtFind.setFont(new Font("Arial", java.awt.Font.PLAIN, 11));
        jPanel1.add(txtFind);

        org.openide.awt.Mnemonics.setLocalizedText(lblPath, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.lblPath.text")); // NOI18N
        lblPath.setToolTipText(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.lblPath.toolTipText")); // NOI18N
        jPanel1.add(lblPath);

        maxPathSpinner.setModel(new javax.swing.SpinnerNumberModel(1, 1, 5, 1));
        maxPathSpinner.setToolTipText(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.maxPathSpinner.toolTipText")); // NOI18N
        maxPathSpinner.setMaximumSize(new java.awt.Dimension(60, 32767));
        maxPathSpinner.setRequestFocusEnabled(false);
        maxPathSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                maxPathSpinnerStateChanged(evt);
            }
        });
        jPanel1.add(maxPathSpinner);

        org.openide.awt.Mnemonics.setLocalizedText(jdkLabel, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.jdkLabel.text")); // NOI18N
        jdkLabel.setToolTipText(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.jdkLabel.toolTipText")); // NOI18N
        jPanel1.add(jdkLabel);

        jdkComboBox.setMaximumSize(new java.awt.Dimension(300, 32767));
        jdkComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jdkComboBoxItemStateChanged(evt);
            }
        });
        jPanel1.add(jdkComboBox);

        org.openide.awt.Mnemonics.setLocalizedText(transitiveCheckBox, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.transitiveCheckBox.text")); // NOI18N
        transitiveCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.transitiveCheckBox.toolTipText")); // NOI18N
        transitiveCheckBox.setIcon(ImageUtilities.loadImageIcon(PUBLIC_ICON, true));
        transitiveCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                transitiveCheckBoxActionPerformed(evt);
            }
        });
        jPanel1.add(transitiveCheckBox);

        add(jPanel1, java.awt.BorderLayout.NORTH);
    }// </editor-fold>//GEN-END:initComponents

    private void zoomIn(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomIn
        scene.setMyZoomFactor(scene.getZoomFactor() * 1.2);
        scene.validate();
        scene.repaint();
        if (pane.getHorizontalScrollBar().isVisible() ||
            pane.getVerticalScrollBar().isVisible()) {
            revalidate();
            repaint();
        }
    }//GEN-LAST:event_zoomIn

    private void zoomOut(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_zoomOut
        scene.setMyZoomFactor(scene.getZoomFactor() * 0.8);
        scene.validate();
        scene.repaint();
        if (!pane.getHorizontalScrollBar().isVisible() &&
            !pane.getVerticalScrollBar().isVisible()) {
            revalidate();
            repaint();
        }
    }//GEN-LAST:event_zoomOut

    private void maxPathSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_maxPathSpinnerStateChanged
        scene.highlightDepth(getSelectedDepth());
    }//GEN-LAST:event_maxPathSpinnerStateChanged

    private void jdkComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jdkComboBoxItemStateChanged
        if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED && scene != null) {                        
            scene.updateVisibility();
        }
    }//GEN-LAST:event_jdkComboBoxItemStateChanged

    private void transitiveCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_transitiveCheckBoxActionPerformed
        if (scene != null) {
            scene.updateVisibility();
        }     
    }//GEN-LAST:event_transitiveCheckBoxActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox<String> jComboBox1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JComboBox<String> jdkComboBox;
    private javax.swing.JLabel jdkLabel;
    private javax.swing.JLabel lblFind;
    private javax.swing.JLabel lblPath;
    private javax.swing.JSpinner maxPathSpinner;
    private javax.swing.JCheckBox transitiveCheckBox;
    private javax.swing.JTextField txtFind;
    private javax.swing.JButton zoomIn;
    private javax.swing.JButton zoomOut;
    // End of variables declaration//GEN-END:variables

    private void checkFindValue() {
        String val = txtFind.getText().trim();
        if ("".equals(val)) { //NOI18N
            val = null;
        }
        scene.setSearchString(val);
    }
    
    @NbBundle.Messages({
        "TXT_ComputingDependencies=Computing Dependencies...",
        "TXT_RefreshingDependencies=Refreshing Dependencies..."
    })
    private void refreshModel() {
        setPaneText(alreadyShown?
                Bundle.TXT_RefreshingDependencies() :
                Bundle.TXT_ComputingDependencies());
        enableControls(false);
        refreshTask.schedule(0);
    }

    private void enableControls(final boolean enable) {
        zoomIn.setEnabled(enable);
        zoomOut.setEnabled(enable);
    }

    private void setPaneText(@NonNull final String text)  {
        final JLabel lbl = new JLabel(text);
        lbl.setHorizontalAlignment(JLabel.CENTER);
        lbl.setVerticalAlignment(JLabel.CENTER);
        pane.setViewportView(lbl);
    }

    private static final BasicStroke TRANSITIVE_STROKE = new BasicStroke (1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, BasicStroke.JOIN_MITER, new float[] {5, 5}, 0);
    
    private void displayScene(
            @NonNull final Collection<? extends ModuleNode> nodes,
            @NonNull final Collection<? extends DependencyEdge> edges) 
    {
        
        this.edges = edges;
        
        DependencyGraphScene.PaintingProvider<ModuleNode> paintingProvider = new DependencyGraphScene.PaintingProvider<ModuleNode>() {
            @Override
            public boolean isVisible(ModuleNode node) {
                switch((JDKVisibility)jdkComboBox.getSelectedItem()) {
                    case ALL:
                        return true;
                    case DIRECT:
                        if(!node.isJdk()) {
                            return true;
                        } else {
                            Collection<GraphEdge<ModuleNode>> edges = scene.findNodeEdges(scene.getGraphNodeRepresentant(node), true, true);
                            return edges.stream().anyMatch(e -> !e.getSource().isJdk() && !getEdge(e.getSource(), e.getTarget()).isTrasitive());                            
                        }
                    case NONE:
                        return !node.isJdk();
                    default:
                        assert false;
                        return true;
                }
            }

            @Override
            public boolean isVisible(ModuleNode source, ModuleNode target) {
                DependencyEdge edge = getEdge(source, target);
                assert edge != null;
                if(edge.isTrasitive() && !transitiveCheckBox.isSelected()) {
                    return false;
                }
                switch((JDKVisibility)jdkComboBox.getSelectedItem()) {
                    case ALL:
                        return true;
                    case DIRECT:
                    case NONE:
                        return isVisible(source) && isVisible(target);
                    default:
                        assert false;
                        return true;
                }
            }
            
            @Override
            public Stroke getStroke(ModuleNode source, ModuleNode target) {
                if(!transitiveCheckBox.isSelected()) {
                    return null;
                }
                DependencyEdge edge = getEdge(source, target);
                assert edge != null;
                Stroke s = null;
                if(edge.isTrasitive()) { 
                    s = TRANSITIVE_STROKE;
                }
                return s;
            }            

            @Override
            public Icon getIcon(ModuleNode node) {
                return null;
            }

            @Override
            public Color getColor(ModuleNode node) {
                return null;
            }
        };                          
        
        scene = new DependencyGraphScene<>(null, GraphTopComponent.this::getSelectedDepth, null, paintingProvider);
        nodes.stream().forEach((n)-> {
            scene.addGraphNodeImpl(n);
        });
        edges.stream().forEach((e)-> scene.addEdge(e.getSource(), e.getTarget()));
        scene.calculatePrimaryPathsAndLevels();       
        JComponent sceneView = scene.getView();
        if (sceneView == null) {
            sceneView = scene.createView();
            // vlv: print
            sceneView.putClientProperty("print.printable", true); // NOI18N
        }
        pane.setViewportView(sceneView);
        scene.setSurroundingScrollPane(pane);
        scene.initialLayout();
        scene.setSelectedObjects(Collections.singleton(scene.getRootGraphNode()));
        if (scene.getMaxNodeDepth() > 1) {
            lblPath.setVisible(true);
            ((SpinnerNumberModel)maxPathSpinner.getModel()).
                    setMaximum(Integer.valueOf(scene.getMaxNodeDepth()));
            maxPathSpinner.setEnabled(true);
            maxPathSpinner.setVisible(true);
        }
        scene.highlightDepth(getSelectedDepth());
        enableControls(true);
    }

    private DependencyEdge getEdge(ModuleNode source, ModuleNode target) {
        // XXX suboptimal, though still extremely cheap                
        for (DependencyEdge edge : edges) {
            if(edge.getSource().equals(source) && edge.getTarget().equals(target)) {
                return edge;
            }
        }
        return null;
    }
                
    private static class EditorToolbar extends org.openide.awt.Toolbar {
        public EditorToolbar() {
            Border b = UIManager.getBorder("Nb.Editor.Toolbar.border"); //NOI18N
            setBorder(b);
            if( "Aqua".equals(UIManager.getLookAndFeel().getID()) ) { //NOI18N
                setBackground(UIManager.getColor("NbExplorerView.background")); //NOI18N
            }
        }

        @Override
        public String getUIClassID() {
            if( UIManager.get("Nb.Toolbar.ui") != null ) { //NOI18N
                return "Nb.Toolbar.ui"; //NOI18N
            }
            return super.getUIClassID();
        }

        @Override
        public String getName() {
            return "editorToolbar"; //NOI18N
        }
    }

    private int getSelectedDepth() {
        return ((SpinnerNumberModel)maxPathSpinner.getModel()).getNumber().intValue();
    }
    
    private static class ChangeSupport extends FileChangeAdapter implements PropertyChangeListener, DocumentListener {

        private final Runnable resetAction;
        private final FileObject file;
        private final EditorCookie.Observable ec;
        private Document currentDoc;

        ChangeSupport(
                @NonNull final FileObject file,
                @NonNull final Runnable resetAction) {
            Parameters.notNull("file", file);   //NOI18N
            Parameters.notNull("resetAction", resetAction); //NOI18N
            this.resetAction = resetAction;
            this.file = file;
            this.file.addFileChangeListener(WeakListeners.create(FileChangeListener.class, this, this.file));
            EditorCookie.Observable cookie = null;
            try {
                final DataObject dobj = DataObject.find(file);
                cookie = dobj.getLookup().lookup(EditorCookie.Observable.class);
            } catch (DataObjectNotFoundException e) {
                //pass
            }
            this.ec = cookie;
            if (this.ec != null) {
                this.ec.addPropertyChangeListener(WeakListeners.propertyChange(this, this.ec));
                assignDocListener(this.ec);
            }
        }


        @Override
        public void fileDataCreated(FileEvent fe) {
            reset();
        }

        @Override
        public void fileChanged(FileEvent fe) {
            reset();
        }

        @Override
        public void fileDeleted(FileEvent fe) {
            reset();
        }

        @Override
        public void fileRenamed(FileRenameEvent fe) {
            reset();
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (EditorCookie.Observable.PROP_DOCUMENT.equals(evt.getPropertyName())) {
                assignDocListener(this.ec);
            }
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            reset();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            reset();
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
        }

        private void reset() {
            resetAction.run();
        }

        private void assignDocListener(@NonNull final EditorCookie ec) {
            if (currentDoc != null) {
                currentDoc.removeDocumentListener(this);
            }
            currentDoc = ec.getDocument();
            if (currentDoc != null) {
                currentDoc.addDocumentListener(this);
            }
        }
    }
    
    @NbBundle.Messages({
        "LBL_All=Show all JDK modules",
        "LBL_Direct=Show only direct JDK dependencies",
        "LBL_None=Hide all JDK modules"
    })
    private enum JDKVisibility {
        ALL(Bundle.LBL_All()),
        DIRECT(Bundle.LBL_Direct()),
        NONE(Bundle.LBL_None());        
        final String displayName;
        private JDKVisibility(String displayName) {
            this.displayName = displayName;
        }
    }
    
    private static class JDKRenderer extends DefaultListCellRenderer {
        @Override
        @SuppressWarnings({"AssignmentToMethodParameter"})
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if(value instanceof JDKVisibility) {
                value = ((JDKVisibility)value).displayName;
            }
            return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        }
    }
}
