001package jmri.jmrit.display.layoutEditor.blockRoutingTable; 002 003import java.beans.PropertyChangeListener; 004import jmri.jmrit.display.layoutEditor.LayoutBlock; 005import jmri.jmrit.display.layoutEditor.LayoutBlockManager; 006 007/** 008 * Table data model for display of Roster variable values. 009 * <p> 010 * Any desired ordering, etc, is handled outside this class. 011 * <p> 012 * The initial implementation doesn't automatically update when roster entries 013 * change, doesn't allow updating of the entries, and only shows some of the 014 * fields. But it's a start.... 015 * 016 * @author Bob Jacobsen Copyright (C) 2009, 2010 017 * @since 2.7.5 018 */ 019public class LayoutBlockRouteTableModel extends javax.swing.table.AbstractTableModel implements PropertyChangeListener { 020 021 public static final int DESTCOL = 0; 022 static final int NEXTHOPCOL = 1; 023 static final int HOPCOUNTCOL = 2; 024 static final int DIRECTIONCOL = 3; 025 static final int METRICCOL = 4; 026 static final int LENGTHCOL = 5; 027 static final int STATECOL = 6; 028 static final int VALIDCOL = 7; 029 030 static final int NUMCOL = 7 + 1; 031 032 boolean editable = false; 033 034 public LayoutBlockRouteTableModel(boolean editable, LayoutBlock lBlock) { 035 this.editable = editable; 036 this.lBlock = lBlock; 037 lBlock.addPropertyChangeListener(this); 038 } 039 040 @Override 041 public int getRowCount() { 042 return lBlock.getNumberOfRoutes(); 043 } 044 045 @Override 046 public int getColumnCount() { 047 return NUMCOL; 048 } 049 050 @Override 051 public String getColumnName(int col) { 052 switch (col) { 053 case DESTCOL: 054 return Bundle.getMessage("Destination"); 055 case NEXTHOPCOL: 056 return Bundle.getMessage("NextHop"); 057 case HOPCOUNTCOL: 058 return Bundle.getMessage("HopCount"); 059 case DIRECTIONCOL: 060 return Bundle.getMessage("Direction"); 061 case METRICCOL: 062 return Bundle.getMessage("Metric"); 063 case LENGTHCOL: 064 return Bundle.getMessage("Length"); 065 case STATECOL: 066 return Bundle.getMessage("State"); 067 case VALIDCOL: 068 return Bundle.getMessage("Valid"); 069 070 default: 071 return "<UNKNOWN>"; 072 } 073 } 074 075 @Override 076 public Class<?> getColumnClass(int col) { 077 if (col == HOPCOUNTCOL) { 078 return Integer.class; 079 } else if (col == METRICCOL) { 080 return Integer.class; 081 } else if (col == LENGTHCOL) { 082 return Float.class; 083 } else { 084 return String.class; 085 } 086 } 087 088 /** 089 * Editable state must be set in ctor. 090 */ 091 @Override 092 public boolean isCellEditable(int row, int col) { 093 return false; 094 } 095 096 @Override 097 public void propertyChange(java.beans.PropertyChangeEvent e) { 098 if (e.getPropertyName().equals("length")) { 099 fireTableDataChanged(); 100 } else if (e.getPropertyName().equals("routing")) { 101 fireTableDataChanged(); 102 } else if (matchPropertyName(e)) { 103 // a value changed. Find it, to avoid complete redraw 104 int row = (Integer) e.getNewValue(); 105 // since we can add columns, the entire row is marked as updated 106 fireTableRowsUpdated(row, row); 107 } 108 } 109 110 protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) { 111 return (e.getPropertyName().contains("state") || e.getPropertyName().contains("hop") 112 || e.getPropertyName().contains("metric") || e.getPropertyName().contains("valid") 113 || e.getPropertyName().contains("neighbourmetric")); 114 } 115 116 /** 117 * Provides the empty String if attribute doesn't exist. 118 */ 119 @Override 120 public Object getValueAt(int row, int col) { 121 // get roster entry for row 122 if (lBlock == null) { 123 log.debug("layout Block is null!"); 124 return "Error"; 125 } 126 switch (col) { 127 case DESTCOL: 128 return lBlock.getRouteDestBlockAtIndex(row).getDisplayName(); 129 case NEXTHOPCOL: 130 String nextBlock = lBlock.getRouteNextBlockAtIndex(row).getDisplayName(); 131 if (nextBlock.equals(lBlock.getDisplayName())) { 132 nextBlock = Bundle.getMessage("DirectConnect"); 133 } 134 return nextBlock; 135 case HOPCOUNTCOL: 136 return lBlock.getRouteHopCountAtIndex(row); 137 case DIRECTIONCOL: 138 return jmri.Path.decodeDirection(lBlock.getRouteDirectionAtIndex(row)); 139 case METRICCOL: 140 return lBlock.getRouteMetric(row); 141 case LENGTHCOL: 142 return lBlock.getRouteLengthAtIndex(row); 143 case STATECOL: 144 return lBlock.getRouteStateAsString(row); 145 case VALIDCOL: 146 String value = ""; 147 if (lBlock.getRouteValid(row)) { 148 value = "*"; 149 } 150 return value; 151 default: 152 return "<UNKNOWN>"; 153 } 154 } 155 156 @Override 157 public void setValueAt(Object value, int row, int col) { 158 } 159 160 public int getPreferredWidth(int column) { 161 int retval = 20; // always take some width 162 retval = Math.max(retval, new javax.swing.JLabel(getColumnName(column)).getPreferredSize().width + 15); // leave room for sorter arrow 163 for (int row = 0; row < getRowCount(); row++) { 164 if (getColumnClass(column).equals(String.class)) { 165 retval = Math.max(retval, new javax.swing.JLabel(getValueAt(row, column).toString()).getPreferredSize().width); 166 } else if (getColumnClass(column).equals(Integer.class)) { 167 retval = Math.max(retval, new javax.swing.JLabel(getValueAt(row, column).toString()).getPreferredSize().width); 168 } 169 } 170 return retval + 5; 171 } 172 173 // drop listeners 174 public void dispose() { 175 } 176 177 public jmri.Manager<LayoutBlock> getManager() { 178 return jmri.InstanceManager.getDefault(LayoutBlockManager.class); 179 } 180 181 private LayoutBlock lBlock = null; 182 183 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutBlockRouteTableModel.class); 184}