001package jmri.jmrit.beantable.block; 002 003import java.awt.Component; 004import java.text.DecimalFormat; 005import java.util.HashMap; 006 007import javax.swing.JLabel; 008import javax.swing.JTable; 009import javax.swing.table.TableCellEditor; 010import javax.swing.table.TableCellRenderer; 011 012import jmri.*; 013import jmri.util.table.NamedBeanBoxRenderer; 014import jmri.util.table.JComboBoxEditor; 015 016/** 017 * JTable for displaying Block BeanTable. 018 * @author Steve Young Copyright (C) 2024 019 */ 020public class BlockTableJTable extends jmri.jmrit.beantable.BeanTableJTable<Block> implements Disposable { 021 022 private final HashMap<Block, NamedBeanBoxRenderer<Sensor>> sensorComboMap = new HashMap<>(); 023 private final HashMap<Block, NamedBeanBoxRenderer<Reporter>> reporterComboMap = new HashMap<>(); 024 025 public BlockTableJTable( BlockTableDataModel blockTableDataModel) { 026 super(blockTableDataModel); 027 setDefaultRenderer(Float.class, new LengthRenderer()); 028 } 029 030 @Override 031 public TableCellRenderer getCellRenderer(int row, int column) { 032 // Convert the displayed index to the model index, rather than the displayed index 033 switch (convertColumnIndexToModel(column)) { 034 case BlockTableDataModel.SENSORCOL: 035 return getSensorRenderer(convertRowIndexToModel(row)); 036 case BlockTableDataModel.REPORTERCOL: 037 return getReporterRenderer(convertRowIndexToModel(row)); 038 default: 039 return super.getCellRenderer(row, column); 040 } 041 } 042 043 @Override 044 public TableCellEditor getCellEditor(int row, int column) { 045 //Convert the displayed index to the model index, rather than the displayed index 046 switch (convertColumnIndexToModel(column)) { 047 case BlockTableDataModel.SENSORCOL: 048 Block t = (Block) getModel().getValueAt(convertRowIndexToModel(row), BlockTableDataModel.SYSNAMECOL); 049 return new JComboBoxEditor(sensorComboMap.get(t),null ); 050 case BlockTableDataModel.REPORTERCOL: 051 Block tt = (Block) getModel().getValueAt(convertRowIndexToModel(row), BlockTableDataModel.SYSNAMECOL); 052 return new JComboBoxEditor(reporterComboMap.get(tt), null); 053 default: 054 return super.getCellEditor(row, column); 055 } 056 } 057 058 private TableCellRenderer getSensorRenderer(int modelRow) { 059 Block t = (Block) getModel().getValueAt(modelRow, BlockTableDataModel.SYSNAMECOL); 060 java.util.Objects.requireNonNull(t, "SYSNAMECOL column content must be nonnull"); 061 return sensorComboMap.computeIfAbsent(t, k -> 062 new NamedBeanBoxRenderer<Sensor>(InstanceManager.getDefault(SensorManager.class))); 063 } 064 065 private TableCellRenderer getReporterRenderer(int modelRow) { 066 Block t = (Block) getModel().getValueAt(modelRow, BlockTableDataModel.SYSNAMECOL); 067 java.util.Objects.requireNonNull(t, "SYSNAMECOL column content must be nonnull"); 068 return reporterComboMap.computeIfAbsent(t, k -> 069 new NamedBeanBoxRenderer<Reporter>(InstanceManager.getDefault(ReporterManager.class))); 070 } 071 072 private static class LengthRenderer extends javax.swing.table.DefaultTableCellRenderer{ 073 074 private static final DecimalFormat twoDigit = new DecimalFormat("0.00"); 075 076 @Override 077 public Component getTableCellRendererComponent(JTable table, Object value, 078 boolean isSelected, boolean hasFocus, int row, int column) { 079 080 Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 081 if ( value instanceof Float && comp instanceof JLabel ) { 082 ((JLabel)comp).setText(twoDigit.format(value)); 083 } 084 return comp; 085 } 086 087 } 088 089 @Override 090 public void dispose(){ 091 sensorComboMap.forEach( (b,s) -> s.dispose() ); 092 sensorComboMap.clear(); 093 reporterComboMap.forEach( (b,r) -> r.dispose() ); 094 reporterComboMap.clear(); 095 } 096 097}