001package jmri.jmrit.beantable;
002
003import javax.annotation.Nonnull;
004import javax.swing.*;
005
006import jmri.*;
007import jmri.jmrit.beantable.routetable.RouteEditFrame;
008import jmri.util.JmriJFrame;
009import jmri.util.swing.JmriJOptionPane;
010
011/**
012 * TableDataModel for the Route Table.
013 *
014 * Split from {@link RouteTableAction}
015 *
016 * @author Dave Duchamp Copyright (C) 2004
017 * @author Bob Jacobsen Copyright (C) 2007
018 * @author Simon Reader Copyright (C) 2008
019 * @author Pete Cressman Copyright (C) 2009
020 * @author Egbert Broerse Copyright (C) 2016
021 * @author Paul Bender Colyright (C) 2020
022 */
023public class RouteTableDataModel extends BeanTableDataModel<Route> {
024
025    private static final int ENABLECOL = NUMCOLUMN;
026    private static final int LOCKCOL = ENABLECOL + 1;
027    private static final int SETCOL = ENABLECOL + 2;
028
029    @Override
030    public int getColumnCount() {
031        return NUMCOLUMN + 3;
032    }
033
034    @Override
035    public String getColumnName(int col) {
036        switch (col) {
037            case VALUECOL: // no heading on "Edit"
038            case SETCOL: // no heading on "Set"
039                return "";
040            case ENABLECOL:
041                return Bundle.getMessage("ColumnHeadEnabled");
042            case LOCKCOL:
043                return Bundle.getMessage("Locked");
044            default:
045                return super.getColumnName(col);
046        }
047    }
048
049    @Override
050    public Class<?> getColumnClass(int col) {
051        switch (col) {
052            case SETCOL:
053                return JButton.class;
054            case ENABLECOL:
055            case LOCKCOL:
056                return Boolean.class;
057            default:
058                return super.getColumnClass(col);
059        }
060    }
061
062    @Override
063    public int getPreferredWidth(int col) {
064        switch (col) {
065            case SETCOL:
066            case ENABLECOL:
067            case LOCKCOL:
068                return new JTextField(6).getPreferredSize().width;
069            default:
070                return super.getPreferredWidth(col);
071        }
072    }
073
074    @Override
075    public boolean isCellEditable(int row, int col) {
076        switch (col) {
077            case USERNAMECOL:
078            case SETCOL:
079            case ENABLECOL:
080                return true;
081            case LOCKCOL: // Route lock is available if turnouts are lockable
082                return ((Route) getValueAt(row, SYSNAMECOL)).canLock();
083            default:
084                return super.isCellEditable(row, col);
085        }
086    }
087
088    @Override
089    public Object getValueAt(int row, int col) {
090        switch (col) {
091            case SETCOL:
092                return Bundle.getMessage("ButtonEdit");
093            case ENABLECOL:
094                return ((Route) getValueAt(row, SYSNAMECOL)).getEnabled();
095            case LOCKCOL:
096                Route r = (Route) getValueAt(row, SYSNAMECOL);
097                if (r.canLock()) {
098                    return r.getLocked();
099                } else {
100                    // this covers the case when route was locked and lockable turnouts were removed from the route
101                    r.setLocked(false);
102                    return false;
103                }
104            default:
105                return super.getValueAt(row, col);
106        }
107    }
108
109    @Override
110    public void setValueAt(Object value, int row, int col) {
111        switch (col) {
112            case USERNAMECOL:
113                // Directly changing the username should only be possible if the username was previously null or ""
114                // check to see if user name already exists
115                if (value.equals("")) {
116                    value = null;
117                } else {
118                    Route nB = getByUserName((String) value);
119                    if (nB != null) {
120                        log.error("User Name is not unique {}", value);
121                        String msg;
122                        msg = Bundle.getMessage("WarningUserName", ("" + value));
123                        JmriJOptionPane.showMessageDialog(null, msg, Bundle.getMessage("WarningTitle"), JmriJOptionPane.ERROR_MESSAGE);
124                        return;
125                    }
126                }
127                Route nBean = getBySystemName(sysNameList.get(row));
128                nBean.setUserName((String) value);
129                fireTableRowsUpdated(row, row);
130                break;
131            case SETCOL:
132                SwingUtilities.invokeLater(() -> {
133                    JmriJFrame editFrame = new RouteEditFrame(((Route) getValueAt(row, SYSNAMECOL)).getSystemName());
134                    editFrame.setVisible(true);
135                });
136                break;
137            case ENABLECOL: {
138                // alternate
139                Route r = (Route) getValueAt(row, SYSNAMECOL);
140                r.setEnabled(!r.getEnabled());
141                break;
142            }
143            case LOCKCOL: {
144                // alternate
145                Route r = (Route) getValueAt(row, SYSNAMECOL);
146                r.setLocked(!r.getLocked());
147                break;
148            }
149            default:
150                super.setValueAt(value, row, col);
151                break;
152        }
153    }
154
155    @Override
156    public void configureTable(JTable table) {
157        table.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer());
158        table.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer());
159        table.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor());
160        super.configureTable(table);
161    }
162
163    /**
164     * Delete the bean after all the checking has been done.
165     * <p>
166     * Deactivate the Route, then use the superclass to delete it.
167     */
168    @Override
169    protected void doDelete(Route bean) {
170        bean.deActivateRoute();
171        super.doDelete(bean);
172    }
173
174    // want to update when enabled parameter changes
175    @Override
176    protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) {
177        switch (e.getPropertyName()) {
178            case "Enabled": // NOI18N
179            case "Locked": // NOI18N
180                return true;
181            default:
182                return super.matchPropertyName(e);
183        }
184    }
185
186    @Override
187    public RouteManager getManager() {
188        return InstanceManager.getDefault(RouteManager.class);
189    }
190
191    @Override
192    public Route getBySystemName(@Nonnull String name) {
193        return InstanceManager.getDefault(RouteManager.class).getBySystemName(name);
194    }
195
196    @Override
197    public Route getByUserName(@Nonnull String name) {
198        return InstanceManager.getDefault(RouteManager.class).getByUserName(name);
199    }
200
201    @Override
202    protected String getMasterClassName() {
203        // Use the RouteTabelAction class to combine messages in Preferences -> Messages
204        return RouteTableAction.class.getName();
205    }
206
207    @Override
208    public void clickOn(Route t) {
209        t.setRoute();
210    }
211
212    @Override
213    public String getValue(String s) {
214        return Bundle.getMessage("Set");
215        //Title of Set button in Route table
216    }
217
218    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteTableDataModel.class);
219
220}