001package jmri.jmrix.can.cbus.swing.nodeconfig; 002 003import java.awt.BorderLayout; 004import java.awt.Color; 005import java.awt.Component; 006import java.awt.Font; 007import java.awt.event.MouseEvent; 008import java.util.EventObject; 009 010import javax.swing.*; 011import javax.swing.event.ChangeEvent; 012import javax.swing.event.ChangeListener; 013import javax.swing.table.TableCellEditor; 014import javax.swing.table.TableCellRenderer; 015import javax.swing.table.TableColumnModel; 016 017import jmri.jmrix.can.cbus.node.CbusNode; 018import jmri.jmrix.can.cbus.node.CbusNodeNVTableDataModel; 019 020import org.slf4j.Logger; 021import org.slf4j.LoggerFactory; 022 023/** 024 * Pane providing a Cbus event table. Menu code copied from BeanTableFrame. 025 * 026 * @author Steve Young (C) 2019 027 * 028 * @since 4.15.5 029 */ 030public class CbusNodeNVEditTablePane extends jmri.jmrix.can.swing.CanPanel { 031 032 private final CbusNodeNVTableDataModel nodeNVModel; 033 private int largerFont; 034 private final JTable nodeNvTable; 035 private JScrollPane eventVarScroll; 036 private JPanel pane1; 037 038 protected CbusNodeNVEditTablePane( CbusNodeNVTableDataModel nVModel ) { 039 super(); 040 nodeNVModel = nVModel; 041 nodeNvTable = new JTable(nodeNVModel); 042 043 } 044 045 protected void setNode(CbusNode node ) { 046 047 if (pane1==null){ 048 initTable(); 049 } 050 051 CbusNode nodeOfInterest = node; 052 nodeNVModel.setNode( nodeOfInterest ); 053 pane1.setVisible(!(node == null)); 054 } 055 056 private void initTable(){ 057 058 pane1 = new JPanel(); 059 060 TableColumnModel tableModel = nodeNvTable.getColumnModel(); 061 062 nodeNvTable.createDefaultColumnsFromModel(); 063 064 nodeNvTable.setRowSelectionAllowed(true); 065 nodeNvTable.setColumnSelectionAllowed(false); 066 nodeNvTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); 067 nodeNvTable.getTableHeader().setReorderingAllowed(true); 068 nodeNvTable.setRowHeight(27); 069 070 tableModel.getColumn(CbusNodeNVTableDataModel.NV_NUMBER_COLUMN).setCellRenderer(getRenderer()); 071 tableModel.getColumn(CbusNodeNVTableDataModel.NV_CURRENT_VAL_COLUMN).setCellRenderer( getRenderer() ); 072 tableModel.getColumn(CbusNodeNVTableDataModel.NV_CURRENT_HEX_COLUMN).setCellRenderer(getRenderer()); 073 tableModel.getColumn(CbusNodeNVTableDataModel.NV_CURRENT_BIT_COLUMN).setCellRenderer( getRenderer() ); 074 075 log.debug("_editable : {} , tot column {}",_editable, nodeNVModel.getColumnCount()); 076 077 if (_editable) { 078 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_COLUMN).setCellRenderer( new SpinnerRenderer() ); 079 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_COLUMN).setCellEditor( new NvSpinnerEditor() ); 080 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_HEX_COLUMN).setCellRenderer(getRenderer()); 081 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_BIT_COLUMN).setCellRenderer( getRenderer() ); 082 } 083 else { 084 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_COLUMN).setMinWidth(0); 085 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_COLUMN).setMaxWidth(0); 086 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_COLUMN).setWidth(0); 087 088 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_HEX_COLUMN).setMinWidth(0); 089 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_HEX_COLUMN).setMaxWidth(0); 090 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_HEX_COLUMN).setWidth(0); 091 092 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_BIT_COLUMN).setMinWidth(0); 093 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_BIT_COLUMN).setMaxWidth(0); 094 tableModel.getColumn(CbusNodeNVTableDataModel.NV_SELECT_BIT_COLUMN).setWidth(0); 095 } 096 097 largerFont = new JTextField().getFont().getSize()+2; 098 099 setLayout(new BorderLayout() ); 100 101 pane1.setLayout(new BorderLayout()); 102 103 // scroller for main table 104 eventVarScroll = new JScrollPane(nodeNvTable); 105 106 pane1.add(eventVarScroll); 107 108 add(pane1); 109 pane1.setVisible(true); 110 111 nodeNvTable.setAutoCreateColumnsFromModel( false ); 112 113 add(eventVarScroll); 114 115 } 116 117 private boolean _editable = true; 118 119 protected void setNonEditable() { 120 _editable = false; 121 } 122 123 public static final Color WHITE_GREEN = new Color(0xf5,0xf5,0xf5); 124 125 /** 126 * Cell Renderer for string table columns, highlights any text in filter input 127 */ 128 private TableCellRenderer getRenderer() { 129 return new TableCellRenderer() { 130 131 JTextField f = new JTextField(); 132 133 @Override 134 public Component getTableCellRendererComponent( 135 JTable table, Object arg1, boolean isSelected, boolean hasFocus, int row, int col) { 136 137 f.setHorizontalAlignment(JTextField.CENTER); 138 f.setBorder( table.getBorder() ); 139 140 int tablecol = nodeNvTable.convertColumnIndexToModel(col); 141 142 if ( tablecol == CbusNodeNVTableDataModel.NV_NUMBER_COLUMN ){ 143 f.setFont(f.getFont().deriveFont(Font.BOLD, largerFont )); 144 } 145 146 int oldval = (int) nodeNVModel.getValueAt(row, CbusNodeNVTableDataModel.NV_CURRENT_VAL_COLUMN); 147 int newval = (int) nodeNVModel.getValueAt(row, CbusNodeNVTableDataModel.NV_SELECT_COLUMN); 148 149 String string; 150 if(arg1 != null){ 151 string = arg1.toString(); 152 try { 153 if (Integer.parseInt(string)<0){ 154 string=""; 155 } 156 } catch (NumberFormatException ex) { 157 } 158 159 f.setText(string.toUpperCase()); 160 } else { 161 f.setText(""); 162 } 163 164 if (( tablecol == CbusNodeNVTableDataModel.NV_SELECT_HEX_COLUMN 165 || tablecol == CbusNodeNVTableDataModel.NV_SELECT_BIT_COLUMN) 166 && ( oldval == newval ) ){ 167 f.setText(""); 168 } 169 170 171 if (isSelected) { 172 if ( oldval != newval ) { 173 f.setBackground( Color.orange ); 174 } 175 else { 176 f.setBackground( table.getSelectionBackground() ); 177 } 178 } else { 179 if ( oldval != newval ) { 180 f.setBackground( Color.yellow ); 181 } 182 else { 183 if ( row % 2 == 0 ) { 184 f.setBackground( table.getBackground() ); 185 } 186 else { 187 f.setBackground( WHITE_GREEN ); 188 } 189 } 190 } 191 return f; 192 } 193 }; 194 } 195 196 protected static class NvSpinnerEditor extends AbstractCellEditor implements ChangeListener, TableCellEditor { 197 198 final JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 255, 1)); 199 200 public NvSpinnerEditor() { 201 init(); 202 } 203 204 final void init() { 205 spinner.addChangeListener(this); 206 } 207 208 @Override 209 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, 210 int row, int column) { 211 spinner.setValue( value); 212 spinner.setBorder(null); 213 214 return spinner; 215 } 216 217 @Override 218 public boolean isCellEditable(EventObject evt) { 219 if (evt instanceof MouseEvent) { 220 return ((MouseEvent) evt).getClickCount() >= 1; 221 } 222 return true; 223 } 224 225 @Override 226 public Object getCellEditorValue() { 227 return spinner.getValue(); 228 } 229 230 @Override 231 public void stateChanged(ChangeEvent eve) { 232 stopCellEditing(); 233 } 234 } 235 236 protected static class SpinnerRenderer extends JSpinner implements TableCellRenderer { 237 238 public SpinnerRenderer() { 239 } 240 241 @Override 242 public Component getTableCellRendererComponent(JTable table, Object value, 243 boolean isSelected, boolean hasFocus, int row, int column) { 244 setModel(new SpinnerNumberModel( (int) value, -1, 255, 1)); 245 setEnabled((int)value >-1); 246 this.setOpaque(true); 247 this.setBorder(null); 248 return this; 249 } 250 } 251 252 private final static Logger log = LoggerFactory.getLogger(CbusNodeNVEditTablePane.class); 253 254}