/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> 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.ranking; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.imageio.ImageIO; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableModel; import org.gephi.graph.api.Edge; import org.gephi.graph.api.Node; import org.gephi.ranking.api.ColorTransformer; import org.gephi.ranking.api.NodeRanking; import org.gephi.ranking.api.RankingController; import org.gephi.ranking.api.RankingResult; import org.gephi.ranking.api.SizeTransformer; import org.gephi.ui.utils.DialogFileFilter; import org.gephi.ui.utils.UIUtils; import org.jdesktop.swingx.JXTable; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.openide.windows.WindowManager; /** * * @author Mathieu Bastian */ public class ResultListPanel extends JScrollPane implements LookupListener { //Const private final String LAST_PATH = "ResultListPanel_TableScreenshot_Last_Path"; private final String LAST_PATH_DEFAULT = "ResultListPanel_TableScreenshot_Last_Path_Default"; //Variable private Lookup.Result<RankingResult> result; private JXTable table; private JPopupMenu popupMenu; public ResultListPanel() { //Lookup listener RankingController rankingController = Lookup.getDefault().lookup(RankingController.class); Lookup eventBus = rankingController.getEventBus(); result = eventBus.lookupResult(RankingResult.class); result.addLookupListener(this); initTable(); initTablePopup(); } public void resultChanged(LookupEvent ev) { Lookup.Result<RankingResult> r = (Lookup.Result<RankingResult>) ev.getSource(); RankingResult[] res = r.allInstances().toArray(new RankingResult[0]); if (res.length > 0) { RankingResult lastResult = res[0]; if (isVisible()) { fetchTable(lastResult); } } } private void initTable() { table = new JXTable(); table.putClientProperty(JXTable.USE_DTCR_COLORMEMORY_HACK, Boolean.FALSE); //Disable strange hack that overwrite JLabel's setBackground() by a Highlighter color table.setColumnControlVisible(false); table.setEditable(false); table.setSortable(false); table.setRolloverEnabled(false); table.setShowHorizontalLines(false); table.setShowVerticalLines(false); table.setRowSelectionAllowed(false); table.setColumnSelectionAllowed(false); table.setCellSelectionEnabled(false); //table.setHighlighters(HighlighterFactory.createAlternateStriping()); table.getTableHeader().setReorderingAllowed(false); table.getTableHeader().setResizingAllowed(true); setViewportView(table); } private void initTablePopup() { popupMenu = new JPopupMenu(); JMenuItem screenshotItem = new JMenuItem(NbBundle.getMessage(ResultListPanel.class, "ResultListPanel.action.tablescreenshot")); screenshotItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { BufferedImage image = UIUtils.createComponentScreenshot(table); writeImage(image); } catch (Exception ex) { String msg = NbBundle.getMessage(ResultListPanel.class, "ResultListPanel.tablescreenshot.error", new Object[]{ex.getClass().getSimpleName(), ex.getLocalizedMessage(), ex.getStackTrace()[0].getClassName(), ex.getStackTrace()[0].getLineNumber()}); JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), msg, NbBundle.getMessage(ResultListPanel.class, "ResultListPanel.tablescreenshot.error.title"), JOptionPane.ERROR_MESSAGE); ex.printStackTrace(); } } }); popupMenu.add(screenshotItem); table.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { showPopup(e); } @Override public void mouseReleased(MouseEvent e) { showPopup(e); } private void showPopup(MouseEvent e) { if (e.isPopupTrigger()) { popupMenu.show(e.getComponent(), e.getX(), e.getY()); } } }); } private void writeImage(BufferedImage image) throws Exception { //Get last directory String lastPathDefault = NbPreferences.forModule(ResultListPanel.class).get(LAST_PATH_DEFAULT, null); String lastPath = NbPreferences.forModule(ResultListPanel.class).get(LAST_PATH, lastPathDefault); final JFileChooser chooser = new JFileChooser(lastPath); chooser.setAcceptAllFileFilterUsed(false); chooser.setDialogTitle(NbBundle.getMessage(ResultListPanel.class, "ResultListPanel.tablescreenshot.filechooser.title")); DialogFileFilter dialogFileFilter = new DialogFileFilter(NbBundle.getMessage(ResultListPanel.class, "ResultListPanel.tablescreenshot.filechooser.pngDescription")); dialogFileFilter.addExtension("png"); chooser.addChoosableFileFilter(dialogFileFilter); File selectedFile = new File(chooser.getCurrentDirectory(), "rank_table.png"); chooser.setSelectedFile(selectedFile); int returnFile = chooser.showSaveDialog(null); if (returnFile != JFileChooser.APPROVE_OPTION) { return; } selectedFile = chooser.getSelectedFile(); if (!selectedFile.getPath().endsWith(".png")) { selectedFile = new File(selectedFile.getPath() + ".png"); } //Save last path String defaultDirectory = selectedFile.getParentFile().getAbsolutePath(); NbPreferences.forModule(ResultListPanel.class).put(LAST_PATH, defaultDirectory); String format = "png"; if (!ImageIO.write(image, format, selectedFile)) { throw new IOException("Unsupported file format"); } } private void fetchTable(RankingResult result) { List<RankingResult.RankingResultLine> results = new ArrayList<RankingResult.RankingResultLine>(); results.addAll(result.getResultLines()); Collections.reverse(results); boolean nodeRanking = result.getRanking() instanceof NodeRanking; List<RankCell> cells = new ArrayList<RankCell>(); List<String> labels = new ArrayList<String>(); for (RankingResult.RankingResultLine line : results) { if (line.getResult() != null) { if (result.getTransformer() instanceof ColorTransformer) { RankCellColor rankCellColor = new RankCellColor((Color) line.getResult(), line.getRank()); cells.add(rankCellColor); } else if (result.getTransformer() instanceof SizeTransformer) { RankCellSize rankCellSize = new RankCellSize((Float) line.getResult(), line.getRank()); cells.add(rankCellSize); } else { } if (nodeRanking) { Node n = (Node) line.getTarget(); labels.add(n.getNodeData().getLabel()); } else { Edge e = (Edge) line.getTarget(); labels.add(e.getEdgeData().getLabel()); } } } ResultListTableModel model = new ResultListTableModel(cells.toArray(new RankCell[0]), labels.toArray(new String[0])); table.setDefaultRenderer(RankCell.class, new RankCellRenderer()); table.setModel(model); } private class ResultListTableModel implements TableModel { private RankCell[] ranks; private String[] labels; public ResultListTableModel(RankCell[] ranks, String[] labels) { this.ranks = ranks; this.labels = labels; } public int getRowCount() { return labels.length; } public int getColumnCount() { return 2; } public String getColumnName(int columnIndex) { if (columnIndex == 0) { return "Rank"; } else { return "Label"; } } public Class<?> getColumnClass(int columnIndex) { if (columnIndex == 0) { return RankCell.class; } else { return String.class; } } public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public Object getValueAt(int rowIndex, int columnIndex) { if (columnIndex == 0) { return ranks[rowIndex]; } else { return labels[rowIndex]; } } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columnIndex == 0) { ranks[rowIndex] = (RankCell) aValue; } else { labels[rowIndex] = (String) aValue; } } public void addTableModelListener(TableModelListener l) { } public void removeTableModelListener(TableModelListener l) { } } private static interface RankCell { public void render(JLabel label); } private static class RankCellColor implements RankCell { private Color color; private Object rank; public RankCellColor(Color color, Object rank) { this.color = color; this.rank = rank; } public void render(JLabel label) { label.setBackground(color); label.setForeground(UIUtils.getForegroundColorForBackground(color)); label.setText(rank.toString()); } } private static class RankCellSize implements RankCell { private Float size; private Object rank; public RankCellSize(Float size, Object rank) { this.size = size; this.rank = rank; } public void render(JLabel label) { label.setText(rank.toString()); } } private static class RankCellRenderer extends DefaultTableCellRenderer { public RankCellRenderer() { setHorizontalAlignment(SwingConstants.RIGHT); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { RankCell rankCell = (RankCell) value; rankCell.render(this); return this; } } }