001package jmri.jmrix.can.cbus.eventtable;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005
006import javax.annotation.Nonnull;
007
008import jmri.Disposable;
009import jmri.InstanceManager;
010import jmri.ShutDownManager;
011import jmri.jmrix.can.CanListener;
012import jmri.jmrix.can.CanMessage;
013import jmri.jmrix.can.CanReply;
014import jmri.jmrix.can.CanSystemConnectionMemo;
015import jmri.jmrix.can.cbus.CbusPreferences;
016import jmri.ShutDownTask;
017import jmri.util.ThreadingUtil;
018
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022/**
023 * Table data model for display of CBUS events
024 *
025 * @author Andrew Crosland (C) 2009
026 * @author Steve Young (c) 2018 2019
027 * 
028 */
029public class CbusEventTableDataModel extends CbusBasicEventTableModel implements CanListener, Disposable {
030
031    
032    private CbusPreferences preferences;
033    private ShutDownTask shutDownTask;
034    
035    public CbusEventTableDataModel(CanSystemConnectionMemo memo, int row, int column) {
036        this(memo, row);
037    }
038
039    /**
040     * Create a new CbusEventTableDataModel.
041     * @param memo System Connection.
042     * @param initialRowSize initial array size.
043     */
044    public CbusEventTableDataModel(@Nonnull CanSystemConnectionMemo memo, int initialRowSize) {
045        super(memo, initialRowSize);
046
047        log.info("Starting {} Event Table",memo.getProtocol());
048        preferences = memo.get(jmri.jmrix.can.cbus.CbusPreferences.class);
049        shutDownTask = new CbusEventTableShutdownTask("CbusEventTableShutdownTask "+memo.getSystemPrefix(),this);
050        InstanceManager.getDefault(ShutDownManager.class).register(shutDownTask);
051
052        addTc(_memo);
053        checkRestoreEvents();
054        ta.updatejmricols();
055    
056    }
057    
058    private void checkRestoreEvents(){
059        if ( preferences !=null && preferences.getSaveRestoreEventTable() ){
060                CbusEventTableXmlAction.restoreEventsFromXmlTablestart(this);
061        }
062    }
063
064    /**
065     * De-register the shut down task which saves table details.
066     */
067    public void skipSaveOnDispose(){
068        InstanceManager.getDefault(ShutDownManager.class).deregister(shutDownTask);
069    }
070    
071    /**
072     * Get the Column Tooltips.
073     *<p>
074     * Order needs to match column list
075     */
076    public static final String[] CBUS_EV_TABLE_COL_TOOLTIPS = {
077        Bundle.getMessage("NodeColTip"),  // NOI18N
078        Bundle.getMessage("EventColTip"),  // NOI18N
079        Bundle.getMessage("NameColTip"),  // NOI18N
080        Bundle.getMessage("CbusNodeNameTip"),  // NOI18N
081        Bundle.getMessage("CommentColTip"),  // NOI18N
082        Bundle.getMessage("TypeColTip"), // NOI18N
083        Bundle.getMessage("SendToggleTip"), // NOI18N
084        Bundle.getMessage("SendOntip"), // NOI18N
085        Bundle.getMessage("SendOfftip"), // NOI18N
086        Bundle.getMessage("IDColTip"), // NOI18N
087        Bundle.getMessage("ColumnLastHeard"), // NOI18N
088        Bundle.getMessage("ColumnRequestStatusTip"), // NOI18N
089        Bundle.getMessage("ColumnTotalSession"), // NOI18N
090        Bundle.getMessage("ColumnOnSession"), // NOI18N
091        Bundle.getMessage("ColumnOffSession"), // NOI18N
092        Bundle.getMessage("ColumnInSessionTip"), // NOI18N
093        Bundle.getMessage("ColumnOutSessionTip"), // NOI18N
094        null,
095        null,
096        null,
097        null,
098        null,
099        Bundle.getMessage("ColumnEventDeleteTip"), // NOI18N
100        Bundle.getMessage("StlrOnTip"), // NOI18N
101        Bundle.getMessage("StlrOffTip"), // NOI18N
102        null,
103        null,
104        null
105
106    }; // Length = number of items in array should (at least) match number of columns
107    
108    private final static String[] COLUMN_NAMES = new String[] {
109        "CbusNode","CbusEvent","ColumnName","CbusNodeName","ColumnComment","CbusEventOnOrOff", //0-5
110        "ColumnToggle", "CbusSendOnHeader", "CbusSendOffHeader","CanID","ColumnLastHeard","ColumnStatusRequest", // 6-11
111        "ColumnTotalSession","ColumnOnSession","ColumnOffSession","ColumnInSession","ColumnOutSession", // 12-16
112        "ColumnTotalAll", "ColumnTotalOn", "ColumnTotalOff", "ColumnTotalIn", "ColumnTotalOut", // 17-21
113        "ColumnEventDelete","JmriOnEv","JmriOffEv","Dat1","Dat2","Dat3" }; // NOI18N
114    
115    /**
116     * {@inheritDoc}
117     */
118    @Override
119    public String getColumnName(int col) {
120        return Bundle.getMessage(COLUMN_NAMES[col]);
121    }
122    
123    public final static int[]BUTTON_COLUMNS = new int[]{TOGGLE_BUTTON_COLUMN, ON_BUTTON_COLUMN,
124        OFF_BUTTON_COLUMN, STATUS_REQUEST_BUTTON_COLUMN, DELETE_BUTTON_COLUMN};
125    
126    /**
127     * {@inheritDoc}
128     */
129    @Override
130    public Class<?> getColumnClass(int col) {
131        if (_mainArray.isEmpty() || null == getValueAt(0, col)) {
132            return Object.class;
133        }
134        return getValueAt(0, col).getClass();
135    }
136    
137    private final static int[] EDITABLE_COLS =new int[]{ 
138        NAME_COLUMN, COMMENT_COLUMN, TOGGLE_BUTTON_COLUMN, ON_BUTTON_COLUMN, 
139        OFF_BUTTON_COLUMN, STATUS_REQUEST_BUTTON_COLUMN, DELETE_BUTTON_COLUMN }; 
140    
141    /**
142     * {@inheritDoc}
143     */
144    @Override
145    public boolean isCellEditable(int row, int col) {
146        return Arrays.stream(EDITABLE_COLS).anyMatch(i -> i == col);
147    }
148
149    /**
150     * {@inheritDoc}
151     */
152    @Override
153    public void setValueAt(Object value, int row, int col) {
154        if (col==DELETE_BUTTON_COLUMN) {
155            ThreadingUtil.runOnGUIEventually(() -> ta.buttonDeleteClicked(row));
156        } else {                
157            super.setValueAt(value, row, col);
158        }
159    }
160
161    /**
162     * {@inheritDoc}
163     */
164    @Override
165    public void message(CanMessage m) { // outgoing cbus message
166        ta.parseMessage( m);
167    }
168    
169    /**
170     * {@inheritDoc}
171     */
172    @Override
173    public void reply(CanReply m) { // incoming cbus message
174        ta.parseMessage( m);
175    }
176    
177    /**
178     * Remove all events from table.
179     */
180    protected void clearAllEvents() {
181        _mainArray = new ArrayList<>();
182    }
183    
184    public CbusEventBeanData getEventBeans(int nn, int en, CbusTableEvent.EvState state) {
185        return provideEvent(nn, en).getBeans(state);
186    }
187    
188    /**
189     * Disconnect from the CBUS.
190     * Check and trigger if need to save table to xml.
191     */
192    @Override
193    public void dispose() {
194        ta.dispose();
195        
196        if ( preferences !=null && preferences.getSaveRestoreEventTable() ){
197            CbusEventTableXmlAction.storeEventsToXml(this);
198        }
199        removeTc(_memo);
200    }
201
202    private final static Logger log = LoggerFactory.getLogger(CbusEventTableDataModel.class);
203}