001package jmri.jmrix.dcc4pc.swing.boardlists; 002 003import java.awt.BorderLayout; 004import java.beans.PropertyChangeListener; 005import java.util.List; 006import java.util.ResourceBundle; 007 008import javax.swing.BoxLayout; 009import javax.swing.JButton; 010import javax.swing.JPanel; 011import javax.swing.JScrollPane; 012import javax.swing.JTable; 013import javax.swing.JTextField; 014import javax.swing.SortOrder; 015import javax.swing.table.AbstractTableModel; 016import javax.swing.table.TableCellEditor; 017import javax.swing.table.TableRowSorter; 018 019import jmri.jmrix.dcc4pc.Dcc4PcSystemConnectionMemo; 020import jmri.jmrix.dcc4pc.swing.Dcc4PcPanelInterface; 021import jmri.swing.RowSorterUtil; 022import jmri.util.swing.JmriJOptionPane; 023import jmri.util.table.ButtonEditor; 024import jmri.util.table.ButtonRenderer; 025 026/** 027 * Frame for Signal Mast Add / Edit Panel 028 * 029 * @author Kevin Dickerson Copyright (C) 2011 030 * 031 */ 032public class BoardListPanel extends jmri.jmrix.dcc4pc.swing.Dcc4PcPanel implements Dcc4PcPanelInterface { 033 034 static final ResourceBundle rb = ResourceBundle.getBundle("jmri.jmrix.dcc4pc.swing.boardlists.BoardListBundle"); 035 036 jmri.jmrix.dcc4pc.Dcc4PcSensorManager senMan; 037 ReaderBoardModel _BoardModel; 038 039 JScrollPane _BoardScrollPane; 040 041 public BoardListPanel() { 042 super(); 043 } 044 045 /** 046 * {@inheritDoc} 047 */ 048 @Override 049 public void initComponents(Dcc4PcSystemConnectionMemo memo) { 050 super.initComponents(memo); 051 senMan = memo.getSensorManager(); 052 _boardListCount = senMan.getBoards(); 053 054 setLayout(new BorderLayout()); 055 056 JPanel header = new JPanel(); 057 header.setLayout(new BoxLayout(header, BoxLayout.Y_AXIS)); 058 059 JPanel sourcePanel = new JPanel(); 060 header.add(sourcePanel); 061 add(header, BorderLayout.NORTH); 062 063 _BoardModel = new ReaderBoardModel(); 064 JTable boardTable = new JTable(_BoardModel); 065 TableRowSorter<ReaderBoardModel> sorter = new TableRowSorter<>(_BoardModel); // leave default comparator for Integers 066 RowSorterUtil.setSortOrder(sorter, ReaderBoardModel.ADDRESS_COLUMN, SortOrder.ASCENDING); 067 068 boardTable.setRowSelectionAllowed(false); 069 boardTable.setPreferredScrollableViewportSize(new java.awt.Dimension(600, 120)); 070 _BoardModel.configureTable(boardTable); 071 _BoardScrollPane = new JScrollPane(boardTable); 072 _BoardModel.fireTableDataChanged(); 073 add(_BoardScrollPane, BorderLayout.CENTER); 074 075 JPanel footer = new JPanel(); 076 077 add(footer, BorderLayout.SOUTH); 078 } 079 080 private List<Integer> _boardListCount; 081 082 public class ReaderBoardModel extends AbstractTableModel implements PropertyChangeListener { 083 084 ReaderBoardModel() { 085 super(); 086 if (senMan != null) { 087 senMan.addPropertyChangeListener(ReaderBoardModel.this); 088 } 089 } 090 091 /*void updateSignalMastLogic(SignalMastLogic senManOld, SignalMastLogic senManNew){ 092 if(senManOld!=null) 093 senManOld.removePropertyChangeListener(this); 094 if(senManNew!=null) 095 senManNew.addPropertyChangeListener(this); 096 fireTableDataChanged(); 097 }*/ 098 @Override 099 public Class<?> getColumnClass(int c) { 100 if (c == EDIT_COLUMN) { 101 return JButton.class; 102 } 103 return String.class; 104 } 105 106 public void configureTable(JTable table) { 107 // allow reordering of the columns 108 table.getTableHeader().setReorderingAllowed(true); 109 110 // have to shut off autoResizeMode to get horizontal scroll to work (JavaSwing p 541) 111 table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 112 113 // resize columns as requested 114 for (int i = 0; i < table.getColumnCount(); i++) { 115 int width = getPreferredWidth(i); 116 table.getColumnModel().getColumn(i).setPreferredWidth(width); 117 } 118 table.sizeColumnsToFit(-1); 119 120 configEditColumn(table); 121 122 } 123 124 public int getPreferredWidth(int col) { 125 switch (col) { 126 case ADDRESS_COLUMN: 127 case VERSION_COLUMN: 128 case INPUTS_COLUMN: 129 return new JTextField(5).getPreferredSize().width; 130 case ENCODING_COLUMN: 131 case DESCRIPTION_COLUMN: // not actually used due to the configureTable, setColumnToHoldButton, configureButton 132 case EDIT_COLUMN: // not actually used due to the configureTable, setColumnToHoldButton, configureButton 133 return new JTextField(22).getPreferredSize().width; 134 default: 135 log.warn("Unexpected column in getPreferredWidth: {}", col); 136 return new JTextField(8).getPreferredSize().width; 137 } 138 } 139 140 @Override 141 public String getColumnName(int col) { 142 switch (col) { 143 case INPUTS_COLUMN: 144 return rb.getString("ColumnInput"); 145 case ADDRESS_COLUMN: 146 return rb.getString("ColumnAddress"); 147 case ENCODING_COLUMN: 148 return rb.getString("ColumnEncoding"); 149 case VERSION_COLUMN: 150 return rb.getString("ColumnVersion"); 151 case DESCRIPTION_COLUMN: 152 return rb.getString("ColumnDescription"); 153 case EDIT_COLUMN: // no title above Edit buttons 154 default: 155 return ""; 156 } 157 } 158 159 public void dispose() { 160 if (senMan != null) { 161 senMan.removePropertyChangeListener(this); 162 } 163 } 164 165 @Override 166 public void propertyChange(java.beans.PropertyChangeEvent e) { 167 if (e.getPropertyName().equals("length")) { 168 _boardListCount = senMan.getBoards(); 169 int length = (Integer) e.getNewValue(); 170 if (length == 0) { 171 senMan.removePropertyChangeListener(this); 172 senMan = null; 173 } 174 fireTableDataChanged(); 175 } /*else if (e.getPropertyName().equals("updatedDestination")) { 176 // a new NamedBean is available in the manager 177 _boardListCount = senMan.getBoards(); 178 fireTableDataChanged(); 179 } else if((e.getPropertyName().equals("state")) || (e.getPropertyName().equals("Enabled"))) { 180 fireTableDataChanged(); 181 fireTableRowsUpdated(0, _boardListCount.size()); 182 }*/ 183 184 } 185 186 protected void configEditColumn(JTable table) { 187 // have the delete column hold a button 188 /*AbstractTableAction.rb.getString("EditDelete")*/ 189 /*setColumnToHoldButton(table, DESCRIPTION_COLUMN, 190 new JButton(rb.getString("ButtonEdit")));*/ 191 setColumnToHoldButton(table, EDIT_COLUMN, 192 new JButton(rb.getString("ButtonEdit"))); 193 } 194 195 protected void setColumnToHoldButton(JTable table, int column, JButton sample) { 196 //TableColumnModel tcm = table.getColumnModel(); 197 // install a button renderer & editor 198 ButtonRenderer buttonRenderer = new ButtonRenderer(); 199 table.setDefaultRenderer(JButton.class, buttonRenderer); 200 TableCellEditor buttonEditor = new ButtonEditor(new JButton()); 201 table.setDefaultEditor(JButton.class, buttonEditor); 202 // ensure the table rows, columns have enough room for buttons 203 table.setRowHeight(sample.getPreferredSize().height); 204 table.getColumnModel().getColumn(column) 205 .setPreferredWidth((sample.getPreferredSize().width) + 4); 206 } 207 208 @Override 209 public int getColumnCount() { 210 return 6; 211 } 212 213 @Override 214 public boolean isCellEditable(int r, int c) { 215 return c == EDIT_COLUMN; 216 } 217 218 protected void editAddress(int r) { 219 int boardAddress = _boardListCount.get(r); 220 221 String retval = JmriJOptionPane.showInputDialog(_BoardScrollPane, rb.getString("ChangeAddress"), 222 rb.getString("ChangeAddressTitle"), JmriJOptionPane.INFORMATION_MESSAGE); 223 if ( retval == null ) { // Dialog closed 224 return; 225 } 226 //Need some validation! 227 senMan.changeBoardAddress(boardAddress, Integer.parseInt(retval)); 228 } 229 230 public static final int ADDRESS_COLUMN = 0; 231 public static final int INPUTS_COLUMN = 1; 232 public static final int ENCODING_COLUMN = 2; 233 public static final int VERSION_COLUMN = 3; 234 public static final int DESCRIPTION_COLUMN = 4; 235 public static final int EDIT_COLUMN = 5; 236 237 238 @Override 239 public int getRowCount() { 240 if (_boardListCount == null) { 241 return 0; 242 } 243 return _boardListCount.size(); 244 } 245 246 @Override 247 public Object getValueAt(int r, int c) { 248 if (senMan == null) { 249 return null; 250 } 251 // some error checking 252 if (r >= _boardListCount.size()) { 253 log.debug("row is greater than turnout list size"); 254 return null; 255 } 256 switch (c) { 257 case INPUTS_COLUMN: 258 return senMan.getBoardInputs(_boardListCount.get(r)) + 1; 259 case ADDRESS_COLUMN: // slot number 260 return _boardListCount.get(r); 261 case ENCODING_COLUMN: 262 return senMan.getBoardEncodingAsString(_boardListCount.get(r)); 263 case VERSION_COLUMN: 264 return senMan.getBoardVersion(_boardListCount.get(r)); 265 case DESCRIPTION_COLUMN: 266 return senMan.getBoardDescription(_boardListCount.get(r)); 267 case EDIT_COLUMN: 268 return rb.getString("ButtonEdit"); 269 default: 270 return null; 271 } 272 } 273 274 @Override 275 public void setValueAt(Object type, int r, int c) { 276 if (c == EDIT_COLUMN) { 277 editAddress(r); 278 } 279 /*else if (c==EDIT_COLUMN) 280 deletePair(r); 281 else if (c==VERSION_COLUMN){ 282 boolean b = ((Boolean)type).booleanValue(); 283 if(b) 284 senMan.setEnabled(_boardListCount.get(r)); 285 else 286 senMan.setDisabled(_boardListCount.get(r)); 287 288 }*/ 289 } 290 } 291 292 /** 293 * Nested class to create one of these using old-style defaults 294 */ 295 static public class Default extends jmri.jmrix.dcc4pc.swing.Dcc4PcNamedPaneAction { 296 297 public Default() { 298 super("Dcc4PC Command Monitor", 299 new jmri.util.swing.sdi.JmriJFrameInterface(), 300 BoardListPanel.class.getName(), 301 jmri.InstanceManager.getDefault(Dcc4PcSystemConnectionMemo.class)); 302 } 303 } 304 305 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BoardListPanel.class); 306 307}