001package jmri.jmrix.can.cbus.swing.nodeconfig; 002 003import java.awt.BorderLayout; 004import java.awt.event.ActionListener; 005 006import javax.swing.*; 007import javax.swing.event.TableModelEvent; 008import javax.swing.event.TableModelListener; 009 010import jmri.jmrix.can.cbus.node.CbusNode; 011import jmri.jmrix.can.cbus.node.CbusNodeNVTableDataModel; 012import jmri.jmrix.can.cbus.swing.modules.CbusConfigPaneProvider; 013import jmri.jmrix.can.cbus.swing.modules.UnknownPaneProvider; 014import jmri.util.swing.JmriJOptionPane; 015 016/** 017 * 018 * @author Steve Young Copyright (C) 2019 019 */ 020public class CbusNodeEditNVarPane extends CbusNodeConfigTab implements TableModelListener { 021 022 private JTabbedPane tabbedPane; 023 private JPanel infoPane; 024 private CbusNodeNVTableDataModel nodeNVModel; 025 private JButton saveNvButton; 026 private JToggleButton liveUpdateNvButton; 027 private JButton resetNvButton; 028 private JPanel buttonPane; 029 private CbusNodeNVEditTablePane genericNVTable; 030 private CbusNodeNVEditGuiPane editNVGui; 031 private CbusConfigPaneProvider provider; 032 033 private static final int GENERIC = 0; 034 private static final int EDIT = 1; 035 036 /** 037 * Create a new instance of CbusNodeEditNVarPane. 038 * @param main the NodeConfigToolPane this is a component of 039 */ 040 protected CbusNodeEditNVarPane( NodeConfigToolPane main ) { 041 super(main); 042 buildPane(); 043 } 044 045 /** 046 * {@inheritDoc} 047 */ 048 @Override 049 public String getTitle(){ 050 return "Node Variables"; 051 } 052 053 private void buildPane() { 054 055 nodeNVModel = new CbusNodeNVTableDataModel(memo, 5, 056 CbusNodeNVTableDataModel.MAX_COLUMN); // controller, row, column 057 nodeNVModel.addTableModelListener(this); 058 059 infoPane = new JPanel(); 060 infoPane.setLayout(new BorderLayout() ); 061 062 saveNvButton = new JButton(Bundle.getMessage("ButtonSave")); 063 saveNvButton.setToolTipText(Bundle.getMessage("SaveNvButtonTt")); 064 065 liveUpdateNvButton = new JToggleButton(Bundle.getMessage("LiveUpdateNode")); 066 liveUpdateNvButton.setToolTipText(Bundle.getMessage("LiveUpdateNodeTt")); 067 068 resetNvButton = new JButton(Bundle.getMessage("Reset")); 069 resetNvButton.setToolTipText(Bundle.getMessage("ResetTt")); 070 071 ActionListener reset = ae -> { 072 cancelOption(); 073 }; 074 resetNvButton.addActionListener(reset); 075 076 ActionListener save = ae -> { 077 saveOption(); 078 }; 079 saveNvButton.addActionListener(save); 080 081 ActionListener liveUpdate = ae -> { 082 liveUpdateOption(); 083 }; 084 liveUpdateNvButton.addActionListener(liveUpdate); 085 086 buttonPane = new JPanel(); 087 buttonPane.add(liveUpdateNvButton ); 088 buttonPane.add(saveNvButton ); 089 buttonPane.add(resetNvButton ); 090 091 092 infoPane.setLayout(new BorderLayout() ); 093 094 JPanel nvMenuPane = new JPanel(); 095 096 nvMenuPane.add(buttonPane); 097 nvMenuPane.add( new JSeparator(SwingConstants.HORIZONTAL) ); 098 099 genericNVTable = new CbusNodeNVEditTablePane(nodeNVModel); 100 genericNVTable.initComponents(memo); 101 102 editNVGui = new CbusNodeNVEditGuiPane(nodeNVModel); 103 editNVGui.initComponents(memo); 104 105 tabbedPane = new JTabbedPane(); 106 107 tabbedPane.addTab(("Generic"), genericNVTable); 108 tabbedPane.addTab(("Edit"), editNVGui); 109 110 tabbedPane.setEnabledAt(EDIT,false); 111 tabbedPane.setSelectedIndex(GENERIC); 112 113 infoPane.add(nvMenuPane, BorderLayout.PAGE_START); 114 infoPane.add(tabbedPane, BorderLayout.CENTER); 115 116 this.add(infoPane); 117 118 } 119 120 /** 121 * Put the Node into Live Update Mode. 122 * For templates that support this, NV writes are performed immediately. 123 * e.g., for live update of servo position NVs. 124 * Checks if NVs are changed before entering this mode. 125 */ 126 protected void liveUpdateOption() { 127 if ( liveUpdateNvButton.isSelected() && areNvsDirty() ) { 128 JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("LiveUpdateVeto"), 129 nodeOfInterest.toString(), JmriJOptionPane.ERROR_MESSAGE); 130 liveUpdateNvButton.setSelected(false); 131 return; 132 } 133 nodeOfInterest.setliveUpdate(liveUpdateNvButton.isSelected()); 134 } 135 136 /** 137 * {@inheritDoc} 138 * 139 * Save button ( only enabled if changed NVs ) clicked. 140 * Show dialogue to save NVs to module. 141 */ 142 @Override 143 protected void saveOption(){ 144 getMainPane().showConfirmThenSave(nodeNVModel.getChangedNode(),nodeOfInterest, 145 true,false,false, null ); // from, to, nvs, clear events, events, null uses mainpane frame 146 } 147 148 /** 149 * Set the Node and update panes 150 * 151 * Show the edit GUI if available. 152 * 153 * @param node the CbusNode of Interest, can be null 154 */ 155 @Override 156 public void changedNode( CbusNode node ) { 157 log.debug("setnode {}",nodeOfInterest); 158 159 nodeNVModel.setNode(nodeOfInterest); 160 setSaveCancelButtonsActive ( false ); 161 if (nodeOfInterest.getnvWriteInLearnOnly()) { // perhaps in future change to flag in Config Pane Provider? 162 liveUpdateNvButton.setVisible(true); 163 liveUpdateNvButton.setEnabled(true); 164 } else { 165 liveUpdateNvButton.setVisible(false); 166 liveUpdateNvButton.setEnabled(false); 167 } 168 genericNVTable.setNode( nodeOfInterest ); 169 170 provider = CbusConfigPaneProvider.getProviderByNode(nodeOfInterest); 171 editNVGui.setNode(nodeOfInterest, provider); 172 173 if (!(provider instanceof UnknownPaneProvider)) { 174 tabbedPane.setEnabledAt(EDIT, true); 175 tabbedPane.setSelectedIndex(EDIT); 176 } else { 177 tabbedPane.setEnabledAt(EDIT, false); 178 tabbedPane.setSelectedIndex(GENERIC); 179 } 180 181 validate(); 182 repaint(); 183 setVisible(true); 184 } 185 186 /** 187 * Get if any NVs are dirty 188 * @return true if NVs have been edited, else false 189 */ 190 public boolean areNvsDirty(){ 191 log.debug("Table Dirty {}",nodeNVModel.isTableDirty()); 192 return nodeNVModel.isTableDirty(); 193 } 194 195 /** 196 * Reset edited NVs to original value ( or reset edited NV values if mid-load ) 197 * Inform the provider of a the reset 198 */ 199 @Override 200 protected void cancelOption(){ 201 nodeNVModel.resetNewNvs(); 202 editNVGui.setNode(nodeOfInterest); 203 } 204 205 /** 206 * Set the Save / Reset NV button status 207 * 208 * Save button is always enabled when in live update 209 * 210 * @param newstate true if buttons should be enabled, else false 211 */ 212 public void setSaveCancelButtonsActive ( boolean newstate ) { 213 saveNvButton.setEnabled(newstate); 214 resetNvButton.setEnabled(newstate); 215 } 216 217 /** 218 * Sets save / reset buttons active / inactive depending on table status. 219 * Informs the module provider of a table change 220 * {@inheritDoc} 221 */ 222 @Override 223 public void tableChanged(TableModelEvent e) { 224 setSaveCancelButtonsActive( nodeNVModel.isTableDirty() ); 225 editNVGui.tableChanged(e); 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 protected boolean getVetoBeingChanged(){ 233 if (areNvsDirty()) { 234 return getCancelSaveEditDialog( Bundle.getMessage("NvsEditUnsaved",nodeOfInterest) ); 235 } 236 return false; 237 } 238 239 /** 240 * Removes the NV Model listener from the Node. 241 * 242 * Also dispose of the edit gui cleanly, take node out of live update mode 243 */ 244 @Override 245 public void dispose(){ 246 if ( nodeNVModel !=null ) { 247 nodeNVModel.removeTableModelListener(this); 248 nodeNVModel.dispose(); // which does a node setliveUpdate(false) 249 } 250 editNVGui.dispose(); 251 } 252 253 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusNodeEditNVarPane.class); 254 255}