package net.seninp.grammarviz.view; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import javax.swing.table.TableColumnModel; import javax.swing.table.TableRowSorter; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.JXTableHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.seninp.grammarviz.model.GrammarVizMessage; import net.seninp.grammarviz.session.UserSession; import net.seninp.grammarviz.view.table.GrammarvizRulesTableColumns; import net.seninp.grammarviz.view.table.GrammarvizRulesTableModel; /** * * Implements the rules panel. * * @author Manfred Lerner, seninp * */ public class GrammarRulesPanel extends JPanel implements ListSelectionListener, PropertyChangeListener { /** Fancy serial. */ private static final long serialVersionUID = -2710973854572981568L; public static final String FIRING_PROPERTY = "selectedRows"; private GrammarvizRulesTableModel sequiturTableModel = new GrammarvizRulesTableModel(); private JXTable sequiturTable; private UserSession session; private JScrollPane sequiturRulesPane; private ArrayList<String> selectedRules; private boolean acceptListEvents; // static block - we instantiate the logger // private static final Logger LOGGER = LoggerFactory.getLogger(GrammarRulesPanel.class); /* * * Comparator for the sorting of the Expanded Sequitur Rules Easy logic: sort by the length of the * Expanded Sequitur Rules */ private Comparator<String> expandedRuleComparator = new Comparator<String>() { public int compare(String s1, String s2) { return s1.length() - s2.length(); } }; /** * Constructor. */ public GrammarRulesPanel() { super(); this.sequiturTableModel = new GrammarvizRulesTableModel(); this.sequiturTable = new JXTable() { private static final long serialVersionUID = 2L; @Override protected JTableHeader createDefaultTableHeader() { return new JXTableHeader(columnModel) { private static final long serialVersionUID = 1L; @Override public void updateUI() { super.updateUI(); // need to do in updateUI to survive toggling of LAF if (getDefaultRenderer() instanceof JLabel) { ((JLabel) getDefaultRenderer()).setHorizontalAlignment(JLabel.CENTER); } } }; } }; this.sequiturTable.setModel(sequiturTableModel); // this.sequiturTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.sequiturTable.getSelectionModel() .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); this.sequiturTable.setShowGrid(false); this.sequiturTable.getSelectionModel().addListSelectionListener(this); @SuppressWarnings("unused") org.jdesktop.swingx.renderer.DefaultTableRenderer renderer = (org.jdesktop.swingx.renderer.DefaultTableRenderer) sequiturTable .getDefaultRenderer(String.class); // Make some columns wider than the rest, so that the info fits in. TableColumnModel columnModel = sequiturTable.getColumnModel(); columnModel.getColumn(GrammarvizRulesTableColumns.RULE_NUMBER.ordinal()).setPreferredWidth(30); columnModel.getColumn(GrammarvizRulesTableColumns.RULE_USE_FREQUENCY.ordinal()) .setPreferredWidth(40); columnModel.getColumn(GrammarvizRulesTableColumns.SEQUITUR_RULE.ordinal()) .setPreferredWidth(100); columnModel.getColumn(GrammarvizRulesTableColumns.EXPANDED_SEQUITUR_RULE.ordinal()) .setPreferredWidth(150); columnModel.getColumn(GrammarvizRulesTableColumns.RULE_MEAN_LENGTH.ordinal()) .setPreferredWidth(120); TableRowSorter<GrammarvizRulesTableModel> sorter = new TableRowSorter<GrammarvizRulesTableModel>( sequiturTableModel); sequiturTable.setRowSorter(sorter); sorter.setComparator(GrammarvizRulesTableColumns.EXPANDED_SEQUITUR_RULE.ordinal(), expandedRuleComparator); DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer(); rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT); this.sequiturTable.getColumnModel().getColumn(5).setCellRenderer(rightRenderer); this.sequiturRulesPane = new JScrollPane(sequiturTable); } /** * create the panel with the sequitur rules table * * @return sequitur panel */ public void resetPanel() { // cleanup all the content this.removeAll(); this.add(sequiturRulesPane); this.acceptListEvents = false; sequiturTableModel.update(this.session.chartData.getGrammarRules()); this.acceptListEvents = true; this.revalidate(); this.repaint(); } /** * @return sequitur table model */ public GrammarvizRulesTableModel getSequiturTableModel() { return sequiturTableModel; } /** * @return sequitur table */ public JTable getSequiturTable() { return sequiturTable; } @Override public void valueChanged(ListSelectionEvent arg) { if (!arg.getValueIsAdjusting() && this.acceptListEvents) { int[] rows = sequiturTable.getSelectedRows(); LOGGER.debug("Selected ROWS: " + Arrays.toString(rows)); ArrayList<String> rules = new ArrayList<String>(rows.length); for (int i = 0; i < rows.length; i++) { int ridx = rows[i]; String rule = String.valueOf( sequiturTable.getValueAt(ridx, GrammarvizRulesTableColumns.RULE_NUMBER.ordinal())); rules.add(rule); } this.firePropertyChange(FIRING_PROPERTY, this.selectedRules, rules); this.selectedRules = rules; } } /** * Resets the selection and resorts the table by the Rules. */ public void resetSelection() { // TODO: there is the bug. commented out. sequiturTable.getSelectionModel().clearSelection(); // sequiturTable.setSortOrder(0, SortOrder.ASCENDING); } public void propertyChange(PropertyChangeEvent event) { String prop = event.getPropertyName(); if (prop.equalsIgnoreCase(GrammarVizMessage.MAIN_CHART_CLICKED_MESSAGE)) { String rule = (String) event.getNewValue(); for (int row = 0; row <= sequiturTable.getRowCount() - 1; row++) { for (int col = 0; col <= sequiturTable.getColumnCount() - 1; col++) { if (rule.equals(this.session.chartData.convert2OriginalSAXAlphabet('1', sequiturTable.getValueAt(row, col).toString()))) { sequiturTable.scrollRectToVisible(sequiturTable.getCellRect(row, 0, true)); sequiturTable.setRowSelectionInterval(row, row); } } } } } /** * Clears the panel. */ public void clearPanel() { this.acceptListEvents = false; this.removeAll(); sequiturTableModel.update(null); this.validate(); this.repaint(); this.acceptListEvents = true; } public void setChartData(UserSession session) { clearPanel(); this.session = session; resetPanel(); } }