Package org.gephi.desktop.datalab

Source Code of org.gephi.desktop.datalab.DataTableTopComponent

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>, Mathieu Jacomy, Julian Bilcke, Eduardo Ramos
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.desktop.datalab;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeEvent;
import org.gephi.data.attributes.api.AttributeEvent.EventType;
import org.gephi.data.attributes.api.AttributeListener;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.data.attributes.api.AttributeTable;
import org.gephi.datalab.api.DataLaboratoryHelper;
import org.gephi.datalab.api.datatables.DataTablesController;
import org.gephi.datalab.api.datatables.DataTablesEventListener;
import org.gephi.datalab.spi.ContextMenuItemManipulator;
import org.gephi.datalab.spi.columns.AttributeColumnsManipulator;
import org.gephi.datalab.spi.edges.EdgesManipulator;
import org.gephi.datalab.spi.general.GeneralActionsManipulator;
import org.gephi.datalab.spi.general.PluginGeneralActionsManipulator;
import org.gephi.datalab.spi.nodes.NodesManipulator;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphEvent;
import org.gephi.graph.api.GraphListener;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.gephi.project.api.ProjectController;
import org.gephi.ui.utils.BusyUtils;
import org.gephi.project.api.Workspace;
import org.gephi.project.api.WorkspaceListener;
import org.gephi.ui.components.WrapLayout;
import org.gephi.desktop.datalab.general.actions.AddColumnUI;
import org.gephi.desktop.datalab.general.actions.CSVExportUI;
import org.gephi.desktop.datalab.general.actions.MergeColumnsUI;
import org.gephi.ui.utils.DialogFileFilter;
import org.gephi.ui.utils.UIUtils;
import org.gephi.utils.TableCSVExporter;
import org.netbeans.swing.etable.ETableColumnModel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.JCommandButtonPanel;
import org.pushingpixels.flamingo.api.common.JCommandButtonStrip;
import org.pushingpixels.flamingo.api.common.JCommandMenuButton;
import org.pushingpixels.flamingo.api.common.RichTooltip;
import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon;
import org.pushingpixels.flamingo.api.common.popup.JCommandPopupMenu;
import org.pushingpixels.flamingo.api.common.popup.JPopupPanel;
import org.pushingpixels.flamingo.api.common.popup.PopupPanelCallback;

/**
*
* @author Mathieu Bastian
*/
final class DataTableTopComponent extends TopComponent implements AWTEventListener, DataTablesEventListener, AttributeListener, GraphListener {

    private enum ClassDisplayed {

        NONE, NODE, EDGE
    };
    private static DataTableTopComponent instance;
    static final String ICON_PATH = "org/gephi/desktop/datalab/resources/small.png";
    private static final String PREFERRED_ID = "DataTableTopComponent";
    //Settings
    private static final String DATA_LABORATORY_DYNAMIC_FILTERING = "DataLaboratory_Dynamic_Filtering";
    private static final String DATA_LABORATORY_ONLY_VISIBLE = "DataLaboratory_visibleOnly";
    private static final String DATA_LABORATORY_SPARKLINES = "DataLaboratory_useSparklines";
    private static final String DATA_LABORATORY_TIME_INTERVAL_GRAPHICS = "DataLaboratory_timeIntervalGraphics";
    private static final String DATA_LABORATORY_EDGES_NODES_LABELS = "DataLaboratory_showEdgesNodesLabels";
    private static final Color invalidFilterColor = new Color(254, 150, 150);
    private final boolean dynamicFiltering;
    private boolean visibleOnly = false;
    private boolean useSparklines = false;
    private boolean timeIntervalGraphics = false;
    private boolean showEdgesNodesLabels = false;
    private Map<Integer, ContextMenuItemManipulator> nodesActionMappings = new HashMap<Integer, ContextMenuItemManipulator>();//For key bindings
    private Map<Integer, ContextMenuItemManipulator> edgesActionMappings = new HashMap<Integer, ContextMenuItemManipulator>();//For key bindings
    //Data
    private GraphModel graphModel;
    private DataTablesModel dataTablesModel;
    private AvailableColumnsModel nodeAvailableColumnsModel;
    private AvailableColumnsModel edgeAvailableColumnsModel;
    //Table
    private NodeDataTable nodeTable;
    private EdgeDataTable edgeTable;
    //General actions buttons
    private ArrayList<JComponent> generalActionsButtons = new ArrayList<JComponent>();
    //States
    private ClassDisplayed classDisplayed = ClassDisplayed.NODE;//Display nodes by default at first.
    private ArrayList previousNodeFilterColumns = new ArrayList();
    private int previousNodeColumnsFilterIndex = 0;
    private ArrayList previousEdgeFilterColumns = new ArrayList();
    private int previousEdgeColumnsFilterIndex = 0;
    //Executor
    private RefreshOnceHelperThread refreshOnceHelperThread;

    private DataTableTopComponent() {

        //Get saved preferences if existing:
        dynamicFiltering = NbPreferences.forModule(DataTableTopComponent.class).getBoolean(DATA_LABORATORY_DYNAMIC_FILTERING, true);
        visibleOnly = NbPreferences.forModule(DataTableTopComponent.class).getBoolean(DATA_LABORATORY_ONLY_VISIBLE, false);
        useSparklines = NbPreferences.forModule(DataTableTopComponent.class).getBoolean(DATA_LABORATORY_SPARKLINES, false);
        timeIntervalGraphics = NbPreferences.forModule(DataTableTopComponent.class).getBoolean(DATA_LABORATORY_TIME_INTERVAL_GRAPHICS, false);
        showEdgesNodesLabels = NbPreferences.forModule(DataTableTopComponent.class).getBoolean(DATA_LABORATORY_EDGES_NODES_LABELS, false);

        initComponents();
        if (UIUtils.isAquaLookAndFeel()) {
            columnManipulatorsPanel.setBackground(UIManager.getColor("NbExplorerView.background"));
        }

        columnManipulatorsPanel.setLayout(new WrapLayout(WrapLayout.CENTER, 25, 20));
        setName(NbBundle.getMessage(DataTableTopComponent.class, "CTL_DataTableTopComponent"));
        setIcon(ImageUtilities.loadImage(ICON_PATH));

        //toolbar
        Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
        controlToolbar.setBorder(b);
        if (UIUtils.isAquaLookAndFeel()) {
            controlToolbar.setBackground(UIManager.getColor("NbExplorerView.background"));
        }

        initEvents();

        //Init tables
        nodeTable = new NodeDataTable();
        edgeTable = new EdgeDataTable();

        nodeTable.setUseSparklines(useSparklines);
        nodeTable.setTimeIntervalGraphics(timeIntervalGraphics);
        edgeTable.setUseSparklines(useSparklines);
        edgeTable.setTimeIntervalGraphics(timeIntervalGraphics);
        edgeTable.setShowEdgesNodesLabels(showEdgesNodesLabels);


        //Init
        ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
        Workspace workspace = pc.getCurrentWorkspace();
        if (workspace == null) {
            clearAll();
        } else {
            AttributeModel attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel();

            dataTablesModel = workspace.getLookup().lookup(DataTablesModel.class);
            if (dataTablesModel == null) {
                workspace.add(dataTablesModel = new DataTablesModel(attributeModel.getNodeTable(), attributeModel.getEdgeTable()));
            }
            nodeAvailableColumnsModel = dataTablesModel.getNodeAvailableColumnsModel();
            edgeAvailableColumnsModel = dataTablesModel.getEdgeAvailableColumnsModel();
            refreshAllOnce();
        }
        bannerPanel.setVisible(false);
    }

    private void initEvents() {

        //Workspace Listener
        ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
        final GraphController gc = Lookup.getDefault().lookup(GraphController.class);
        pc.addWorkspaceListener(new WorkspaceListener() {

            public void initialize(Workspace workspace) {
                //Prepare DataTablesEvent listener
                Lookup.getDefault().lookup(DataTablesController.class).setDataTablesEventListener(DataTableTopComponent.this);
            }

            public void select(Workspace workspace) {
                //Prepare DataTablesEvent listener
                Lookup.getDefault().lookup(DataTablesController.class).setDataTablesEventListener(DataTableTopComponent.this);
                AttributeModel attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel();

                dataTablesModel = workspace.getLookup().lookup(DataTablesModel.class);
                if (dataTablesModel == null) {
                    workspace.add(dataTablesModel = new DataTablesModel(attributeModel.getNodeTable(), attributeModel.getEdgeTable()));
                }
                nodeAvailableColumnsModel = dataTablesModel.getNodeAvailableColumnsModel();
                edgeAvailableColumnsModel = dataTablesModel.getEdgeAvailableColumnsModel();
                hideTable();
                enableTableControls();

                attributeModel.addAttributeListener(DataTableTopComponent.this);

                graphModel = gc.getModel();
                graphModel.addGraphListener(DataTableTopComponent.this);

                refreshAllOnce();
            }

            public void unselect(Workspace workspace) {
                graphModel.removeGraphListener(DataTableTopComponent.this);

                AttributeModel attributeModel = workspace.getLookup().lookup(AttributeModel.class);
                attributeModel.removeAttributeListener(DataTableTopComponent.this);
                graphModel = null;
                dataTablesModel = null;
                nodeAvailableColumnsModel = null;
                edgeAvailableColumnsModel = null;
                clearAll();
            }

            public void close(Workspace workspace) {
            }

            public void disable() {
                clearAll();
                //No more workspaces active, disable the DataTablesEvent listener
                Lookup.getDefault().lookup(DataTablesController.class).setDataTablesEventListener(null);
            }
        });
        if (pc.getCurrentWorkspace() != null) {
            //Prepare DataTablesEvent listener
            Lookup.getDefault().lookup(DataTablesController.class).setDataTablesEventListener(DataTableTopComponent.this);
            dataTablesModel = pc.getCurrentWorkspace().getLookup().lookup(DataTablesModel.class);
            graphModel = gc.getModel();
            graphModel.addGraphListener(DataTableTopComponent.this);

            AttributeModel attributeModel = pc.getCurrentWorkspace().getLookup().lookup(AttributeModel.class);
            attributeModel.addAttributeListener(DataTableTopComponent.this);
        }

        //Filter
        if (dynamicFiltering) {
            filterTextField.getDocument().addDocumentListener(new DocumentListener() {

                public void insertUpdate(DocumentEvent e) {
                    refreshFilter();
                }

                public void removeUpdate(DocumentEvent e) {
                    refreshFilter();
                }

                public void changedUpdate(DocumentEvent e) {
                }
            });
        } else {
            filterTextField.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    refreshFilter();
                }
            });
        }
        columnComboBox.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                refreshFilter();
            }
        });
        initKeyEventContextMenuActionMappings();
    }

    private void initKeyEventContextMenuActionMappings() {
        mapItems(DataLaboratoryHelper.getDefault().getNodesManipulators(), nodesActionMappings);
        mapItems(DataLaboratoryHelper.getDefault().getEdgesManipulators(), edgesActionMappings);
    }

    private void mapItems(ContextMenuItemManipulator[] items, Map<Integer, ContextMenuItemManipulator> map) {
        Integer key;
        ContextMenuItemManipulator[] subItems;
        for (ContextMenuItemManipulator item : items) {
            key = item.getMnemonicKey();
            if (key != null) {
                if (!map.containsKey(key)) {
                    map.put(key, item);
                }
            }
            subItems = item.getSubItems();
            if (subItems != null) {
                mapItems(subItems, map);
            }
        }
    }

    private synchronized void refreshAll() {
        if (Lookup.getDefault().lookup(ProjectController.class).getCurrentWorkspace() != null) {//Some workspace is selected
            refreshTable();
            refreshColumnManipulators();
            refreshGeneralActionsButtons();
        }
    }

    private void clearAll() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                clearTableControls();
                clearColumnManipulators();
                clearGeneralActionsButtons();
            }
        });
    }

    private AvailableColumnsModel getTableAvailableColumnsModel(AttributeTable table) {
        if (Lookup.getDefault().lookup(AttributeController.class).getModel().getNodeTable() == table) {
            return nodeAvailableColumnsModel;
        } else {
            return edgeAvailableColumnsModel;
        }
    }

    public void attributesChanged(final AttributeEvent event) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                AvailableColumnsModel tableAvailableColumnsModel = getTableAvailableColumnsModel(event.getSource());
                switch (event.getEventType()) {
                    case ADD_COLUMN:
                        for (AttributeColumn c : event.getData().getAddedColumns()) {
                            if (!tableAvailableColumnsModel.addAvailableColumn(c)) {//Add as available by default. Will only be added if the max number of available columns is not surpassed
                                availableColumnsButton.setIcon(ImageUtilities.loadImageIcon("org/gephi/desktop/datalab/resources/light-bulb--plus.png", true));
                                break;
                            }
                        }
                        break;
                    case REMOVE_COLUMN:
                        for (AttributeColumn c : event.getData().getAddedColumns()) {
                            tableAvailableColumnsModel.removeAvailableColumn(c);
                        }
                        break;
                }
                if (isOpened()) {
                    refreshOnce(event.is(EventType.SET_VALUE));
                }
            }
        });
    }

    public void graphChanged(GraphEvent event) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                if (isOpened()) {
                    refreshOnce(false);
                }
            }
        });
    }

    /**
     * This method ensures that the refreshing of all Data laboratory or table only happens once in a short time period.
     *
     * @param refreshTableOnly True to refresh only table values, false to refresh all UI including manipulators
     */
    private void refreshOnce(boolean refreshTableOnly) {
        if (refreshOnceHelperThread == null || !refreshOnceHelperThread.isAlive() || (refreshOnceHelperThread.refreshTableOnly && !refreshTableOnly)) {
            refreshOnceHelperThread = new RefreshOnceHelperThread(refreshTableOnly);
            refreshOnceHelperThread.start();
        } else {
            refreshOnceHelperThread.eventAttended();
        }
    }

    private void refreshAllOnce() {
        refreshOnce(false);
    }

    /****************Table related methods:*****************/
    private void refreshFilter() {
        int index = columnComboBox.getSelectedIndex();
        if (index < 0) {
            return;
        }
        if (classDisplayed.equals(ClassDisplayed.NODE)) {
            if (nodeTable.setFilter(filterTextField.getText(), index)) {
                filterTextField.setBackground(Color.WHITE);
            } else {
                filterTextField.setBackground(invalidFilterColor);
            }
            previousNodeColumnsFilterIndex = index;
        } else if (classDisplayed.equals(ClassDisplayed.EDGE)) {
            if (edgeTable.setPattern(filterTextField.getText(), index)) {
                filterTextField.setBackground(Color.WHITE);
            } else {
                filterTextField.setBackground(invalidFilterColor);
            }
            previousEdgeColumnsFilterIndex = index;
        }
    }

    private void initNodesView() {
        Runnable initNodesRunnable = new Runnable() {

            public void run() {
                try {
                    String busyMsg = NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.tableScrollPane.busyMessage");
                    BusyUtils.BusyLabel busylabel = BusyUtils.createCenteredBusyLabel(tableScrollPane, busyMsg, nodeTable.getOutlineTable());
                    busylabel.setBusy(true);

                    //Attributes columns
                    final AttributeColumn[] cols = nodeAvailableColumnsModel.getAvailableColumns();

                    //Nodes from DHNS
                    HierarchicalGraph graph;
                    if (visibleOnly) {
                        graph = graphModel.getHierarchicalGraphVisible();
                    } else {
                        graph = graphModel.getHierarchicalGraph();
                    }
                    if (graph == null) {
                        tableScrollPane.setViewportView(null);
                        return;
                    }

                    //Model
                    nodeTable.refreshModel(graph, cols, dataTablesModel);
                    refreshFilterColumns();

                    busylabel.setBusy(false);
                    nodeTable.scrollToFirstNodeSelected();
                } catch (Exception e) {
                    Exceptions.printStackTrace(e);
                    JLabel errorLabel = new JLabel(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.tableScrollPane.error"), SwingConstants.CENTER);
                    tableScrollPane.setViewportView(errorLabel);
                }
            }
        };
        SwingUtilities.invokeLater(initNodesRunnable);
    }

    private void initEdgesView() {
        Runnable initEdgesRunnable = new Runnable() {

            public void run() {
                try {
                    String busyMsg = NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.tableScrollPane.busyMessage");
                    BusyUtils.BusyLabel busylabel = BusyUtils.createCenteredBusyLabel(tableScrollPane, busyMsg, edgeTable.getTable());
                    busylabel.setBusy(true);

                    //Attributes columns
                    final AttributeColumn[] cols = edgeAvailableColumnsModel.getAvailableColumns();

                    //Edges from DHNS
                    HierarchicalGraph graph;
                    if (visibleOnly) {
                        graph = graphModel.getHierarchicalGraphVisible();
                    } else {
                        graph = graphModel.getHierarchicalGraph();
                    }
                    if (graph == null) {
                        tableScrollPane.setViewportView(null);
                        return;
                    }

                    //Model
                    edgeTable.refreshModel(graph, cols, dataTablesModel);
                    refreshFilterColumns();

                    busylabel.setBusy(false);
                    edgeTable.scrollToFirstEdgeSelected();
                } catch (Exception e) {
                    Exceptions.printStackTrace(e);
                    JLabel errorLabel = new JLabel(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.tableScrollPane.error"), SwingConstants.CENTER);
                    tableScrollPane.setViewportView(errorLabel);
                }
            }
        };
        SwingUtilities.invokeLater(initEdgesRunnable);
    }

    private void refreshFilterColumns() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                ArrayList columns = new ArrayList();
                if (classDisplayed.equals(ClassDisplayed.NODE)) {
                    ETableColumnModel columnModel = (ETableColumnModel) nodeTable.getOutlineTable().getColumnModel();
                    DefaultComboBoxModel model = new DefaultComboBoxModel();
                    for (int i = 0; i < columnModel.getColumnCount(); i++) {
                        if (!columnModel.isColumnHidden(columnModel.getColumn(i))) {
                            model.addElement(columnModel.getColumn(i).getHeaderValue());
                            columns.add(columnModel.getColumn(i).getHeaderValue());
                        }
                    }

                    columnComboBox.setModel(model);
                    if (columns.equals(previousNodeFilterColumns) && previousNodeColumnsFilterIndex < columnComboBox.getItemCount()) {//Preserve user selected column when the columns list does not change
                        columnComboBox.setSelectedIndex(previousNodeColumnsFilterIndex);
                    } else {
                        previousNodeColumnsFilterIndex = 0;
                    }
                    previousNodeFilterColumns = columns;
                } else if (classDisplayed.equals(ClassDisplayed.EDGE)) {
                    DefaultComboBoxModel model = new DefaultComboBoxModel();
                    for (int i = 0; i < edgeTable.getTable().getColumnCount(); i++) {
                        if (edgeTable.getTable().getColumnExt(i).isVisible()) {
                            model.addElement(edgeTable.getTable().getColumnExt(i).getTitle());
                            columns.add(edgeTable.getTable().getColumnExt(i).getTitle());
                        }
                    }
                    columnComboBox.setModel(model);
                    if (columns.equals(previousEdgeFilterColumns) && previousEdgeColumnsFilterIndex < columnComboBox.getItemCount()) {//Preserve user selected column when the columns list does not change
                        columnComboBox.setSelectedIndex(previousEdgeColumnsFilterIndex);
                    } else {
                        previousEdgeColumnsFilterIndex = 0;
                    }
                    previousEdgeFilterColumns = columns;
                }
            }
        });
    }

    private void enableTableControls() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                nodesButton.setEnabled(true);
                edgesButton.setEnabled(true);
                configurationButton.setEnabled(true);
                availableColumnsButton.setEnabled(true);
                filterTextField.setEnabled(true);
                columnComboBox.setEnabled(true);
                labelFilter.setEnabled(true);
            }
        });
    }

    private void clearTableControls() {
        elementGroup.clearSelection();
        nodesButton.setEnabled(false);
        edgesButton.setEnabled(false);
        configurationButton.setEnabled(false);
        filterTextField.setEnabled(false);
        filterTextField.setText("");
        columnComboBox.setEnabled(false);
        columnComboBox.removeAllItems();
        previousNodeFilterColumns.clear();
        previousEdgeFilterColumns.clear();
        availableColumnsButton.setEnabled(false);
        availableColumnsButton.setIcon(ImageUtilities.loadImageIcon("org/gephi/desktop/datalab/resources/light-bulb.png", true));
        labelFilter.setEnabled(false);
        bannerPanel.setVisible(false);
        hideTable();
    }

    private void hideTable() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                tableScrollPane.setViewportView(null);
            }
        });
    }

    private void refreshTable() {
        bannerPanel.setVisible(false);
        if (classDisplayed.equals(ClassDisplayed.NODE)) {
            nodesButton.setSelected(true);
            initNodesView();
        } else if (classDisplayed.equals(ClassDisplayed.EDGE)) {
            edgesButton.setSelected(true);
            initEdgesView();
        }
    }

    public void selectNodesTable() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                classDisplayed = ClassDisplayed.NODE;
                refreshAllOnce();
            }
        });
    }

    public void selectEdgesTable() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                classDisplayed = ClassDisplayed.EDGE;
                refreshAllOnce();
            }
        });
    }

    public void refreshCurrentTable() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                refreshOnce(true);
            }
        });
    }

    public void setNodeTableSelection(final Node[] nodes) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                nodeTable.setNodesSelection(nodes);
                nodeTable.scrollToFirstNodeSelected();
            }
        });
    }

    public void setEdgeTableSelection(final Edge[] edges) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                edgeTable.setEdgesSelection(edges);
                edgeTable.scrollToFirstEdgeSelected();
            }
        });
    }

    public Node[] getNodeTableSelection() {
        return nodeTable.getNodesFromSelectedRows();
    }

    public Edge[] getEdgeTableSelection() {
        return edgeTable.getEdgesFromSelectedRows();
    }

    public boolean isNodeTableMode() {
        return classDisplayed == ClassDisplayed.NODE;
    }

    public boolean isEdgeTableMode() {
        return classDisplayed == ClassDisplayed.EDGE;
    }

    public boolean isShowOnlyVisible() {
        return visibleOnly;
    }

    public void setShowOnlyVisible(boolean showOnlyVisible) {
        visibleOnly = showOnlyVisible;
        refreshCurrentTable();
    }

    public boolean isUseSparklines() {
        return useSparklines;
    }

    public void setUseSparklines(boolean useSparklines) {
        this.useSparklines = useSparklines;
        nodeTable.setUseSparklines(useSparklines);
        edgeTable.setUseSparklines(useSparklines);
        refreshCurrentTable();
    }

    public boolean isTimeIntervalGraphics() {
        return timeIntervalGraphics;
    }

    public void setTimeIntervalGraphics(boolean timeIntervalGraphics) {
        this.timeIntervalGraphics = timeIntervalGraphics;
        nodeTable.setTimeIntervalGraphics(timeIntervalGraphics);
        edgeTable.setTimeIntervalGraphics(timeIntervalGraphics);
        refreshCurrentTable();
    }

    public boolean isShowEdgesNodesLabels() {
        return showEdgesNodesLabels;
    }

    public void setShowEdgesNodesLabels(boolean showEdgesNodesLabels) {
        this.showEdgesNodesLabels = showEdgesNodesLabels;
        edgeTable.setShowEdgesNodesLabels(showEdgesNodesLabels);
        refreshCurrentTable();
    }

    public void exportCurrentTable(ExportMode exportMode) {
        JTable table;
        if (classDisplayed == classDisplayed.NODE) {
            table = nodeTable.getOutlineTable();
        } else {
            table = edgeTable.getTable();
        }

        switch (exportMode) {
            case CSV:
                showCSVExportUI(table);
                break;
        }
    }

    private void showCSVExportUI(JTable table) {
        CSVExportUI csvUI = new CSVExportUI(table);
        DialogDescriptor dd = new DialogDescriptor(csvUI, csvUI.getDisplayName());
        if (DialogDisplayer.getDefault().notify(dd).equals(DialogDescriptor.OK_OPTION)) {
            DataTableTopComponent.exportTableAsCSV(this, table, csvUI.getSelectedSeparator(), csvUI.getSelectedCharset(), csvUI.getSelectedColumnsIndexes());
        }
        csvUI.unSetup();
    }

    /*************Column manipulators related methods:*************/
    private void refreshColumnManipulators() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                clearColumnManipulators();
                prepareAddColumnButton();
                prepareMergeColumnsButton();
                prepareColumnManipulatorsButtons();
            }
        });
    }

    private void clearColumnManipulators() {
        columnManipulatorsPanel.removeAll();
        columnManipulatorsPanel.updateUI();
    }

    /**
     * Creates the buttons that call the AttributeColumnManipulators.
     */
    private void prepareColumnManipulatorsButtons() {
        AttributeModel attributeModel = Lookup.getDefault().lookup(ProjectController.class).getCurrentWorkspace().getLookup().lookup(AttributeModel.class);
        AttributeTable table;
        AttributeColumn[] columns;
        if (classDisplayed == ClassDisplayed.NODE) {
            table = attributeModel.getNodeTable();
            columns = nodeAvailableColumnsModel.getAvailableColumns();
        } else {
            table = attributeModel.getEdgeTable();
            columns = edgeAvailableColumnsModel.getAvailableColumns();
        }

        DataLaboratoryHelper dlh = DataLaboratoryHelper.getDefault();
        AttributeColumnsManipulator[] manipulators = dlh.getAttributeColumnsManipulators();

        JCommandButtonStrip currentButtonGroup = new JCommandButtonStrip(JCommandButtonStrip.StripOrientation.HORIZONTAL);
        currentButtonGroup.setDisplayState(CommandButtonDisplayState.BIG);
        Integer lastManipulatorType = null;
        for (AttributeColumnsManipulator acm : manipulators) {
            if (lastManipulatorType == null) {
                lastManipulatorType = acm.getType();
            }
            if (lastManipulatorType != acm.getType()) {
                columnManipulatorsPanel.add(currentButtonGroup);
                currentButtonGroup = new JCommandButtonStrip(JCommandButtonStrip.StripOrientation.HORIZONTAL);
                currentButtonGroup.setDisplayState(CommandButtonDisplayState.BIG);
            }
            lastManipulatorType = acm.getType();
            currentButtonGroup.add(prepareJCommandButton(table, columns, acm));
        }
        columnManipulatorsPanel.add(currentButtonGroup);
    }

    /**
     * Creates a JCommandButton for the specified columns of a table and AttributeColumnsManipulator
     * @param table table
     * @param columns Columns
     * @param acm AttributeColumnsManipulator
     * @return Prepared JCommandButton
     */
    private JCommandButton prepareJCommandButton(final AttributeTable table, final AttributeColumn[] columns, final AttributeColumnsManipulator acm) {
        JCommandButton manipulatorButton;
        if (acm.getIcon() != null) {
            manipulatorButton = new JCommandButton(acm.getName(), ImageWrapperResizableIcon.getIcon(acm.getIcon(), new Dimension(16, 16)));
        } else {
            manipulatorButton = new JCommandButton(acm.getName());
        }
        manipulatorButton.setCommandButtonKind(JCommandButton.CommandButtonKind.POPUP_ONLY);
        manipulatorButton.setDisplayState(CommandButtonDisplayState.MEDIUM);
        if (acm.getDescription() != null && !acm.getDescription().isEmpty()) {
            manipulatorButton.setPopupRichTooltip(new RichTooltip(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.RichToolTip.title.text"), acm.getDescription()));
        }

        final ArrayList<AttributeColumn> availableColumns = new ArrayList<AttributeColumn>();
        for (final AttributeColumn column : columns) {
            if (acm.canManipulateColumn(table, column)) {
                availableColumns.add(column);
            }
        }

        if (!availableColumns.isEmpty()) {
            manipulatorButton.setPopupCallback(new PopupPanelCallback() {

                public JPopupPanel getPopupPanel(JCommandButton jcb) {
                    JCommandPopupMenu popup = new JCommandPopupMenu();

                    JCommandMenuButton button;
                    for (final AttributeColumn column : availableColumns) {

                        button = new JCommandMenuButton(column.getTitle(), ImageWrapperResizableIcon.getIcon(ImageUtilities.loadImage("org/gephi/desktop/datalab/resources/column.png"), new Dimension(16, 16)));
                        button.addActionListener(new ActionListener() {

                            public void actionPerformed(ActionEvent e) {
                                DataLaboratoryHelper.getDefault().executeAttributeColumnsManipulator(acm, table, column);
                            }
                        });
                        popup.addMenuButton(button);
                    }
                    return popup;
                }
            });
        } else {
            manipulatorButton.setEnabled(false);
        }

        return manipulatorButton;
    }

    /**
     * Create the special Add new column button.
     */
    private void prepareAddColumnButton() {
        JCommandButtonStrip strip = new JCommandButtonStrip(JCommandButtonStrip.StripOrientation.HORIZONTAL);
        strip.setDisplayState(CommandButtonDisplayState.BIG);
        JCommandButton button = new JCommandButton(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.addColumnButton.text"), ImageWrapperResizableIcon.getIcon(ImageUtilities.loadImage("org/gephi/desktop/datalab/resources/table-insert-column.png", true), new Dimension(16, 16)));
        button.setCommandButtonKind(JCommandButton.CommandButtonKind.ACTION_ONLY);
        button.setDisplayState(CommandButtonDisplayState.BIG);
        if (classDisplayed == ClassDisplayed.NODE) {
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    showAddColumnUI(AddColumnUI.Mode.NODES_TABLE);
                }
            });
        } else {
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    showAddColumnUI(AddColumnUI.Mode.EDGES_TABLE);
                }
            });
        }
        strip.add(button);
        columnManipulatorsPanel.add(strip);
    }

    /**
     * Create the special merge columns button.
     */
    private void prepareMergeColumnsButton() {
        JCommandButtonStrip strip = new JCommandButtonStrip(JCommandButtonStrip.StripOrientation.HORIZONTAL);
        strip.setDisplayState(CommandButtonDisplayState.BIG);
        JCommandButton button = new JCommandButton(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.mergeColumnsButton.text"), ImageWrapperResizableIcon.getIcon(ImageUtilities.loadImage("org/gephi/desktop/datalab/resources/merge.png", true), new Dimension(16, 16)));
        button.setCommandButtonKind(JCommandButton.CommandButtonKind.ACTION_ONLY);
        button.setDisplayState(CommandButtonDisplayState.BIG);
        if (classDisplayed == ClassDisplayed.NODE) {
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    showMergeColumnsUI(MergeColumnsUI.Mode.NODES_TABLE);
                }
            });
        } else {
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    showMergeColumnsUI(MergeColumnsUI.Mode.EDGES_TABLE);
                }
            });
        }
        strip.add(button);
        columnManipulatorsPanel.add(strip);
    }

    private void showAddColumnUI(AddColumnUI.Mode mode) {
        JButton okButton = new JButton(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.dialogs.okButton.text"));
        AddColumnUI addColumnUI = new AddColumnUI();
        addColumnUI.setup(mode);
        addColumnUI.setOkButton(okButton);
        DialogDescriptor dd = new DialogDescriptor(AddColumnUI.createValidationPanel(addColumnUI), addColumnUI.getDisplayName());
        dd.setOptions(new Object[]{okButton, DialogDescriptor.CANCEL_OPTION});
        if (DialogDisplayer.getDefault().notify(dd).equals(okButton)) {
            addColumnUI.execute();
        }
        addColumnUI.unSetup();
    }

    private void showMergeColumnsUI(MergeColumnsUI.Mode mode) {
        JButton okButton = new JButton(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.dialogs.okButton.text"));
        MergeColumnsUI mergeColumnsUI = new MergeColumnsUI();
        mergeColumnsUI.setup(mode);
        mergeColumnsUI.setOkButton(okButton);
        DialogDescriptor dd = new DialogDescriptor(MergeColumnsUI.createValidationPanel(mergeColumnsUI), mergeColumnsUI.getDisplayName());
        dd.setOptions(new Object[]{okButton, DialogDescriptor.CANCEL_OPTION});
        if (DialogDisplayer.getDefault().notify(dd).equals(okButton)) {
            mergeColumnsUI.execute();
        }
    }

    /**************General actions manipulators related methods:***************/
    private void refreshGeneralActionsButtons() {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                clearGeneralActionsButtons();
                prepareGeneralActionsButtons();
            }
        });
    }

    private void clearGeneralActionsButtons() {
        for (JComponent b : generalActionsButtons) {
            controlToolbar.remove(b);
        }
        generalActionsButtons.clear();
        controlToolbar.updateUI();
    }

    /**
     * Adds the buttons for the GeneralActionsManipulators.
     */
    public void prepareGeneralActionsButtons() {
        //Figure out the index to place the buttons, in order to put them between separator 2 and the boxGlue.
        int index = controlToolbar.getComponentIndex(boxGlue);

        final DataLaboratoryHelper dlh = DataLaboratoryHelper.getDefault();
        JButton button;
        for (final GeneralActionsManipulator m : dlh.getGeneralActionsManipulators()) {
            button = new JButton(m.getName(), m.getIcon());
            if (m.getDescription() != null && !m.getDescription().isEmpty()) {
                button.setToolTipText(m.getDescription());
            }
            if (m.canExecute()) {
                button.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        dlh.executeManipulator(m);
                    }
                });
            } else {
                button.setEnabled(false);
            }
            controlToolbar.add(button, index);
            index++;
            generalActionsButtons.add(button);
        }

        //Add plugin general actions as a drop down list:
        final PluginGeneralActionsManipulator[] plugins = dlh.getPluginGeneralActionsManipulators();
        if (plugins != null && plugins.length > 0) {
            JCommandButton pluginsButton = new JCommandButton(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.general.actions.plugins.button.text"), ImageWrapperResizableIcon.getIcon(ImageUtilities.loadImage("org/gephi/desktop/datalab/resources/puzzle--arrow.png", true), new Dimension(16, 16)));
            pluginsButton.setDisplayState(CommandButtonDisplayState.MEDIUM);
            pluginsButton.setCommandButtonKind(JCommandButton.CommandButtonKind.POPUP_ONLY);
            pluginsButton.setPopupCallback(new PopupPanelCallback() {

                public JPopupPanel getPopupPanel(JCommandButton jcb) {
                    JCommandButtonPanel pluginsPanel = new JCommandButtonPanel(CommandButtonDisplayState.BIG);
                    Integer lastManipulatorType = null;
                    int group = 1;
                    pluginsPanel.addButtonGroup(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.general.actions.plugins.group.name", group));
                    for (final PluginGeneralActionsManipulator m : plugins) {
                        if (lastManipulatorType == null) {
                            lastManipulatorType = m.getType();
                        }
                        if (lastManipulatorType != m.getType()) {
                            group++;
                            pluginsPanel.addButtonGroup(NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.general.actions.plugins.group.name", group));
                        }
                        lastManipulatorType = m.getType();
                        pluginsPanel.addButtonToLastGroup(preparePluginGeneralActionsButton(m));
                    }
                    JCommandPopupMenu popup = new JCommandPopupMenu(pluginsPanel, 8, 8);
                    return popup;
                }
            });
            controlToolbar.add(pluginsButton, index);
            generalActionsButtons.add(pluginsButton);
        }
        controlToolbar.updateUI();
    }

    /**
     * Prepare a button for the popup panel for plugin general actions.
     * @param m PluginGeneralActionsManipulator for the button
     * @return JCommandButton for the manipulator
     */
    private JCommandButton preparePluginGeneralActionsButton(final PluginGeneralActionsManipulator m) {
        JCommandButton button = new JCommandButton(m.getName(), m.getIcon() != null ? ImageWrapperResizableIcon.getIcon(ImageUtilities.icon2Image(m.getIcon()), new Dimension(16, 16)) : null);//Convert icon to Image if it is not null
        button.setDisplayState(CommandButtonDisplayState.BIG);
        button.setCommandButtonKind(JCommandButton.CommandButtonKind.ACTION_ONLY);
        if (m.getDescription() != null && !m.getDescription().isEmpty()) {
            button.setToolTipText(m.getDescription());
        }
        if (m.canExecute()) {
            button.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    DataLaboratoryHelper.getDefault().executeManipulator(m);
                }
            });
        } else {
            button.setEnabled(false);
        }
        return button;
    }

    /**
     * This thread is used for processing graphChanged and attributesChanged events.
     * It takes care to only refresh the UI once (the last one) when a lot of events come in a short period of time.
     */
    class RefreshOnceHelperThread extends Thread {

        private static final int CHECK_TIME_INTERVAL = 100;//100 ms.
        private volatile boolean moreEvents = false;
        private boolean refreshTableOnly;

        public RefreshOnceHelperThread() {
            refreshTableOnly = false;
        }

        public RefreshOnceHelperThread(boolean refreshTableOnly) {
            this.refreshTableOnly = refreshTableOnly;
        }

        @Override
        public void run() {
            try {
                do {
                    moreEvents = false;
                    Thread.sleep(CHECK_TIME_INTERVAL);
                } while (moreEvents);
                if (refreshTableOnly) {
                    DataTableTopComponent.this.refreshTable();
                } else {
                    DataTableTopComponent.this.refreshAll();
                }
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
        }

        public void eventAttended() {
            this.moreEvents = true;
        }
    }

    /**
     * To react to Ctrl+F keys combination calling Search/Replace general action
     * (and nodes/edges context menu mappings)
     * @param event
     */
    public void eventDispatched(AWTEvent event) {
        KeyEvent evt = (KeyEvent) event;

        if (evt.getID() == KeyEvent.KEY_RELEASED && (evt.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0) {
            DataLaboratoryHelper dlh = DataLaboratoryHelper.getDefault();
            if (evt.getKeyCode() == KeyEvent.VK_F) {//Call Search replace with 'F' without general actions key mappings support:
                GeneralActionsManipulator gam = dlh.getGeneralActionsManipulatorByName("SearchReplace");
                if (gam != null) {
                    dlh.executeManipulator(gam);
                }
                evt.consume();
            } else {//Nodes/edges mappings:
                if (classDisplayed == ClassDisplayed.NODE) {
                    final ContextMenuItemManipulator item = nodesActionMappings.get(evt.getKeyCode());
                    if (item != null) {
                        Node[] nodes = nodeTable.getNodesFromSelectedRows();
                        if (nodes.length > 0) {
                            ((NodesManipulator) item).setup(nodes, nodes[0]);
                            if (item.isAvailable() && item.canExecute()) {
                                DataLaboratoryHelper.getDefault().executeManipulator(item);
                            }
                        }
                        evt.consume();
                    }
                } else if (classDisplayed == ClassDisplayed.EDGE) {
                    final ContextMenuItemManipulator item = edgesActionMappings.get(evt.getKeyCode());
                    if (item != null) {
                        Edge[] edges = edgeTable.getEdgesFromSelectedRows();
                        if (edges.length > 0) {
                            ((EdgesManipulator) item).setup(edges, edges[0]);
                            if (item.isAvailable() && item.canExecute()) {
                                DataLaboratoryHelper.getDefault().executeManipulator(item);
                            }
                        }
                        evt.consume();
                    }
                }
            }
        }
    }

    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        elementGroup = new javax.swing.ButtonGroup();
        controlToolbar = new javax.swing.JToolBar();
        nodesButton = new javax.swing.JToggleButton();
        edgesButton = new javax.swing.JToggleButton();
        separator = new javax.swing.JToolBar.Separator();
        configurationButton = new javax.swing.JButton();
        separator2 = new javax.swing.JToolBar.Separator();
        boxGlue = new javax.swing.JLabel();
        labelFilter = new org.jdesktop.swingx.JXLabel();
        filterTextField = new javax.swing.JTextField();
        columnComboBox = new javax.swing.JComboBox();
        availableColumnsButton = new javax.swing.JButton();
        tableScrollPane = new javax.swing.JScrollPane();
        bannerPanel = new javax.swing.JPanel();
        labelBanner = new javax.swing.JLabel();
        refreshButton = new javax.swing.JButton();
        attributeColumnsScrollPane = new javax.swing.JScrollPane();
        columnManipulatorsPanel = new javax.swing.JPanel();

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

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

        elementGroup.add(nodesButton);
        org.openide.awt.Mnemonics.setLocalizedText(nodesButton, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.nodesButton.text")); // NOI18N
        nodesButton.setFocusable(false);
        nodesButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        nodesButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        nodesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nodesButtonActionPerformed(evt);
            }
        });
        controlToolbar.add(nodesButton);

        elementGroup.add(edgesButton);
        org.openide.awt.Mnemonics.setLocalizedText(edgesButton, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.edgesButton.text")); // NOI18N
        edgesButton.setFocusable(false);
        edgesButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        edgesButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        edgesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                edgesButtonActionPerformed(evt);
            }
        });
        controlToolbar.add(edgesButton);
        controlToolbar.add(separator);

        configurationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/desktop/datalab/resources/gear-small.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(configurationButton, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.configurationButton.text")); // NOI18N
        configurationButton.setFocusable(false);
        configurationButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        configurationButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        configurationButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                configurationButtonActionPerformed(evt);
            }
        });
        controlToolbar.add(configurationButton);
        controlToolbar.add(separator2);

        org.openide.awt.Mnemonics.setLocalizedText(boxGlue, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.boxGlue.text")); // NOI18N
        boxGlue.setMaximumSize(new java.awt.Dimension(32767, 32767));
        controlToolbar.add(boxGlue);

        org.openide.awt.Mnemonics.setLocalizedText(labelFilter, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.labelFilter.text")); // NOI18N
        controlToolbar.add(labelFilter);

        filterTextField.setText(org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.filterTextField.text")); // NOI18N
        filterTextField.setToolTipText(org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.filterTextField.toolTipText")); // NOI18N
        filterTextField.setMaximumSize(new java.awt.Dimension(1000, 30));
        filterTextField.setPreferredSize(new java.awt.Dimension(150, 20));
        controlToolbar.add(filterTextField);

        columnComboBox.setMaximumSize(new java.awt.Dimension(2000, 20));
        columnComboBox.setPreferredSize(new java.awt.Dimension(120, 20));
        controlToolbar.add(columnComboBox);

        availableColumnsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/desktop/datalab/resources/light-bulb.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(availableColumnsButton, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.availableColumnsButton.text")); // NOI18N
        availableColumnsButton.setToolTipText(org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.availableColumnsButton.toolTipText")); // NOI18N
        availableColumnsButton.setFocusable(false);
        availableColumnsButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        availableColumnsButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        availableColumnsButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                availableColumnsButtonActionPerformed(evt);
            }
        });
        controlToolbar.add(availableColumnsButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        add(controlToolbar, gridBagConstraints);

        tableScrollPane.setMinimumSize(new java.awt.Dimension(100, 100));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(tableScrollPane, gridBagConstraints);

        bannerPanel.setBackground(new java.awt.Color(178, 223, 240));
        bannerPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));
        bannerPanel.setLayout(new java.awt.GridBagLayout());

        labelBanner.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/desktop/datalab/resources/info.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(labelBanner, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.labelBanner.text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 5, 2, 0);
        bannerPanel.add(labelBanner, gridBagConstraints);

        org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(DataTableTopComponent.class, "DataTableTopComponent.refreshButton.text")); // NOI18N
        refreshButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(1, 0, 1, 1);
        bannerPanel.add(refreshButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        add(bannerPanel, gridBagConstraints);

        attributeColumnsScrollPane.setMinimumSize(new java.awt.Dimension(200, 100));
        attributeColumnsScrollPane.setPreferredSize(new java.awt.Dimension(200, 100));

        columnManipulatorsPanel.setMinimumSize(new java.awt.Dimension(200, 100));
        columnManipulatorsPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 25, 20));
        attributeColumnsScrollPane.setViewportView(columnManipulatorsPanel);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        add(attributeColumnsScrollPane, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
        refreshCurrentTable();
}//GEN-LAST:event_refreshButtonActionPerformed

    private void edgesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_edgesButtonActionPerformed
        selectEdgesTable();
}//GEN-LAST:event_edgesButtonActionPerformed

    private void nodesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nodesButtonActionPerformed
        selectNodesTable();
}//GEN-LAST:event_nodesButtonActionPerformed

    private void configurationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configurationButtonActionPerformed
        DialogDescriptor dd = new DialogDescriptor(new ConfigurationPanel(this), NbBundle.getMessage(DataTableTopComponent.class, "ConfigurationPanel.title"));
        dd.setOptions(new Object[]{DialogDescriptor.OK_OPTION});
        DialogDisplayer.getDefault().notify(dd);

        //Save preferences:
        NbPreferences.forModule(DataTableTopComponent.class).putBoolean(DATA_LABORATORY_ONLY_VISIBLE, visibleOnly);
        NbPreferences.forModule(DataTableTopComponent.class).putBoolean(DATA_LABORATORY_SPARKLINES, useSparklines);
        NbPreferences.forModule(DataTableTopComponent.class).putBoolean(DATA_LABORATORY_TIME_INTERVAL_GRAPHICS, timeIntervalGraphics);
        NbPreferences.forModule(DataTableTopComponent.class).putBoolean(DATA_LABORATORY_EDGES_NODES_LABELS, showEdgesNodesLabels);
    }//GEN-LAST:event_configurationButtonActionPerformed

    private void availableColumnsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_availableColumnsButtonActionPerformed
        AttributeTable table;
        AvailableColumnsModel availableColumnsModel;
        if (classDisplayed == classDisplayed.NODE) {
            table = Lookup.getDefault().lookup(AttributeController.class).getModel().getNodeTable();
        } else {
            table = Lookup.getDefault().lookup(AttributeController.class).getModel().getEdgeTable();
        }
        availableColumnsModel = getTableAvailableColumnsModel(table);
        DialogDescriptor dd = new DialogDescriptor(new AvailableColumnsPanel(table, availableColumnsModel).getValidationPanel(), NbBundle.getMessage(DataTableTopComponent.class, "AvailableColumnsPanel.title"));
        dd.setOptions(new Object[]{DialogDescriptor.OK_OPTION});
        DialogDisplayer.getDefault().notify(dd);
        refreshAllOnce();
        availableColumnsButton.setIcon(ImageUtilities.loadImageIcon("org/gephi/desktop/datalab/resources/light-bulb.png", true));
    }//GEN-LAST:event_availableColumnsButtonActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane attributeColumnsScrollPane;
    private javax.swing.JButton availableColumnsButton;
    private javax.swing.JPanel bannerPanel;
    private javax.swing.JLabel boxGlue;
    private javax.swing.JComboBox columnComboBox;
    private javax.swing.JPanel columnManipulatorsPanel;
    private javax.swing.JButton configurationButton;
    private javax.swing.JToolBar controlToolbar;
    private javax.swing.JToggleButton edgesButton;
    private javax.swing.ButtonGroup elementGroup;
    private javax.swing.JTextField filterTextField;
    private javax.swing.JLabel labelBanner;
    private org.jdesktop.swingx.JXLabel labelFilter;
    private javax.swing.JToggleButton nodesButton;
    private javax.swing.JButton refreshButton;
    private javax.swing.JToolBar.Separator separator;
    private javax.swing.JToolBar.Separator separator2;
    private javax.swing.JScrollPane tableScrollPane;
    // End of variables declaration//GEN-END:variables

    /**
     * Gets default instance. Do not use directly: reserved for *.settings files only,
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
     * To obtain the singleton instance, use {@link #findInstance}.
     */
    public static synchronized DataTableTopComponent getDefault() {
        if (instance == null) {
            instance = new DataTableTopComponent();
        }
        return instance;
    }

    /**
     * Obtain the DataTableTopComponent instance. Never call {@link #getDefault} directly!
     */
    public static synchronized DataTableTopComponent findInstance() {
        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
        if (win == null) {
            Logger.getLogger(DataTableTopComponent.class.getName()).warning(
                    "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
            return getDefault();
        }
        if (win instanceof DataTableTopComponent) {
            return (DataTableTopComponent) win;
        }
        Logger.getLogger(DataTableTopComponent.class.getName()).warning(
                "There seem to be multiple components with the '" + PREFERRED_ID
                + "' ID. That is a potential source of errors and unexpected behavior.");
        return getDefault();
    }

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_ALWAYS;
    }

    @Override
    public void componentOpened() {
        refreshAllOnce();
    }

    @Override
    public void componentClosed() {
    }

    @Override
    protected void componentActivated() {
        super.componentActivated();
        java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
    }

    @Override
    protected void componentDeactivated() {
        super.componentDeactivated();
        java.awt.Toolkit.getDefaultToolkit().removeAWTEventListener(this);
    }

    /** replaces this in object stream */
    @Override
    public Object writeReplace() {
        return new ResolvableHelper();
    }

    @Override
    protected String preferredID() {
        return PREFERRED_ID;
    }

    final static class ResolvableHelper implements Serializable {

        private static final long serialVersionUID = 1L;

        public Object readResolve() {
            return DataTableTopComponent.getDefault();
        }
    }

    /**
     * <p>Exports a JTable to a CSV file showing first a dialog to select the file to write.</p>
     * @param parent Parent window
     * @param table Table to export
     * @param separator Separator to use for separating values of a row in the CSV file. If null ',' will be used.
     * @param charset Charset encoding for the file
     * @param columnsToExport Indicates the indexes of the columns to export. All columns will be exported if null
     */
    public static void exportTableAsCSV(JComponent parent, JTable table, Character separator, Charset charset, Integer[] columnsToExport) {
        String lastPath = NbPreferences.forModule(TableCSVExporter.class).get(LAST_PATH, null);
        final JFileChooser chooser = new JFileChooser(lastPath);
        chooser.setAcceptAllFileFilterUsed(false);
        DialogFileFilter dialogFileFilter = new DialogFileFilter(NbBundle.getMessage(TableCSVExporter.class, "TableCSVExporter.filechooser.csvDescription"));
        dialogFileFilter.addExtension("csv");
        chooser.addChoosableFileFilter(dialogFileFilter);
        File selectedFile = new File(chooser.getCurrentDirectory(), "table.csv");
        chooser.setSelectedFile(selectedFile);
        int returnFile = chooser.showSaveDialog(null);
        if (returnFile != JFileChooser.APPROVE_OPTION) {
            return;
        }
        File file = chooser.getSelectedFile();

        if (!file.getPath().endsWith(".csv")) {
            file = new File(file.getPath() + ".csv");
        }

        //Save last path
        String defaultDirectory = file.getParentFile().getAbsolutePath();
        NbPreferences.forModule(TableCSVExporter.class).put(LAST_PATH, defaultDirectory);
        try {
            TableCSVExporter.writeCSVFile(table, file, separator, charset, columnsToExport);
            JOptionPane.showMessageDialog(parent, NbBundle.getMessage(TableCSVExporter.class, "TableCSVExporter.dialog.success"));
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(parent, NbBundle.getMessage(TableCSVExporter.class, "TableCSVExporter.dialog.error"), NbBundle.getMessage(TableCSVExporter.class, "TableCSVExporter.dialog.error.title"), JOptionPane.ERROR_MESSAGE);
        }
    }
    private static final String LAST_PATH = "TableCSVExporter_Save_Last_Path";
}
TOP

Related Classes of org.gephi.desktop.datalab.DataTableTopComponent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.