001package jmri.jmrit.beantable;
002
003import java.beans.PropertyChangeEvent;
004import java.util.Date;
005import jmri.*;
006import jmri.implementation.DefaultIdTag;
007
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011import javax.annotation.Nonnull;
012import javax.swing.*;
013
014/**
015 * TableDataModel for an IdTag Table.
016 *
017 * Split from {@link IdTagTableAction}
018 *
019 * @author  Bob Jacobsen Copyright (C) 2003
020 * @author  Matthew Harris Copyright (C) 2011
021 * @author Steve Young Copyright (C) 2021
022 */
023public class IdTagTableDataModel extends BeanTableDataModel<IdTag> {
024
025    /**
026     * Create a new IdTag Table Data Model.
027     * @param mgr IdTag manager to use in the model, default IdTag Manager always used.
028     */
029    public IdTagTableDataModel(Manager<IdTag> mgr){
030        super();
031        setManager(mgr);
032    }
033    
034    @Override
035    protected final void setManager(Manager<IdTag> mgr){
036        if ( mgr instanceof IdTagManager ){
037            tagManager = (IdTagManager)mgr;
038        }
039    }
040    
041    private IdTagManager tagManager;
042    
043    public static final int WHERECOL = NUMCOLUMN;
044    public static final int WHENCOL = WHERECOL + 1;
045    public static final int CLEARCOL = WHENCOL + 1;
046
047    @Override
048    public String getValue(String name) {
049        IdTag tag = getManager().getBySystemName(name);
050        if (tag == null) {
051            return "?";
052        }
053        return tag.getTagID();
054    }
055
056    @Override
057    public Manager<IdTag> getManager() {
058        return ( tagManager != null ? tagManager : InstanceManager.getDefault(IdTagManager.class));
059    }
060
061    @Override
062    public IdTag getBySystemName(@Nonnull String name) {
063        return getManager().getBySystemName(name);
064    }
065
066    @Override
067    public IdTag getByUserName(@Nonnull String name) {
068        return getManager().getByUserName(name);
069    }
070
071    @Override
072    public void clickOn(IdTag t) {
073        // don't do anything on click; not used in this class, because
074        // we override setValueAt
075    }
076
077    @Override
078    public void setValueAt(Object value, int row, int col) {
079        if (col == CLEARCOL) {
080            IdTag t = getBySystemName(sysNameList.get(row));
081            log.debug("Clear where & when last seen for {}", t.getSystemName());
082            t.setWhereLastSeen(null);
083            fireTableRowsUpdated(row, row);
084        } else {
085            super.setValueAt(value, row, col);
086        }
087    }
088
089    @Override
090    public int getColumnCount() {
091        return CLEARCOL + 1;
092    }
093
094    @Override
095    public String getColumnName(int col) {
096        switch (col) {
097            case VALUECOL:
098                return Bundle.getMessage("ColumnIdTagID");
099            case WHERECOL:
100                return Bundle.getMessage("ColumnIdWhere");
101            case WHENCOL:
102                return Bundle.getMessage("ColumnIdWhen");
103            case CLEARCOL:
104                return "";
105            default:
106                return super.getColumnName(col);
107        }
108    }
109
110    @Override
111    public Class<?> getColumnClass(int col) {
112        switch (col) {
113            case VALUECOL:
114            case WHERECOL:
115                return String.class;
116            case CLEARCOL:
117                return JButton.class;
118            case WHENCOL:
119                return Date.class;
120            default:
121                return super.getColumnClass(col);
122        }
123    }
124
125    @Override
126    public boolean isCellEditable(int row, int col) {
127        switch (col) {
128            case VALUECOL:
129            case WHERECOL:
130            case WHENCOL:
131                return false;
132            case CLEARCOL:
133                return true;
134            default:
135                return super.isCellEditable(row, col);
136        }
137    }
138
139    @Override
140    public Object getValueAt(int row, int col) {
141        IdTag t;
142        switch (col) {
143            case WHERECOL:
144                Reporter r;
145                t = getBySystemName(sysNameList.get(row));
146                if ( t !=null ){
147                    r = t.getWhereLastSeen();
148                    if (r!=null){
149                        return r.getDisplayName();                            
150                    }
151                }
152                return null;
153            case WHENCOL:
154                t = getBySystemName(sysNameList.get(row));
155                return (t != null ?  t.getWhenLastSeen() : null);
156            case CLEARCOL:
157                return Bundle.getMessage("ButtonClear");
158            default:
159                return super.getValueAt(row, col);
160        }
161    }
162
163    @Override
164    public int getPreferredWidth(int col) {
165        switch (col) {
166            case SYSNAMECOL:
167            case WHERECOL:
168            case WHENCOL:
169                return new JTextField(12).getPreferredSize().width;
170            case VALUECOL:
171                return new JTextField(10).getPreferredSize().width;
172            case CLEARCOL:
173                return new JButton(Bundle.getMessage("ButtonClear")).getPreferredSize().width + 4;
174            default:
175                return super.getPreferredWidth(col);
176        }
177    }
178
179    @Override
180    public void configValueColumn(JTable table) {
181        // value column isn't button, so config is null
182    }
183
184    @Override
185    public void propertyChange(PropertyChangeEvent e) {
186        if (!(((IdTagManager)getManager()).isInitialised())) {
187            return;
188        }
189        switch (e.getPropertyName()) {
190            case DefaultIdTag.PROPERTY_WHEN_LAST_SEEN: // fire whole table update to ensure sorted view is updated
191                fireTableDataChanged();
192                break;
193            case jmri.managers.DefaultIdTagManager.PROPERTY_INITIALISED: // fire whole table update
194                updateNameList();
195                fireTableDataChanged();
196                break;
197            default:
198                super.propertyChange(e);
199                break;
200        }
201    }
202
203    /**
204     * {@inheritDoc}
205     * Do not update row on whereLastSeen as these are always followed
206     * by a whenLastSeen where we'll do a full data changed.
207     */
208    @Override
209    protected boolean matchPropertyName(java.beans.PropertyChangeEvent e) {
210        // log.debug("IdTag / Mgr matchPropertyName {} {}", e.getPropertyName(), e.getNewValue());
211        switch (e.getPropertyName()) {
212            case DefaultIdTag.PROPERTY_WHERE_LAST_SEEN:
213            case "beans":
214                return false;
215            default:
216                return true;
217        }
218    }
219
220    @Override
221    public JButton configureButton() {
222        log.error("configureButton should not have been called");
223        return null;
224    }
225
226    @Override
227    protected String getMasterClassName() {
228        return IdTagTableAction.class.getName();
229    }
230
231    // TODO - further investigate why the TableRowSorter does not update on this
232    // @Override
233    // public void configureTable(JTable table) {
234       // super.configureTable(table);
235       // ((javax.swing.table.TableRowSorter)table.getRowSorter()).setSortsOnUpdates(true);
236    // }
237
238    private static final Logger log = LoggerFactory.getLogger(IdTagTableDataModel.class);
239
240}