/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2015 Broad Institute
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * Created by JFormDesigner on Mon Dec 13 14:39:17 EST 2010
 */

package org.broad.igv.lists;

import org.broad.igv.logging.*;
import org.broad.igv.DirectoryManager;
import org.broad.igv.ui.IGV;
import org.broad.igv.ui.util.FileDialogUtils;
import org.broad.igv.ui.util.IGVMouseInputAdapter;
import org.broad.igv.ui.util.MessageUtils;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.*;

/**
 * @author Jim RObinson
 * <p/>
 * public String getToolTipText(MouseEvent evt) {
 * // Get item index
 * int index = locationToIndex(evt.getPoint());
 * // Get item Object i
 * tem = getModel().getElementAt(index);
 * // Return the tool tip text
 * return "tool tip for "+item; }
 */
public class GeneListManagerUI extends org.broad.igv.ui.IGVDialog  {

    private static Logger log = LogManager.getLogger(GeneListManagerUI.class);

    private static String ALL = "All";
    private static String DEFAULT_ACTION_TEXT = "View";
    private static final GeneListListener DEFAULT_ACTION_LISTENER = new GeneListListener() {
        @Override
        public void actionPerformed(JDialog dialog, GeneList geneList) {
            IGV.getInstance().setGeneList(geneList);
            dialog.setVisible(false);
            dialog.dispose();
        }
    };

    // This is a static so its "remembered" withing the context of a session.
    static String lastSelectedGroup;

    String selectedGroup;
    ListListModel listModel;
    GeneListModel geneListModel;

    /**
     * Map of gene list name -> gene list
     */
    Map<String, GeneList> geneLists;
    private String selectedList;

    GeneListManager manager;

    private static GeneListManagerUI instance;
    private GeneListListener listener;

    /**
     * Get or create new GeneListManagerUI.
     * If old instance retrieved, the owner IS NOT changed
     *
     * @param owner
     * @return
     */
    public static GeneListManagerUI getInstance(Frame owner) {
        return getInstance(owner, DEFAULT_ACTION_TEXT, DEFAULT_ACTION_LISTENER);
    }

    /**
     * @param owner
     * @param actionText Text to be displayed when the action is performed. Default is "View", for simply viewing the gene list
     * @param listener   The action performed with the specified GeneList
     * @return
     */
    public static GeneListManagerUI getInstance(Frame owner, String actionText, GeneListListener listener) {
        if (instance == null) {
            instance = new GeneListManagerUI(owner);
        }

        instance.setTitle(actionText);
        instance.actionButton.setText(actionText);
        instance.listener = listener;

        return instance;
    }


    private GeneListManagerUI(Frame owner) {
        super(owner);
        manager = GeneListManager.getInstance();
        initComponents();
        initLists();

//        boolean showTDMButton = Boolean.parseBoolean(System.getProperty("enableGitools", "false"));
//        exportTDMButton.setVisible(showTDMButton);
    }

    private void initLists() {
        geneLists = manager.getGeneLists();

        groupJList.setModel(new AbstractListModel() {

            ArrayList<String> groups = new ArrayList();

            {
                groups.add(ALL);
                groups.addAll(manager.getGroups());
            }


            public int getSize() {
                return groups.size();
            }

            public Object getElementAt(int i) {
                return groups.get(i);
            }
        });

        listModel = new ListListModel();
        glJList.setModel(listModel);

        geneListModel = new GeneListModel();
        lociJList.setModel(geneListModel);

        if (lastSelectedGroup != null) {
            groupJList.setSelectedValue(lastSelectedGroup, true);
        } else {
            groupJList.setSelectedIndex(0);
        }
        glJList.setSelectedIndex(0);
    }


    private void groupsValueChanged(ListSelectionEvent e) {
        selectedGroup = (String) groupJList.getSelectedValue();
        lastSelectedGroup = selectedGroup;
        deleteGroupButton.setEnabled(!(GeneListManager.USER_GROUP.equals(selectedGroup) ||
                !GeneListManager.DEFAULT_GENE_LISTS.contains(selectedGroup)));
        updateListModel();
    }

    private void listsValueChanged(ListSelectionEvent e) {

        selectedList = (String) glJList.getSelectedValue();
        if (selectedList == null) {
            geneListModel.clear();
        } else {
            actionButton.setEnabled(true);
            GeneList gl = listModel.getGeneList(selectedList);
            geneListModel.setGeneList(gl);
            lociJList.setModel(geneListModel);
            lociJList.updateUI();

            editButton.setEnabled(gl.isEditable());
            //deleteButton.setEnabled(gl.isEditable());
        }
    }

    private void listLabelMouseClicked(MouseEvent e) {
        listModel.sort();
        glJList.updateUI();
    }

    private void searchBoxKeyReleased(KeyEvent e) {

        updateListModel();
    }

    private void updateListModel() {
        listModel.filter();
        glJList.clearSelection();
        glJList.updateUI();
        lociJList.updateUI();
    }

    /**
     * Stub method generated by JFormDesigner t0 place custom code
     */
    private void createUIComponents() {
        glJList = new JList() {
            public String getToolTipText(MouseEvent evt) {
                int index = locationToIndex(evt.getPoint());
                if (index >= 0) {
                    Object item = getModel().getElementAt(index);
                    GeneList gl = geneLists.get(item);
                    return gl.getDescription();
                }
                return null;
            }
        };
    }


    private void editButtonActionPerformed(ActionEvent e) {

        String selection = (String) glJList.getSelectedValue();
        if (selection != null) {
            GeneList geneList = geneLists.get(selection);
            GeneListEditDialog dlg = new GeneListEditDialog(this, geneList);
            dlg.setVisible(true);

            if (!dlg.isCanceled()) {
                geneListModel.setGeneList(geneList);
                listModel.filter();
                glJList.updateUI();
                lociJList.updateUI();
            }

        }
    }


    private void newListActionPerformed(ActionEvent e) {
        GeneList geneList = new GeneList();
        GeneListEditDialog dlg = new GeneListEditDialog(this, geneList);
        dlg.setVisible(true);

        if (!dlg.isCanceled()) {
            geneList.setGroup(manager.USER_GROUP);
            manager.addGeneList(geneList);
            listModel.add(geneList);
            glJList.updateUI();
            glJList.setSelectedValue(geneList.getName(), true);
            groupJList.updateUI();
            //loci.updateUI();
        }
    }


    private void copyListButtonActionPerformed(ActionEvent e) {
        String selection = (String) glJList.getSelectedValue();
        if (selection != null) {
            GeneList geneList = geneLists.get(selection);
            GeneList copiedList = geneList.copy();
            GeneListEditDialog dlg = new GeneListEditDialog(this, copiedList);
            dlg.setVisible(true);

            if (!dlg.isCanceled()) {
                listModel.add(copiedList);
                glJList.updateUI();
                glJList.setSelectedValue(copiedList.getName(), true);
                //loci.updateUI();
            }
        }
    }

    private void deleteButtonActionPerformed(ActionEvent e) {
        String selection = (String) glJList.getSelectedValue();
        if (selection != null) {
            if (MessageUtils.confirm("<html>Are you sure you want to delete list '" + selection + "' ?" +
                    "<br>associated lists? &nbsp;<b>This action cannot be undone")) {

                boolean groupRemoved = manager.deleteList(selection);
                if (groupRemoved) {
                    initLists();
                } else {
                    geneLists.remove(selection);
                    listModel.filter();
                    glJList.updateUI();
                    glJList.setSelectedIndex(0);
                    lociJList.updateUI();
                }
            }
        }
    }

    /**
     * Import a gene list group from a GMT file
     *
     * @param e
     */
    private void importButtonActionPerformed(ActionEvent e) {

        File gmtFile = FileDialogUtils.chooseFile("Import GMT File");
        if (gmtFile != null) {

            try {
                List<GeneList> loadedLists = manager.importFile(gmtFile);
                initLists();

                if (loadedLists.size() > 0) {
                    groupJList.setSelectedValue(loadedLists.get(0).getGroup(), true);
                    glJList.setSelectedValue(loadedLists.get(0).getName(), true);
                    groupJList.updateUI();
                    glJList.updateUI();
                }

            } catch (IOException e1) {
                log.error("Error updating genome property file", e1);
                MessageUtils.showMessage("Error importing .gmt file: " + e1.getMessage());
            }
        }
    }

    /**
     * Export the selected group to a GMT file
     *
     * @param e
     */
    private void exportButtonActionPerformed(ActionEvent e) {
        if (selectedGroup != null) {
            File userDir = DirectoryManager.getUserDirectory();
            File initFile = new File(selectedGroup + ".gmt");
            File glFile = FileDialogUtils.chooseFile("Save gene lists", userDir, initFile, FileDialogUtils.SAVE);
            if (glFile != null) {
                try {
                    manager.exportGMT(selectedGroup, glFile);
                } catch (Exception e1) {
                    log.error("Error exporting gene lists", e1);
                    MessageUtils.showMessage("Error exporting gene lists: " + e1.getMessage());
                }
            }
        }
    }


    private void deleteGroupButtonActionPerformed(ActionEvent e) {

        if (selectedGroup != null && MessageUtils.confirm(this, "<html>Are you sure you want to delete group '" +
                selectedGroup + "' and all " +
                "<br>associated lists? &nbsp;<b>This action cannot be undone")) {
            manager.deleteGroup(selectedGroup);
            initLists();
        }
    }


    private void closeButtonActionPerformed(ActionEvent e) {
        setVisible(false);
    }

    private void actionButtonActionPerformed(ActionEvent e) {
        if (selectedList != null) {
            GeneList geneList = geneLists.get(selectedList);
            listener.actionPerformed(this, geneList);
        }
    }

    private void glJListMouseClicked(MouseEvent e) {
        if (e.getClickCount() > 1) {
            this.actionButtonActionPerformed(null);
        }
    }


    class ListListModel extends AbstractListModel {

        boolean sortAscending;
        ArrayList<String> filteredNames;

        ListListModel() {
            filteredNames = new ArrayList(geneLists.size());
            filter();
        }

        public int getSize() {
            return filteredNames.size();
        }

        public Object getElementAt(int i) {
            return filteredNames.get(i);
        }

        void sort() {

            Collections.sort(filteredNames, new Comparator<String>() {
                public int compare(String s, String s1) {
                    return sortAscending ? s.compareTo(s1) : s1.compareTo(s);
                }
            });
            sortAscending = !sortAscending;
        }

        GeneList getGeneList(String listName) {
            return geneLists.get(listName);
        }

        void filter() {
            filteredNames.clear();
            for (Map.Entry<String, GeneList> entry : geneLists.entrySet()) {
                String name = entry.getKey();
                GeneList gl = entry.getValue();

                if (gl != null) {
                    if (gl != null && isPassFilter(gl)) {
                        filteredNames.add(name);
                    }
                }
            }
        }

        boolean isPassFilter(GeneList geneList) {

            if (selectedGroup != null && !selectedGroup.equals(ALL)) {
                if (!geneList.getGroup().equals(selectedGroup)) {
                    return false;
                }
            }

            String filterString = searchBox.getText();
            if (filterString != null && filterString.trim().length() > 0) {
                String tmp = filterString.trim().toLowerCase();

                if (geneList.getName().toLowerCase().contains(tmp)) {
                    return true;
                }

                for (String gene : geneList.getLoci()) {
                    if (gene.toLowerCase().contains(tmp)) {
                        return true;
                    }
                }

                return false;

            }
            return true;
        }

        public void add(GeneList geneList) {
            geneLists.put(geneList.getName(), geneList);
            if (isPassFilter(geneList)) {
                filteredNames.add(geneList.getName());
            }
        }
    }

    class GeneListModel extends AbstractListModel {

        java.util.List<String> genes;

        GeneListModel() {
            genes = new ArrayList();
        }

        void setGeneList(GeneList geneList) {
            genes = geneList == null ? new ArrayList() : new ArrayList(geneList.getLoci());
        }

        public int getSize() {
            return genes.size();
        }

        public Object getElementAt(int i) {
            return genes.get(i);
        }

        public void clear() {
            genes.clear();
        }
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        // Generated using JFormDesigner non-commercial license
        createUIComponents();

        dialogPane = new JPanel();
        contentPanel = new JPanel();
        panel2 = new JPanel();
        panel1 = new JPanel();
        panel6 = new JPanel();
        label1 = new JLabel();
        searchBox = new JTextField();
        panel10 = new JPanel();
        splitPane2 = new JSplitPane();
        splitPane1 = new JSplitPane();
        panel3 = new JPanel();
        label3 = new JLabel();
        scrollPane1 = new JScrollPane();
        groupJList = new JList<>();
        panel7 = new JPanel();
        importButton = new JButton();
        exportButton = new JButton();
        deleteGroupButton = new JButton();
        panel4 = new JPanel();
        listLabel = new JLabel();
        scrollPane2 = new JScrollPane();
        panel8 = new JPanel();
        newList = new JButton();
        copyListButton = new JButton();
        editButton = new JButton();
        deleteButton = new JButton();
        panel5 = new JPanel();
        label4 = new JLabel();
        scrollPane3 = new JScrollPane();
        lociJList = new JList();
        panel9 = new JPanel();
        buttonBar = new JPanel();
        exportTDMButton = new JButton();
        actionButton = new JButton();
        closeButton = new JButton();

        //======== this ========
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());

        //======== dialogPane ========
        {
            dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12));
            dialogPane.setLayout(new BorderLayout());

            //======== contentPanel ========
            {
                contentPanel.setBorder(new EtchedBorder(EtchedBorder.RAISED));
                contentPanel.setLayout(new BorderLayout());

                //======== panel2 ========
                {
                    panel2.setBackground(new Color(204, 204, 204));
                    panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS));

                    //======== panel1 ========
                    {
                        panel1.setBorder(new EmptyBorder(5, 5, 5, 0));
                        panel1.setBackground(new Color(204, 204, 204));
                        panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS));

                        //======== panel6 ========
                        {
                            panel6.setMinimumSize(new Dimension(0, 0));
                            panel6.setPreferredSize(new Dimension(400, 0));
                            panel6.setOpaque(false);
                            panel6.setLayout(null);
                        }
                        panel1.add(panel6);

                        //---- label1 ----
                        label1.setText("Search");
                        label1.setBorder(new EmptyBorder(0, 0, 0, 10));
                        panel1.add(label1);

                        //---- searchBox ----
                        searchBox.setBorder(new BevelBorder(BevelBorder.LOWERED));
                        searchBox.addKeyListener(new KeyAdapter() {
                            @Override
                            public void keyReleased(KeyEvent e) {
                                searchBoxKeyReleased(e);
                            }
                        });
                        panel1.add(searchBox);

                        //======== panel10 ========
                        {
                            panel10.setPreferredSize(new Dimension(5, 0));
                            panel10.setMinimumSize(new Dimension(5, 0));
                            panel10.setOpaque(false);
                            panel10.setLayout(null);
                        }
                        panel1.add(panel10);
                    }
                    panel2.add(panel1);
                }
                contentPanel.add(panel2, BorderLayout.NORTH);

                //======== splitPane2 ========
                {
                    splitPane2.setBorder(null);
                    splitPane2.setDividerLocation(600);

                    //======== splitPane1 ========
                    {
                        splitPane1.setBorder(null);
                        splitPane1.setDividerLocation(270);

                        //======== panel3 ========
                        {
                            panel3.setBorder(LineBorder.createBlackLineBorder());
                            panel3.setLayout(new BorderLayout());

                            //---- label3 ----
                            label3.setText("Group");
                            panel3.add(label3, BorderLayout.NORTH);

                            //======== scrollPane1 ========
                            {
                                scrollPane1.setPreferredSize(new Dimension(80, 140));

                                //---- groupJList ----
                                groupJList.setModel(new AbstractListModel<String>() {
                                    String[] values = {
                                            "All"
                                    };

                                    @Override
                                    public int getSize() {
                                        return values.length;
                                    }

                                    @Override
                                    public String getElementAt(int i) {
                                        return values[i];
                                    }
                                });
                                groupJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                                groupJList.addListSelectionListener(e -> groupsValueChanged(e));
                                scrollPane1.setViewportView(groupJList);
                            }
                            panel3.add(scrollPane1, BorderLayout.CENTER);

                            //======== panel7 ========
                            {
                                panel7.setLayout(new BoxLayout(panel7, BoxLayout.X_AXIS));

                                //---- importButton ----
                                importButton.setIcon(null);
                                importButton.setText("Import");
                                importButton.setToolTipText("Import a .gmt file, .grp, or .bed file");
                                importButton.addActionListener(e -> importButtonActionPerformed(e));
                                panel7.add(importButton);

                                //---- exportButton ----
                                exportButton.setText("Export");
                                exportButton.addActionListener(e -> exportButtonActionPerformed(e));
                                panel7.add(exportButton);

                                //---- deleteGroupButton ----
                                deleteGroupButton.setText("Delete");
                                deleteGroupButton.setEnabled(false);
                                deleteGroupButton.addActionListener(e -> deleteGroupButtonActionPerformed(e));
                                panel7.add(deleteGroupButton);
                            }
                            panel3.add(panel7, BorderLayout.SOUTH);
                        }
                        splitPane1.setLeftComponent(panel3);

                        //======== panel4 ========
                        {
                            panel4.setBorder(LineBorder.createBlackLineBorder());
                            panel4.setLayout(new BorderLayout());

                            //---- listLabel ----
                            listLabel.setText("List");
                            listLabel.addMouseListener(new IGVMouseInputAdapter() {
                                @Override
                                public void igvMouseClicked(MouseEvent e) {
                                    listLabelMouseClicked(e);
                                }
                            });
                            panel4.add(listLabel, BorderLayout.PAGE_START);

                            //======== scrollPane2 ========
                            {

                                //---- glJList ----
                                glJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                                glJList.addListSelectionListener(e -> listsValueChanged(e));
                                glJList.addMouseListener(new IGVMouseInputAdapter() {
                                    @Override
                                    public void mouseClicked(MouseEvent e) {
                                        glJListMouseClicked(e);
                                    }
                                });
                                scrollPane2.setViewportView(glJList);
                            }
                            panel4.add(scrollPane2, BorderLayout.CENTER);

                            //======== panel8 ========
                            {
                                panel8.setLayout(new BoxLayout(panel8, BoxLayout.X_AXIS));

                                //---- newList ----
                                newList.setIcon(null);
                                newList.setText("New");
                                newList.addActionListener(e -> newListActionPerformed(e));
                                panel8.add(newList);

                                //---- copyListButton ----
                                copyListButton.setText("Copy");
                                copyListButton.addActionListener(e -> copyListButtonActionPerformed(e));
                                panel8.add(copyListButton);

                                //---- editButton ----
                                editButton.setText("Edit");
                                editButton.setEnabled(false);
                                editButton.addActionListener(e -> editButtonActionPerformed(e));
                                panel8.add(editButton);

                                //---- deleteButton ----
                                deleteButton.setIcon(null);
                                deleteButton.setText("Delete");
                                deleteButton.addActionListener(e -> deleteButtonActionPerformed(e));
                                panel8.add(deleteButton);
                            }
                            panel4.add(panel8, BorderLayout.PAGE_END);
                        }
                        splitPane1.setRightComponent(panel4);
                    }
                    splitPane2.setLeftComponent(splitPane1);

                    //======== panel5 ========
                    {
                        panel5.setBorder(LineBorder.createBlackLineBorder());
                        panel5.setLayout(new BorderLayout());

                        //---- label4 ----
                        label4.setText("Loci");
                        panel5.add(label4, BorderLayout.NORTH);

                        //======== scrollPane3 ========
                        {

                            //---- lociJList ----
                            lociJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                            lociJList.setSelectionBackground(Color.white);
                            lociJList.setSelectionForeground(Color.black);
                            lociJList.setFocusable(false);
                            scrollPane3.setViewportView(lociJList);
                        }
                        panel5.add(scrollPane3, BorderLayout.CENTER);

                        //======== panel9 ========
                        {
                            panel9.setLayout(new BoxLayout(panel9, BoxLayout.X_AXIS));
                        }
                        panel5.add(panel9, BorderLayout.SOUTH);
                    }
                    splitPane2.setRightComponent(panel5);
                }
                contentPanel.add(splitPane2, BorderLayout.CENTER);
            }
            dialogPane.add(contentPanel, BorderLayout.CENTER);

            //======== buttonBar ========
            {
                buttonBar.setBorder(null);
                buttonBar.setLayout(new FlowLayout(FlowLayout.RIGHT));

                //---- actionButton ----
                actionButton.setText("View");
                actionButton.setEnabled(false);
                actionButton.addActionListener(e -> actionButtonActionPerformed(e));
                buttonBar.add(actionButton);

                //---- closeButton ----
                closeButton.setText("Close");
                closeButton.addActionListener(e -> closeButtonActionPerformed(e));
                buttonBar.add(closeButton);
            }
            dialogPane.add(buttonBar, BorderLayout.SOUTH);
        }
        contentPane.add(dialogPane, BorderLayout.CENTER);
        setSize(845, 580);
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    // Generated using JFormDesigner non-commercial license
    private JPanel dialogPane;
    private JPanel contentPanel;
    private JPanel panel2;
    private JPanel panel1;
    private JPanel panel6;
    private JLabel label1;
    private JTextField searchBox;
    private JPanel panel10;
    private JSplitPane splitPane2;
    private JSplitPane splitPane1;
    private JPanel panel3;
    private JLabel label3;
    private JScrollPane scrollPane1;
    private JList<String> groupJList;
    private JPanel panel7;
    private JButton importButton;
    private JButton exportButton;
    private JButton deleteGroupButton;
    private JPanel panel4;
    private JLabel listLabel;
    private JScrollPane scrollPane2;
    private JList glJList;
    private JPanel panel8;
    private JButton newList;
    private JButton copyListButton;
    private JButton editButton;
    private JButton deleteButton;
    private JPanel panel5;
    private JLabel label4;
    private JScrollPane scrollPane3;
    private JList lociJList;
    private JPanel panel9;
    private JPanel buttonBar;
    private JButton exportTDMButton;
    private JButton actionButton;
    private JButton closeButton;
    // JFormDesigner - End of variables declaration  //GEN-END:variables

    /**
     * Custom action listener for receiving a GeneList
     * and taking some action based on that. Listeners
     * implementing this interface can be used as callbacks
     * once a GeneList is selected from GeneListManagerUI
     *
     * @author jacob
     * @date 2013-Jan-04
     * @api
     */
    public interface GeneListListener {

        void actionPerformed(JDialog dialog, GeneList geneList);
    }
}
