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