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 ("".equals(value)) {
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,
124                            Bundle.getMessage("WarningTitle"), JmriJOptionPane.ERROR_MESSAGE);
125                        return;
126                    }
127                }
128                Route nBean = getBySystemName(sysNameList.get(row));
129                nBean.setUserName((String) value);
130                fireTableRowsUpdated(row, row);
131                break;
132            case SETCOL:
133                SwingUtilities.invokeLater(() -> {
134                    JmriJFrame editFrame = new RouteEditFrame(((Route) getValueAt(row, SYSNAMECOL)).getSystemName());
135                    editFrame.setVisible(true);
136                });
137                break;
138            case ENABLECOL: {
139                // alternate
140                Route r = (Route) getValueAt(row, SYSNAMECOL);
141                r.setEnabled(!r.getEnabled());
142                break;
143            }
144            case LOCKCOL: {
145                // alternate
146                Route r = (Route) getValueAt(row, SYSNAMECOL);
147                r.setLocked(!r.getLocked());
148                break;
149            }
150            default:
151                super.setValueAt(value, row, col);
152                break;
153        }
154    }
155
156    @Override
157    public void configureTable(JTable table) {
158        table.setDefaultRenderer(Boolean.class, new EnablingCheckboxRenderer());
159        table.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer());
160        table.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor());
161        super.configureTable(table);
162    }
163
164    /**
165     * Delete the bean after all the checking has been done.
166     * <p>
167     * Deactivate the Route, then use the superclass to delete it.
168     */
169    @Override
170    protected void doDelete(Route bean) {
171        bean.deActivateRoute();
172        super.doDelete(bean);
173    }
174
175    // want to update when enabled parameter changes
176    @Override
177    protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) {
178        switch (e.getPropertyName()) {
179            case Route.PROPERTY_ENABLED:
180            case Route.PROPERTY_ROUTE_LOCKED:
181                return true;
182            default:
183                return super.matchPropertyName(e);
184        }
185    }
186
187    @Override
188    public RouteManager getManager() {
189        return InstanceManager.getDefault(RouteManager.class);
190    }
191
192    @Override
193    public Route getBySystemName(@Nonnull String name) {
194        return InstanceManager.getDefault(RouteManager.class).getBySystemName(name);
195    }
196
197    @Override
198    public Route getByUserName(@Nonnull String name) {
199        return InstanceManager.getDefault(RouteManager.class).getByUserName(name);
200    }
201
202    @Override
203    protected String getMasterClassName() {
204        // Use the RouteTabelAction class to combine messages in Preferences -> Messages
205        return RouteTableAction.class.getName();
206    }
207
208    @Override
209    public void clickOn(Route t) {
210        t.setRoute();
211    }
212
213    @Override
214    public String getValue(String s) {
215        return Bundle.getMessage("Set");
216        //Title of Set button in Route table
217    }
218
219    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteTableDataModel.class);
220
221}