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}