001package jmri.jmrit.operations.routes;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.util.List;
006
007import javax.swing.*;
008import javax.swing.table.TableCellEditor;
009import javax.swing.table.TableColumnModel;
010
011import jmri.InstanceManager;
012import jmri.jmrit.operations.locations.LocationManager;
013import jmri.jmrit.operations.setup.Control;
014import jmri.jmrit.operations.setup.Setup;
015import jmri.jmrit.operations.trains.Train;
016import jmri.jmrit.operations.trains.TrainManager;
017import jmri.util.swing.JmriJOptionPane;
018import jmri.util.table.ButtonEditor;
019import jmri.util.table.ButtonRenderer;
020
021/**
022 * Table Model for edit of routes used by operations
023 *
024 * @author Daniel Boudreau Copyright (C) 2008, 2015
025 */
026public class RoutesTableModel extends javax.swing.table.AbstractTableModel implements PropertyChangeListener {
027
028    RouteManager routemanager; // There is only one manager
029
030    // Defines the columns
031    public static final int ID_COLUMN = 0;
032    public static final int NAME_COLUMN = ID_COLUMN + 1;
033    public static final int COMMENT_COLUMN = NAME_COLUMN + 1;
034    public static final int DEPARTS_COLUMN = COMMENT_COLUMN + 1;
035    public static final int MIN_LENGTH_COLUMN = DEPARTS_COLUMN + 1;
036    public static final int MAX_LENGTH_COLUMN = MIN_LENGTH_COLUMN + 1;
037    public static final int STATUS_COLUMN = MAX_LENGTH_COLUMN + 1;
038    public static final int EDIT_COLUMN = STATUS_COLUMN + 1;
039
040    private static final int HIGHESTCOLUMN = EDIT_COLUMN + 1;
041
042    public RoutesTableModel() {
043        super();
044        Setup.getDefault().addPropertyChangeListener(this);
045        routemanager = InstanceManager.getDefault(RouteManager.class);
046        routemanager.addPropertyChangeListener(this);
047        InstanceManager.getDefault(LocationManager.class).addPropertyChangeListener(this);
048        updateList();
049    }
050
051    public final int SORTBYNAME = 1;
052    public final int SORTBYID = 2;
053
054    private int _sort = SORTBYNAME;
055
056    public void setSort(int sort) {
057        _sort = sort;
058        updateList();
059        fireTableDataChanged();
060    }
061
062    private void updateList() {
063        // first, remove listeners from the individual objects
064        removePropertyChangeRoutes();
065
066        if (_sort == SORTBYID) {
067            sysList = routemanager.getRoutesByIdList();
068        } else {
069            sysList = routemanager.getRoutesByNameList();
070        }
071        // and add them back in
072        for (Route route : sysList) {
073            route.addPropertyChangeListener(this);
074        }
075    }
076
077    List<Route> sysList = null;
078
079    void initTable(RoutesTableFrame frame, JTable table) {
080        // Install the button handlers
081        TableColumnModel tcm = table.getColumnModel();
082        ButtonRenderer buttonRenderer = new ButtonRenderer();
083        TableCellEditor buttonEditor = new ButtonEditor(new javax.swing.JButton());
084        tcm.getColumn(EDIT_COLUMN).setCellRenderer(buttonRenderer);
085        tcm.getColumn(EDIT_COLUMN).setCellEditor(buttonEditor);
086
087        // set column preferred widths
088        table.getColumnModel().getColumn(ID_COLUMN).setPreferredWidth(30);
089        table.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(220);
090        table.getColumnModel().getColumn(COMMENT_COLUMN).setPreferredWidth(380);
091        table.getColumnModel().getColumn(STATUS_COLUMN).setPreferredWidth(70);
092        table.getColumnModel().getColumn(DEPARTS_COLUMN).setPreferredWidth(75);
093        table.getColumnModel().getColumn(MIN_LENGTH_COLUMN).setPreferredWidth(75);
094        table.getColumnModel().getColumn(MAX_LENGTH_COLUMN).setPreferredWidth(75);
095        table.getColumnModel().getColumn(EDIT_COLUMN).setPreferredWidth(80);
096
097        frame.loadTableDetails(table);
098    }
099
100    @Override
101    public int getRowCount() {
102        return sysList.size();
103    }
104
105    @Override
106    public int getColumnCount() {
107        return HIGHESTCOLUMN;
108    }
109
110    @Override
111    public String getColumnName(int col) {
112        switch (col) {
113            case ID_COLUMN:
114                return Bundle.getMessage("Id");
115            case NAME_COLUMN:
116                return Bundle.getMessage("Name");
117            case COMMENT_COLUMN:
118                return Bundle.getMessage("Comment");
119            case DEPARTS_COLUMN:
120                return Bundle.getMessage("DepartsDirection");
121            case MIN_LENGTH_COLUMN:
122                return Bundle.getMessage("MinLength");
123            case MAX_LENGTH_COLUMN:
124                return Bundle.getMessage("MaxLength");
125            case STATUS_COLUMN:
126                return Bundle.getMessage("Status");
127            case EDIT_COLUMN:
128                return Bundle.getMessage("ButtonEdit"); // titles above all columns
129            default:
130                return "unknown"; // NOI18N
131        }
132    }
133
134    @Override
135    public Class<?> getColumnClass(int col) {
136        switch (col) {
137            case NAME_COLUMN:
138            case COMMENT_COLUMN:
139            case DEPARTS_COLUMN:
140            case STATUS_COLUMN:
141                return String.class;
142            case ID_COLUMN:
143            case MIN_LENGTH_COLUMN:
144            case MAX_LENGTH_COLUMN:
145                return Integer.class;
146            case EDIT_COLUMN:
147                return JButton.class;
148            default:
149                return null;
150        }
151    }
152
153    @Override
154    public boolean isCellEditable(int row, int col) {
155        switch (col) {
156            case EDIT_COLUMN:
157                return true;
158            default:
159                return false;
160        }
161    }
162
163    @Override
164    public Object getValueAt(int row, int col) {
165        if (row >= getRowCount()) {
166            return "ERROR unknown " + row; // NOI18N
167        }
168        Route route = sysList.get(row);
169        if (route == null) {
170            return "ERROR route unknown " + row; // NOI18N
171        }
172        switch (col) {
173            case ID_COLUMN:
174                return Integer.parseInt(route.getId());
175            case NAME_COLUMN:
176                return route.getName();
177            case COMMENT_COLUMN:
178                return route.getComment();
179            case DEPARTS_COLUMN:
180                return route.getDepartureDirection();
181            case MIN_LENGTH_COLUMN:
182                return route.getRouteMinimumTrainLength();
183            case MAX_LENGTH_COLUMN:
184                return route.getRouteMaximumTrainLength();
185            case STATUS_COLUMN:
186                return route.getStatus();
187            case EDIT_COLUMN:
188                return Bundle.getMessage("ButtonEdit");
189            default:
190                return "unknown " + col; // NOI18N
191        }
192    }
193
194    @Override
195    public void setValueAt(Object value, int row, int col) {
196        switch (col) {
197            case EDIT_COLUMN:
198                editRoute(row);
199                break;
200            default:
201                break;
202        }
203    }
204
205    RouteEditFrame ref = null;
206    protected static final String NEW_LINE = "\n"; // NOI18N
207
208    private void editRoute(int row) {
209        log.debug("Edit route");
210        if (ref != null) {
211            ref.dispose();
212        }
213        Route route = sysList.get(row);
214        if (route != null && route.getStatus().equals(Route.TRAIN_BUILT)) {
215            // list the built trains for this route
216            StringBuffer buf = new StringBuffer(Bundle.getMessage("DoNotModifyRoute"));
217            for (Train train : InstanceManager.getDefault(TrainManager.class).getTrainsByIdList()) {
218                if (train.getRoute() == route && train.isBuilt()) {
219                    buf.append(NEW_LINE +
220                            Bundle.getMessage("TrainIsBuilt",
221                                    train.getName(), route.getName()));
222                }
223            }
224            JmriJOptionPane.showMessageDialog(null, buf.toString(), Bundle.getMessage("TrainBuilt"),
225                    JmriJOptionPane.WARNING_MESSAGE);
226        }
227        // use invokeLater so new window appears on top
228        SwingUtilities.invokeLater(() -> {
229                ref = new RouteEditFrame();
230                ref.initComponents(sysList.get(row));
231        });
232    }
233
234    @Override
235    public void propertyChange(PropertyChangeEvent e) {
236        if (Control.SHOW_PROPERTY) {
237            log.debug("Property change: ({}) old: ({}) new: ({})", e.getPropertyName(), e.getOldValue(), e
238                    .getNewValue());
239        }
240        if (e.getPropertyName().equals(LocationManager.LISTLENGTH_CHANGED_PROPERTY) ||
241                e.getPropertyName().equals(Setup.TRAIN_DIRECTION_PROPERTY_CHANGE)) {
242            fireTableDataChanged();
243        } else if (e.getPropertyName().equals(RouteManager.LISTLENGTH_CHANGED_PROPERTY)) {
244            updateList();
245            fireTableDataChanged();
246        } else if (e.getSource().getClass().equals(Route.class)) {
247            Route route = (Route) e.getSource();
248            int row = sysList.indexOf(route);
249            if (Control.SHOW_PROPERTY) {
250                log.debug("Update route table row: {} id: {}", row, route.getId());
251            }
252            if (row >= 0) {
253                fireTableRowsUpdated(row, row);
254            }
255        }
256    }
257
258    private void removePropertyChangeRoutes() {
259        if (sysList != null) {
260            for (Route route : sysList) {
261                route.removePropertyChangeListener(this);
262            }
263        }
264    }
265
266    public void dispose() {
267        if (ref != null) {
268            ref.dispose();
269        }
270        Setup.getDefault().removePropertyChangeListener(this);
271        routemanager.removePropertyChangeListener(this);
272        InstanceManager.getDefault(LocationManager.class).removePropertyChangeListener(this);
273        removePropertyChangeRoutes();
274    }
275
276    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RoutesTableModel.class);
277}