001package jmri.jmrit.operations;
002
003import java.awt.*;
004import java.util.List;
005
006import javax.swing.*;
007import javax.swing.table.DefaultTableCellRenderer;
008
009import jmri.jmrit.operations.rollingstock.RollingStock;
010import jmri.jmrit.operations.trains.trainbuilder.TrainCommon;
011import jmri.util.swing.XTableColumnModel;
012
013/**
014 * Common table model methods for operations.
015 * 
016 * @author Daniel Boudreau Copyright (C) 2023, 2025, 2026
017 */
018public abstract class OperationsTableModel extends javax.swing.table.AbstractTableModel {
019    
020    protected JTable _table;
021    
022    public void initTable(JTable table) {
023        _table = table;
024        table.setDefaultRenderer(JComboBox.class, new jmri.jmrit.symbolicprog.ValueRenderer());
025        table.setDefaultEditor(JComboBox.class, new jmri.jmrit.symbolicprog.ValueEditor());
026        table.setDefaultRenderer(Object.class, new MyTableCellRenderer());
027        table.setDefaultRenderer(Integer.class, new MyTableCellRenderer());
028    }
029
030    protected Color getForegroundColor(int row) {
031        return _table.getForeground();
032    }
033    
034    protected Font getFont(int row) {
035        return _table.getFont();
036    }
037    
038    /**
039     * Search list for rolling stock by road number
040     * 
041     * @param roadNumber The string road number to search for.
042     * @param rsList     The list to search
043     * @return -1 if not found, table row number if found
044     */
045    public int findRollingStockByRoadNumber(String roadNumber, List<?> rsList) {
046        if (rsList != null) {
047            if (!roadNumber.equals(_roadNumber)) {
048                return getIndex(0, roadNumber, rsList);
049            }
050            int index = getIndex(_index, roadNumber, rsList);
051            if (index > 0) {
052                return index;
053            }
054            return getIndex(0, roadNumber, rsList);
055        }
056        return -1;
057    }
058
059    protected String _roadNumber = "";
060    protected int _index = 0;
061
062    protected int getIndex(int start, String roadNumber, List<?> rsList) {
063        for (int index = start; index < rsList.size(); index++) {
064            RollingStock rs = (RollingStock) rsList.get(index);
065            if (rs != null) {
066                _roadNumber = roadNumber;
067                _index = index + 1;
068                String[] number = rs.getNumber().split(TrainCommon.HYPHEN);
069                // check for wild card '*'
070                if (roadNumber.startsWith("*") && roadNumber.endsWith("*") && roadNumber.length() > 1) {
071                    String rN = roadNumber.substring(1, roadNumber.length() - 1);
072                    if (rs.getNumber().contains(rN)) {
073                        return index;
074                    }
075                } else if (roadNumber.startsWith("*")) {
076                    String rN = roadNumber.substring(1);
077                    if (rs.getNumber().endsWith(rN) || number[0].endsWith(rN)) {
078                        return index;
079                    }
080                } else if (roadNumber.endsWith("*")) {
081                    String rN = roadNumber.substring(0, roadNumber.length() - 1);
082                    if (rs.getNumber().startsWith(rN)) {
083                        return index;
084                    }
085                } else if (roadNumber.contains("*")) {
086                    String rn = roadNumber.replace("*", ":");
087                    String[] rN = rn.split(":");
088                    if (rs.getNumber().startsWith(rN[0]) && number[0].endsWith(rN[rN.length - 1])) {
089                        return index;
090                    }
091                } else if (rs.getNumber().equals(roadNumber) || number[0].equals(roadNumber)) {
092                    return index;
093                }
094            }
095        }
096        _roadNumber = "";
097        return -1;
098    }
099
100    public boolean showAll = true; // when true show all rolling stock
101    public String locationName = null; // only show rolling stock at this location
102    public String trackName = null; // only show rolling stock using this track
103
104    protected void filterList(List<?> list) {
105        if (showAll) {
106            return;
107        }
108        for (int i = 0; i < list.size(); i++) {
109            RollingStock rs = (RollingStock) list.get(i);
110            if (rs.getLocation() == null) {
111                list.remove(i--);
112                continue;
113            }
114            // filter out cars that don't have a location name that matches
115            if (locationName != null) {
116                if (!rs.getLocationName().equals(locationName)) {
117                    list.remove(i--);
118                    continue;
119                }
120                if (trackName != null) {
121                    if (!rs.getTrackName().equals(trackName)) {
122                        list.remove(i--);
123                    }
124                }
125            }
126        }
127    }
128
129    protected void setToolTip(String text, int col) {
130        XTableColumnModel tcm = (XTableColumnModel) _table.getColumnModel();
131        JComponent jC = (JComponent) tcm.getColumnByModelIndex(col).getCellRenderer();
132        if (jC != null) {
133            jC.setToolTipText(text);
134        }
135    }
136
137    public class MyTableCellRenderer extends DefaultTableCellRenderer {
138        @Override
139        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
140                int row, int column) {
141            Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
142            int modelRow = table.convertRowIndexToModel(row);
143            component.setFont(OperationsTableModel.this.getFont(modelRow));
144            if (!isSelected) {  
145                component.setForeground(getForegroundColor(modelRow));
146            }
147            return component;
148        }
149    }
150}