001package jmri.jmrix.can.cbus.eventtable; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005 006import javax.annotation.Nonnull; 007import javax.swing.JCheckBox; 008 009import jmri.NamedBean; 010import jmri.jmrix.AbstractMessage; 011import jmri.jmrix.can.CanMessage; 012import jmri.jmrix.can.CanReply; 013import jmri.jmrix.can.cbus.CbusConstants; 014import jmri.jmrix.can.cbus.CbusEvent; 015import jmri.jmrix.can.cbus.CbusEventInterface; 016import jmri.jmrix.can.cbus.CbusMessage; 017import jmri.util.ThreadingUtil; 018import jmri.util.swing.JmriJOptionPane; 019 020/** 021 * 022 * @author Steve Young (c) 2018, 2019 023 * 024 */ 025public class CbusEventTableAction implements PropertyChangeListener { 026 027 private final CbusBasicEventTableModel _model; 028 029 public CbusEventTableAction( @Nonnull CbusBasicEventTableModel model) { 030 _model = model; 031 addRemoveListenersToNbManagers(true); 032 } 033 034 protected boolean sessionConfirmDeleteRow=true; // display confirm popup 035 036 private void linkHwaddtoEvent(NamedBean bean, boolean beanState, CanMessage m){ 037 if (m==null){ 038 return; 039 } 040 int en = CbusMessage.getEvent(m); 041 int nn = CbusMessage.getNodeNumber(m); 042 CbusTableEvent event = _model.provideEvent(nn,en); 043 event.appendOnOffBean(bean, beanState, CbusEvent.getEvState(m)); 044 fireJmriCellsChanged(_model.getEventTableRow(nn, en)); 045 } 046 047 private void fireJmriCellsChanged(int row){ 048 ThreadingUtil.runOnGUIEventually( ()->{ 049 _model.fireTableCellUpdated(row, CbusEventTableDataModel.STLR_ON_COLUMN); 050 _model.fireTableCellUpdated(row, CbusEventTableDataModel.STLR_OFF_COLUMN); 051 }); 052 } 053 054 private void fireAllJmriCellsChanged(){ 055 for (int i=0; i < _model.getRowCount(); i++) { 056 fireJmriCellsChanged(i); 057 } 058 } 059 060 /** 061 * Update all columns for JMRI Sensor, Turnout and light details 062 */ 063 public void updatejmricols(){ 064 065 // reset all columns 066 _model._mainArray.forEach((n) -> n.resetBeans() ); 067 fireAllJmriCellsChanged(); 068 for (Class<?> classType : classTypes) { 069 jmri.Manager<?> sm = (jmri.Manager<?>) _model._memo.get(classType); 070 sm.getNamedBeanSet().forEach((nb) -> { 071 if (nb instanceof CbusEventInterface) { 072 linkHwaddtoEvent( nb, true, ((CbusEventInterface)nb).getBeanOnMessage()); 073 linkHwaddtoEvent( nb, false, ((CbusEventInterface)nb).getBeanOffMessage()); 074 } 075 }); 076 } 077 } 078 079 public void resetAllSessionTotals() { 080 _model.getEvents().forEach( ( ev) ->{ 081 ev.resetSessionTotals(); 082 updateStatColumnsinGui(_model.getEventTableRow(ev.getNn(), ev.getEn())); 083 }); 084 } 085 086 private final Class<?>[] classTypes = new Class<?>[]{ 087 jmri.TurnoutManager.class,jmri.SensorManager.class,jmri.LightManager.class}; 088 089 protected final void addRemoveListenersToNbManagers(boolean add){ 090 for (Class<?> classType : classTypes) { 091 if (add) { 092 ((jmri.Manager<?>) _model._memo.get(classType)).addPropertyChangeListener(this); 093 } else { 094 ((jmri.Manager<?>) _model._memo.get(classType)).removePropertyChangeListener(this); 095 } 096 } 097 } 098 099 /** {@inheritDoc} */ 100 @Override 101 public void propertyChange(PropertyChangeEvent ev){ 102 updatejmricols(); 103 } 104 105 /** 106 * Delete Button Clicked 107 * See whether to display confirm popup 108 * @param row int row number 109 */ 110 public void buttonDeleteClicked(int row) { 111 if (sessionConfirmDeleteRow) { 112 // confirm deletion with the user 113 ThreadingUtil.runOnGUI( ()-> { 114 JCheckBox checkbox = new JCheckBox(Bundle.getMessage("PopupSessionConfirmDel")); // NOI18N 115 String message = Bundle.getMessage("DelConfirmOne") + "\n" 116 + Bundle.getMessage("DelConfirmTwo"); // NOI18N 117 Object[] params = {message, checkbox}; 118 119 if (JmriJOptionPane.OK_OPTION == JmriJOptionPane.showConfirmDialog( 120 null, params, Bundle.getMessage("DelEvPopTitle"), // NOI18N 121 JmriJOptionPane.OK_CANCEL_OPTION, 122 JmriJOptionPane.WARNING_MESSAGE)) { 123 124 sessionConfirmDeleteRow=!checkbox.isSelected(); 125 removeRow(row); 126 } 127 }); 128 } else { 129 // no need to show warning, just delete 130 removeRow(row); 131 } 132 } 133 134 /** 135 * Remove Row from table 136 * @param row int row number 137 */ 138 protected void removeRow(int row) { 139 _model._mainArray.remove(row); 140 ThreadingUtil.runOnGUIEventually( ()-> _model.fireTableRowsDeleted(row,row)); 141 } 142 143 protected void updateGuiCell( int row, int col){ 144 ThreadingUtil.runOnGUIEventually(() -> _model.fireTableCellUpdated(row, col)); 145 } 146 147 private void updateStatColumnsinGui( int row){ 148 for (int i : CbusEventTableDataModel.canFrameCols) { 149 updateGuiCell(row,i); 150 } 151 } 152 153 /** 154 * If new event add to table, else update table. 155 * @param m Message to process 156 */ 157 protected void parseMessage( AbstractMessage m) { 158 if (!CbusMessage.isEvent(m)) { // also checks for extended & rtr 159 return; 160 } 161 CbusTableEvent ev = _model.provideEvent(CbusMessage.getNodeNumber(m),CbusMessage.getEvent(m)); 162 ev.setState(CbusTableEvent.getEvState(m)); // sets state, timestamp and on / off count 163 ev.setCanId(CbusMessage.getId(m)); 164 ev.setDataFromFrame(m); 165 ev.bumpDirection( (m instanceof CanReply) ? CbusConstants.EVENT_DIR_IN : CbusConstants.EVENT_DIR_OUT); 166 updateStatColumnsinGui(_model.getEventTableRow(CbusMessage.getNodeNumber(m), CbusMessage.getEvent(m))); 167 168 } 169 170 public void dispose(){ 171 addRemoveListenersToNbManagers(false); 172 } 173 174 // private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusEventTableAction.class); 175}