001package jmri.jmrix.can.cbus.swing.nodeconfig;
002
003import java.awt.BorderLayout;
004import java.beans.PropertyChangeEvent;
005import java.beans.PropertyChangeListener;
006
007import javax.annotation.Nonnull;
008import javax.annotation.OverridingMethodsMustInvokeSuper;
009
010import jmri.jmrix.can.cbus.node.CbusNode;
011import jmri.util.swing.JmriJOptionPane;
012
013/**
014 *
015 * @author Steve Young Copyright (C) 2019, 2020
016 */
017abstract public class CbusNodeConfigTab extends jmri.jmrix.can.swing.CanPanel implements PropertyChangeListener {
018    
019    protected CbusNode nodeOfInterest;
020    private final NodeConfigToolPane mainpane;
021    private boolean _activeDialogue;
022
023    /**
024     * Create a new instance of CbusNodeSetupPane.
025     * @param main the main NodeConfigToolPane this is a pane of.
026     */
027    protected CbusNodeConfigTab( NodeConfigToolPane main ) {
028        super();
029        mainpane = main;
030        if (main != null ){
031            super.initComponents(main.getMemo());
032        }
033        super.setLayout(new BorderLayout() );
034        _activeDialogue = false;
035    }
036    
037    /**
038     * Get the Main Node Manager Pane.
039     * @return Manager Pane
040     */
041    protected NodeConfigToolPane getMainPane(){
042        return mainpane;
043    }
044    
045    /**
046     * Set the Node displayed in the Pane.
047     * Checks for node unchanged and
048     * disposes listeners on previous node.
049     * @param node New CbusNode to display
050     */
051    public final void setNode(CbusNode node){
052        if ( nodeOfInterest != null ) {
053            if (nodeOfInterest.equals(node)){
054            return;
055            }
056            disposeOfNode(nodeOfInterest);
057        }
058        if ( node != null ) {
059            nodeOfInterest = node;
060            nodeOfInterest.addPropertyChangeListener(this);
061            changedNode(node);
062            this.setVisible(true);
063            validate();
064            repaint();
065        }
066    }
067    
068    /**
069     * Stop the tab or Node selection switching from the Pane.
070     * Defaults to false
071     * @return true to veto, false to not veto
072     */
073    protected boolean getVetoBeingChanged(){
074        return false;
075    }
076    
077    /**
078     * Set that a Dialog box is open within the Pane.
079     * @param newVal true if being displayed, else false
080     */
081    protected void setActiveDialog(boolean newVal){
082        _activeDialogue = newVal;
083    }
084    
085    /**
086     * Get if a Dialog box is open within the Pane.
087     * @return true if displaying dialog, else false
088     */
089    protected boolean getActiveDialog(){
090        return _activeDialogue;
091    }
092    
093    /**
094     * Get the Tab Index within the Main Node Manager Pane
095     * @return index for this pane
096     */
097    protected final int getTabIndex(){
098        return getMainPane().getTabs().indexOf(this);
099    }
100    
101    /**
102     * Extending classes must implement this for changed node notifications
103     * @param node The new Node
104     */
105    protected abstract void changedNode(@Nonnull CbusNode node);
106    
107    /**
108     * Remove any update listeners for the node.
109     * @param node Node to remove listeners for
110     */
111    @OverridingMethodsMustInvokeSuper // to remove Node Property Change Listener
112    protected void disposeOfNode(@Nonnull CbusNode node){
113        node.removePropertyChangeListener(this);
114    }
115    
116    /**
117     * Get the index of the node in the main Node Table
118     * @return Row Number for the CbusNode nodeOfInterest
119     */
120    protected int getNodeRow(){
121        return getMainPane().nodeTable.convertRowIndexToView(getMainPane().
122            getNodeModel().getNodeRowFromNodeNum(nodeOfInterest.getNodeNumber()));
123    }
124    
125    /**
126     * Reset the Main Node Manager pane to that of the vetoing Pane.
127     */
128    protected void resetViewToVeto(){
129        getMainPane().nodeTable.getSelectionModel().clearSelection();
130        getMainPane().nodeTable.getSelectionModel().setSelectionInterval(getNodeRow(),getNodeRow());
131        getMainPane().tabbedPane.setSelectedIndex(getTabIndex());
132    }
133    
134    /**
135     * Get a Cancel Edit / Save Edit / Continue Edit Dialog.
136     * @param adviceString Extra text to display in box without opening / closing html tag.
137     * @return true to veto, else false to proceed and continue.
138     */
139    protected boolean getCancelSaveEditDialog(String adviceString){
140        setActiveDialog(true);
141        resetViewToVeto();
142        int selectedValue = JmriJOptionPane.showOptionDialog(this.getParent(),
143            "<html>" + adviceString + "<br>" + Bundle.getMessage("ContinueEditQuestion")+"</html>"
144            ,Bundle.getMessage("WarningTitle") + " " + nodeOfInterest,
145            JmriJOptionPane.DEFAULT_OPTION,JmriJOptionPane.QUESTION_MESSAGE, null,
146            new String[]{Bundle.getMessage("CancelEdit"), Bundle.getMessage("SaveEdit"), Bundle.getMessage("ContinueEdit")},
147            Bundle.getMessage("ContinueEdit")); // default choice
148        
149        setActiveDialog(false);
150        switch (selectedValue) {
151            case -1: // Dialog Closed
152            case 0: // array position 0, CancelEdit
153                cancelOption();
154                return false;
155            case 1: // array position 1, SaveEdit
156                saveOption();
157                return false;
158            default: // array position 2, ContinueEdit
159                return true;
160        }
161    }
162    
163    /**
164     * Custom Cancel action for getCancelSaveEditDialog.
165     */
166    protected void cancelOption() {}
167    
168    /**
169     * Custom Save action for getCancelSaveEditDialog.
170     */
171    protected void saveOption() {}
172    
173    /**
174     * {@inheritDoc}
175     * Get updates from the CbusNode nodeOfInterest
176     */
177    @Override
178    public void propertyChange(PropertyChangeEvent ev){
179    }
180    
181    /**
182     * {@inheritDoc}
183     */
184    @Override
185    public void dispose(){
186        if (nodeOfInterest!=null){
187            disposeOfNode(nodeOfInterest);
188        }
189        super.dispose();
190    }
191    
192    // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusNodeConfigTab.class);
193    
194}