001package jmri.jmrit.progsupport;
002
003import java.awt.event.ActionEvent;
004import java.awt.event.ActionListener;
005import java.beans.PropertyChangeListener;
006import java.util.ArrayList;
007import java.util.List;
008import java.util.Vector;
009import javax.swing.BoxLayout;
010import javax.swing.DefaultComboBoxModel;
011import javax.swing.JComboBox;
012import javax.swing.JLabel;
013
014import jmri.*;
015import org.slf4j.Logger;
016import org.slf4j.LoggerFactory;
017
018/**
019 * Provide a JPanel with a JComboBox to configure the service mode (Global) programmer.
020 * <p>
021 * The using code should get a configured programmer with {@link #getProgrammer()}.
022 * <p>
023 * A ProgModePane may "share" between one of these and a ProgOpsModePane, which
024 * means that there might be _none_ of these buttons selected. When that
025 * happens, the mode of the underlying programmer is left unchanged and no
026 * message is propagated.
027 * <p>
028 * Note that you should call the dispose() method when you're really done, so
029 * that a ProgModePane object can disconnect its listeners.
030 *
031 * <hr>
032 * This file is part of JMRI.
033 * <p>
034 * JMRI is free software; you can redistribute it and/or modify it under the
035 * terms of version 2 of the GNU General Public License as published by the Free
036 * Software Foundation. See the "COPYING" file for a copy of this license.
037 * <p>
038 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
039 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
040 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
041 *
042 * @author Bob Jacobsen Copyright (C) 2001
043 */
044public class ProgServiceModeComboBox extends ProgModeSelector implements PropertyChangeListener, ActionListener {
045
046    // GUI member declarations
047    JLabel progLabel = new JLabel(Bundle.getMessage("ProgrammerLabel"));
048    JComboBox<GlobalProgrammerManager> progBox;
049    JComboBox<ProgrammingMode> modeBox;
050    ArrayList<Integer> modes = new ArrayList<Integer>();
051
052    /**
053     * Get the configured programmer
054     */
055    @Override
056    public Programmer getProgrammer() {
057        if (progBox == null) {
058            log.trace("getProgrammer returns null with no progBox");
059            return null;
060        }
061        GlobalProgrammerManager pm = (GlobalProgrammerManager) progBox.getSelectedItem();
062        if (pm == null) {
063            log.trace("getProgrammer returns null with no selection");
064            return null;
065        }
066        log.trace("getProgrammer returns {}", pm.getGlobalProgrammer());
067        return pm.getGlobalProgrammer();
068    }
069
070    /**
071     * Are any of the modes selected?
072     *
073     * @return true
074     */
075    @Override
076    public boolean isSelected() {
077        return true;
078    }
079
080    public ProgServiceModeComboBox() {
081        this(BoxLayout.X_AXIS);
082    }
083
084    /**
085     * Get the list of Global ProgrammingManagers.
086     *
087     * @return empty list if none
088     */
089    protected final List<GlobalProgrammerManager> getMgrList() {
090        var list = InstanceManager.getList(jmri.GlobalProgrammerManager.class);
091        log.trace("gtMgrList returns {}", list.size());
092        return list;
093    }
094
095    public ProgServiceModeComboBox(int direction) {
096        log.trace("ctor starts");
097        modeBox = new JComboBox<ProgrammingMode>();
098        modeBox.addActionListener(this);
099
100        // general GUI config
101        setLayout(new BoxLayout(this, direction));
102
103        // create the programmer display combo box
104        progBox = new JComboBox<>();
105        Vector<GlobalProgrammerManager> v = new Vector<>();
106        for (GlobalProgrammerManager pm : getMgrList()) {
107            Programmer globProg = null;
108            if (pm != null) {
109                globProg = pm.getGlobalProgrammer();
110            }
111            if (globProg != null) {
112                v.add(pm);
113                log.debug("ProgServiceModeComboBox added programmer {} as item {}",
114                        (pm != null ? pm.getClass() : "null"), pm);
115                // listen for changes
116                globProg.addPropertyChangeListener(this);
117            }
118        }
119
120        add(progLabel);
121        add(progBox = new JComboBox<>(v));
122        progBox.getAccessibleContext().setAccessibleName(Bundle.getMessage("ProgrammerLabel"));
123
124        // if only one, don't show is confusing to user, so show combo with just 1 choice)
125        progBox.setSelectedItem(InstanceManager.getDefault(jmri.GlobalProgrammerManager.class)); // set default
126        progBox.addActionListener(new ActionListener() {
127            @Override
128            public void actionPerformed(ActionEvent e) {
129                // new programmer selection
130                programmerSelected();
131            }
132        });
133        log.trace("progBox loadeded with {}", progBox.getItemCount());
134
135        // install mode selection items in GUI
136        add(new JLabel(Bundle.getMessage("ProgrammingModeLabel")));
137        add(modeBox);
138        modeBox.getAccessibleContext().setAccessibleName(Bundle.getMessage("ProgrammingModeLabel"));
139
140        // and execute the setup for 1st time
141        programmerSelected();
142        log.trace("ctor ends");
143    }
144
145    /**
146     * Reload the interface with the new programming modes
147     */
148    void programmerSelected() {
149        DefaultComboBoxModel<ProgrammingMode> model = new DefaultComboBoxModel<>();
150        Programmer p = getProgrammer();
151        if (p != null) {
152            for (ProgrammingMode mode : p.getSupportedModes()) {
153                model.addElement(mode);
154            }
155        }
156        log.trace("programmerSelected setting modes");
157        modeBox.setModel(model);
158        ProgrammingMode mode = (p != null) ? p.getMode() : null;
159        log.trace("programmerSelected set mode {}", mode);
160        modeBox.setSelectedItem(mode);
161    }
162
163    /**
164     * Listen to modeBox for mode changes
165     */
166    @Override
167    public void actionPerformed(java.awt.event.ActionEvent e) {
168        // convey change to programmer
169        log.debug("Selected mode: {}", modeBox.getSelectedItem());
170        if (modeBox.getSelectedItem() != null) {
171            getProgrammer().setMode((ProgrammingMode) modeBox.getSelectedItem());
172        }
173    }
174
175    /**
176     * Listen to programmer for mode changes
177     */
178    @Override
179    public void propertyChange(java.beans.PropertyChangeEvent e) {
180        if ("Mode".equals(e.getPropertyName()) && getProgrammer().equals(e.getSource())) {
181            // mode changed in programmer, change GUI here if needed
182            if (isSelected()) {  // if we're not holding a current mode, don't update
183                modeBox.setSelectedItem(e.getNewValue());
184            }
185        }
186    }
187
188    // no longer needed, disconnect if still connected
189    @Override
190    public void dispose() {
191    }
192    private final static Logger log = LoggerFactory.getLogger(ProgServiceModeComboBox.class);
193}