001package jmri.jmrix.openlcb.swing;
002
003import jmri.*;
004import jmri.jmrit.beantable.signalmast.SignalMastAddPane;
005import jmri.SystemConnectionMemo;
006
007import jmri.jmrix.openlcb.*;
008
009import java.awt.*;
010import java.text.DecimalFormat;
011import java.util.*;
012import java.util.List;
013
014import javax.swing.*;
015import javax.swing.border.TitledBorder;
016import javax.annotation.Nonnull;
017
018import org.openide.util.lookup.ServiceProvider;
019import org.openlcb.swing.EventIdTextField;
020
021/**
022 * A pane for configuring OlcbSignalMast objects
023 *
024 * @see jmri.jmrit.beantable.signalmast.SignalMastAddPane
025 * @author Bob Jacobsen Copyright (C) 2018
026 * @since 4.11.2
027 */
028public class OlcbSignalMastAddPane extends SignalMastAddPane {
029
030    public OlcbSignalMastAddPane() {
031        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
032
033        litEventID.setText("00.00.00.00.00.00.00.00");
034        notLitEventID.setText("00.00.00.00.00.00.00.00");
035        heldEventID.setText("00.00.00.00.00.00.00.00");
036        notHeldEventID.setText("00.00.00.00.00.00.00.00");
037
038        // lit/unlit controls
039        JPanel p = new JPanel();
040        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
041        p.add(new JLabel(Bundle.getMessage("AllowUnLitLabel") + ": "));
042        p.add(allowUnLit);
043        p.setAlignmentX(Component.LEFT_ALIGNMENT);
044        add(p);
045        
046        // aspects controls
047        TitledBorder disableborder = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black));
048        disableborder.setTitle(Bundle.getMessage("EnterAspectsLabel"));
049        JScrollPane disabledAspectsScroll = new JScrollPane(disabledAspectsPanel);
050        disabledAspectsScroll.setBorder(disableborder);
051        add(disabledAspectsScroll);
052        
053        JPanel p5;
054
055        // Lit
056        TitledBorder litborder = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black));
057        litborder.setTitle(Bundle.getMessage("LitUnLit"));
058        JPanel pLit = new JPanel();
059        pLit.setBorder(litborder);
060        pLit.setLayout(new BoxLayout(pLit, BoxLayout.Y_AXIS));
061        
062        p5 = new JPanel();
063        p5.setLayout(new BoxLayout(p5, BoxLayout.X_AXIS));
064        p5.add(new JLabel(Bundle.getMessage("LitLabel")));
065        p5.add(Box.createHorizontalGlue());
066        pLit.add(p5);
067        pLit.add(litEventID);
068        
069        p5 = new JPanel();
070        p5.setLayout(new BoxLayout(p5, BoxLayout.X_AXIS));
071        p5.add(new JLabel(Bundle.getMessage("NotLitLabel")));
072        p5.add(Box.createHorizontalGlue());
073        pLit.add(p5);
074        pLit.add(notLitEventID);
075        
076        add(pLit);
077       
078        // Held
079        TitledBorder heldborder = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black));
080        heldborder.setTitle(Bundle.getMessage("HeldUnHeld"));
081        JPanel pHeld= new JPanel();
082        pHeld.setBorder(heldborder);
083        pHeld.setLayout(new BoxLayout(pHeld, BoxLayout.Y_AXIS));
084        
085        p5 = new JPanel();
086        p5.setLayout(new BoxLayout(p5, BoxLayout.X_AXIS));
087        p5.add(new JLabel(Bundle.getMessage("HeldLabel")));
088        p5.add(Box.createHorizontalGlue());
089        pHeld.add(p5);
090        pHeld.add(heldEventID);
091        
092        p5 = new JPanel();
093        p5.setLayout(new BoxLayout(p5, BoxLayout.X_AXIS));
094        p5.add(new JLabel(Bundle.getMessage("NotHeldLabel")));
095        p5.add(Box.createHorizontalGlue());
096        pHeld.add(p5);
097        pHeld.add(notHeldEventID);
098        
099        add(pHeld);
100
101    }
102
103    /** {@inheritDoc} */
104    @Override
105    @Nonnull public String getPaneName() {
106        return Bundle.getMessage("OlcbSignalMastPane");
107    }
108
109
110    final JCheckBox allowUnLit = new JCheckBox();
111
112    LinkedHashMap<String, JCheckBox> disabledAspects = new LinkedHashMap<>(NOTIONAL_ASPECT_COUNT);
113    final LinkedHashMap<String, EventIdTextField> aspectEventIDs = new LinkedHashMap<>(NOTIONAL_ASPECT_COUNT);
114    final JPanel disabledAspectsPanel = new JPanel();
115    final EventIdTextField litEventID = new EventIdTextField();
116    final EventIdTextField notLitEventID = new EventIdTextField();
117    final EventIdTextField heldEventID = new EventIdTextField();
118    final EventIdTextField notHeldEventID = new EventIdTextField();
119
120    OlcbSignalMast currentMast = null;
121
122    /** {@inheritDoc} */
123    @Override
124    public void setAspectNames(@Nonnull SignalAppearanceMap map, @Nonnull SignalSystem sigSystem) {
125        Enumeration<String> aspects = map.getAspects();
126        // update immediately
127        disabledAspects = new LinkedHashMap<>(NOTIONAL_ASPECT_COUNT);
128        disabledAspectsPanel.removeAll();
129        while (aspects.hasMoreElements()) {
130            String aspect = aspects.nextElement();
131            JCheckBox disabled = new JCheckBox(aspect);
132            disabledAspects.put(aspect, disabled);
133            EventIdTextField eventID = new EventIdTextField();
134            eventID.setText("00.00.00.00.00.00.00.00");
135            aspectEventIDs.put(aspect, eventID);
136        }
137        disabledAspectsPanel.setLayout(new BoxLayout(disabledAspectsPanel, BoxLayout.Y_AXIS));
138        for (Map.Entry<String, JCheckBox> entry : disabledAspects.entrySet()) {
139            JPanel p1 = new JPanel();
140            TitledBorder p1border = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black));
141            p1border.setTitle(entry.getKey());
142            p1.setBorder(p1border);
143            p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
144            p1.add(aspectEventIDs.get(entry.getKey()));
145            p1.add(entry.getValue());
146            entry.getValue().setName(entry.getKey());
147            entry.getValue().setText(Bundle.getMessage("DisableAspect"));
148            disabledAspectsPanel.add(p1);
149        }
150
151        litEventID.setText("00.00.00.00.00.00.00.00");
152        notLitEventID.setText("00.00.00.00.00.00.00.00");
153        heldEventID.setText("00.00.00.00.00.00.00.00");
154        notHeldEventID.setText("00.00.00.00.00.00.00.00");
155
156        disabledAspectsPanel.revalidate();
157    }
158
159    /** {@inheritDoc} */
160    @Override
161    public boolean canHandleMast(@Nonnull SignalMast mast) {
162        return mast instanceof OlcbSignalMast;
163    }
164
165    /** {@inheritDoc} */
166    @Override
167    public void setMast(SignalMast mast) { 
168        if (mast == null) { 
169            currentMast = null; 
170            return; 
171        }
172        
173        if (! (mast instanceof OlcbSignalMast) ) {
174            log.error("mast was wrong type: {} {}", mast.getSystemName(), mast.getClass().getName());
175            return;
176        }
177
178        currentMast = (OlcbSignalMast) mast;
179        List<String> disabled = currentMast.getDisabledAspects();
180        if (disabled != null) {
181            for (String aspect : disabled) {
182                if (disabledAspects.containsKey(aspect)) {
183                    disabledAspects.get(aspect).setSelected(true);
184                }
185            }
186         }
187        for (String aspect : currentMast.getAllKnownAspects()) {
188            if (aspectEventIDs.get(aspect) == null) {
189                EventIdTextField eventID = new EventIdTextField();
190                eventID.setText("00.00.00.00.00.00.00.00");
191                aspectEventIDs.put(aspect, eventID);
192            }
193            if (currentMast.isOutputConfigured(aspect)) {
194                aspectEventIDs.get(aspect).setText(currentMast.getOutputForAppearance(aspect));
195            } else {
196                aspectEventIDs.get(aspect).setText("00.00.00.00.00.00.00.00");
197            }
198        }
199
200        litEventID.setText(currentMast.getLitEventId());
201        notLitEventID.setText(currentMast.getNotLitEventId());
202        heldEventID.setText(currentMast.getHeldEventId());
203        notHeldEventID.setText(currentMast.getNotHeldEventId());        
204
205        allowUnLit.setSelected(currentMast.allowUnLit());
206
207        log.debug("setMast({})", mast);
208    }
209
210    final DecimalFormat paddedNumber = new DecimalFormat("0000");
211
212    /** {@inheritDoc} */
213    @Override
214    public boolean createMast(@Nonnull String sigsysname,
215                              @Nonnull String mastname,
216                              @Nonnull String username) {
217        if (currentMast == null) {
218            // create a mast
219            String type = mastname.substring(11, mastname.length() - 4);
220            String name = "MF$olm:" + sigsysname + ":" + type;
221            name += "($" + (paddedNumber.format(OlcbSignalMast.getLastRef() + 1)) + ")";
222            currentMast = new OlcbSignalMast(name);
223            if (!username.equals("")) {
224                currentMast.setUserName(username);
225            }
226            currentMast.setMastType(type);
227            InstanceManager.getDefault(jmri.SignalMastManager.class).register(currentMast);
228        }
229        
230        // load a new or existing mast
231        for (Map.Entry<String, JCheckBox> entry : disabledAspects.entrySet()) {
232            if (entry.getValue().isSelected()) {
233                currentMast.setAspectDisabled(entry.getKey());
234            } else {
235                currentMast.setAspectEnabled(entry.getKey());
236            }
237            currentMast.setOutputForAppearance(entry.getKey(), aspectEventIDs.get(entry.getKey()).getText());
238        }
239        
240        currentMast.setLitEventId(litEventID.getText());
241        currentMast.setNotLitEventId(notLitEventID.getText());
242        currentMast.setHeldEventId(heldEventID.getText());
243        currentMast.setNotHeldEventId(notHeldEventID.getText());
244
245        currentMast.setAllowUnLit(allowUnLit.isSelected());
246        return true;
247    }
248
249
250    @ServiceProvider(service = SignalMastAddPane.SignalMastAddPaneProvider.class)
251    static public class SignalMastAddPaneProvider extends SignalMastAddPane.SignalMastAddPaneProvider {
252
253        /**
254         * {@inheritDoc}
255         * Requires a valid OpenLCB connection
256         */
257        @Override
258        public boolean isAvailable() {
259            for (SystemConnectionMemo memo : InstanceManager.getList(SystemConnectionMemo.class)) {
260                if (memo instanceof jmri.jmrix.can.CanSystemConnectionMemo) {
261                    return true;
262                }
263            }
264            return false;
265        }
266
267        /** {@inheritDoc} */
268        @Override
269        @Nonnull public String getPaneName() {
270            return Bundle.getMessage("OlcbSignalMastPane");
271        }
272
273        /** {@inheritDoc} */
274        @Override
275        @Nonnull public SignalMastAddPane getNewPane() {
276            return new OlcbSignalMastAddPane();
277        }
278    }
279
280    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OlcbSignalMastAddPane.class);
281
282}