001package jmri.jmrix.can.cbus.swing.nodeconfig;
002
003import java.awt.BorderLayout;
004import java.awt.Component;
005import java.awt.Dimension;
006import java.text.DateFormat;
007import java.text.SimpleDateFormat;
008import javax.swing.*;
009import javax.swing.event.TableModelEvent;
010import javax.swing.table.TableCellRenderer;
011import javax.swing.table.TableRowSorter;
012import jmri.jmrix.can.CanSystemConnectionMemo;
013import jmri.jmrix.can.cbus.CbusConfigurationManager;
014import jmri.jmrix.can.cbus.node.CbusNodeTableDataModel;
015import jmri.jmrix.can.cbus.swing.CbusCommonSwing;
016import jmri.util.ThreadingUtil;
017import jmri.util.swing.XTableColumnModel;
018import jmri.util.table.*;
019
020// import org.slf4j.Logger;
021// import org.slf4j.LoggerFactory;
022
023/**
024 * Pane providing a CBUS node table.
025 *
026 * @author Steve Young (C) 2019
027 * @see CbusNodeTableDataModel
028 *
029 * @since 2.99.2
030 */
031public class CbusNodeTablePane extends JPanel {
032
033    private CbusNodeTableDataModel nodeModel;
034    protected JTable nodeTable;
035
036    private TableRowSorter<CbusNodeTableDataModel> sorter;
037
038    private final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm EEE d MMM");
039
040    public void initComponents(CanSystemConnectionMemo memo) {
041        nodeModel = memo.get(CbusConfigurationManager.class)
042            .provide(CbusNodeTableDataModel.class);
043
044        init();
045
046    }
047
048    public CbusNodeTablePane() {
049        super();
050    }
051
052    public void init() {
053
054        nodeTable = new JTableWithColumnToolTips(nodeModel,CbusNodeTableDataModel.COLUMNTOOLTIPS){
055
056            @Override
057            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
058                int modelRow = convertRowIndexToModel(row);
059                int modelColumn = convertColumnIndexToModel(column);
060                Component comp = super.prepareRenderer(renderer, row, column);
061                if (!isRowSelected(modelRow) &&
062                        ( modelColumn ==  CbusNodeTableDataModel.NODE_IN_LEARN_MODE_COLUMN
063                        || modelColumn ==  CbusNodeTableDataModel.NODE_EVENT_INDEX_VALID_COLUMN
064                        )) {
065                    comp.setBackground(( row % 2 == 0 ) ? this.getBackground() : jmri.jmrix.can.cbus.swing.CbusCommonSwing.WHITE_GREEN );
066                }
067                return comp;
068            }
069        };
070
071        // Use XTableColumnModel so we can control which columns are visible
072        XTableColumnModel tcm = new XTableColumnModel();
073        nodeTable.setColumnModel(tcm);
074
075        sorter = new TableRowSorter<>(nodeModel);
076        nodeTable.setRowSorter(sorter);
077
078        // configure items for GUI
079        CbusCommonSwing.configureTable(nodeTable);
080
081        tcm.getColumn(CbusNodeTableDataModel.NODE_NUMBER_COLUMN).setCellRenderer(getRenderer());
082        tcm.getColumn(CbusNodeTableDataModel.NODE_TYPE_NAME_COLUMN).setCellRenderer(getRenderer());
083        tcm.getColumn(CbusNodeTableDataModel.NODE_USER_NAME_COLUMN).setCellRenderer(getRenderer());
084        tcm.getColumn(CbusNodeTableDataModel.NODE_EVENTS_COLUMN).setCellRenderer(getRenderer());
085        tcm.getColumn(CbusNodeTableDataModel.COMMAND_STAT_NUMBER_COLUMN).setCellRenderer(getRenderer());
086        tcm.getColumn(CbusNodeTableDataModel.CANID_COLUMN).setCellRenderer(getRenderer());
087        tcm.getColumn(CbusNodeTableDataModel.NODE_TOTAL_BYTES_COLUMN).setCellRenderer(getRenderer());
088        tcm.getColumn(CbusNodeTableDataModel.BYTES_REMAINING_COLUMN).setCellRenderer(new ProgressCellRender(CbusCommonSwing.WHITE_GREEN));
089        tcm.getColumn(CbusNodeTableDataModel.NUMBER_BACKUPS_COLUMN).setCellRenderer(getRenderer());
090        tcm.getColumn(CbusNodeTableDataModel.SESSION_BACKUP_STATUS_COLUMN).setCellRenderer(getRenderer());
091        tcm.getColumn(CbusNodeTableDataModel.LAST_BACKUP_COLUMN).setCellRenderer(getRenderer());
092
093        tcm.getColumn(CbusNodeTableDataModel.NODE_RESYNC_BUTTON_COLUMN).setCellEditor(new ButtonEditor(new JButton()));
094        tcm.getColumn(CbusNodeTableDataModel.NODE_RESYNC_BUTTON_COLUMN).setCellRenderer(new ButtonRenderer());
095
096        tcm.getColumn(CbusNodeTableDataModel.NODE_EDIT_BUTTON_COLUMN).setCellEditor(new ButtonEditor(new JButton()));
097        tcm.getColumn(CbusNodeTableDataModel.NODE_EDIT_BUTTON_COLUMN).setCellRenderer(new ButtonRenderer());
098
099       ((JComponent) tcm.getColumn(CbusNodeTableDataModel.NODE_RESYNC_BUTTON_COLUMN).getCellRenderer()).setOpaque(false);
100       ((JComponent) tcm.getColumn(CbusNodeTableDataModel.NODE_EDIT_BUTTON_COLUMN).getCellRenderer()).setOpaque(false);
101
102        setLayout(new BorderLayout());
103        JScrollPane eventScroll = new JScrollPane(nodeTable);
104        eventScroll.setVisible(true);
105        eventScroll.setPreferredSize(new Dimension(300, 40));
106        add(eventScroll);
107
108        validate();
109        repaint();
110
111        nodeModel.addTableModelListener((TableModelEvent e) -> {
112            if (nodeModel.getRequestNodeRowToDisplay()>-1) {
113                setRowToNode();
114            }
115        });
116        nodeModel.fireTableDataChanged();
117    }
118
119    private void setRowToNode(){
120        ThreadingUtil.runOnGUIEventually(() -> {
121            int newRow = nodeModel.getRequestNodeRowToDisplay();
122            if ( newRow>-1 ) {
123                nodeTable.setRowSelectionInterval(newRow, newRow);
124                nodeTable.scrollRectToVisible(nodeTable.getCellRect(newRow, 0, true));
125                nodeModel.setRequestNodeDisplay(-1);
126            }
127        });
128    }
129
130    /**
131     * Cell Renderer for string table columns
132     */
133    private TableCellRenderer getRenderer() {
134        return new TableCellRenderer() {
135            JTextField f = new JTextField();
136
137            @Override
138            public Component getTableCellRendererComponent(
139                JTable table, Object arg1, boolean isSelected, boolean hasFocus,
140                int row, int col) {
141                String string;
142                if(arg1 != null){
143                    string = arg1.toString();
144                    f.setText(string);
145                    f.setHorizontalAlignment(JTextField.CENTER);
146                    CbusCommonSwing.hideNumbersLessThan(0, string, f);
147                    CbusCommonSwing.setCellFromDate(arg1,f,DATE_FORMAT);
148                    CbusCommonSwing.setCellFromBackupEnum(arg1,f);
149
150                } else {
151                    f.setText("");
152                }
153
154                CbusCommonSwing.setCellBackground(isSelected, f, table,row);
155                CbusCommonSwing.setCellFocus(hasFocus, f, table);
156
157                return f;
158            }
159        };
160    }
161
162    public void dispose() {
163        nodeTable = null;
164    }
165
166    // private final static Logger log = LoggerFactory.getLogger(CbusNodeTablePane.class);
167
168}