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