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        this.setOpaque(false);
103
104        // create the programmer display combo box
105        progBox = new JComboBox<>();
106        Vector<GlobalProgrammerManager> v = new Vector<>();
107        for (GlobalProgrammerManager pm : getMgrList()) {
108            Programmer globProg = null;
109            if (pm != null) {
110                globProg = pm.getGlobalProgrammer();
111            }
112            if (globProg != null) {
113                v.add(pm);
114                log.debug("ProgServiceModeComboBox added programmer {} as item {}",
115                        (pm != null ? pm.getClass() : "null"), pm);
116                // listen for changes
117                globProg.addPropertyChangeListener(this);
118            }
119        }
120
121        add(progLabel);
122        add(progBox = new JComboBox<>(v));
123        progBox.getAccessibleContext().setAccessibleName(Bundle.getMessage("ProgrammerLabel"));
124
125        // if only one, don't show is confusing to user, so show combo with just 1 choice)
126        progBox.setSelectedItem(InstanceManager.getDefault(jmri.GlobalProgrammerManager.class)); // set default
127        progBox.addActionListener(new ActionListener() {
128            @Override
129            public void actionPerformed(ActionEvent e) {
130                // new programmer selection
131                programmerSelected();
132            }
133        });
134        log.trace("progBox loadeded with {}", progBox.getItemCount());
135
136        // install mode selection items in GUI
137        add(new JLabel(Bundle.getMessage("ProgrammingModeLabel")));
138        add(modeBox);
139        modeBox.getAccessibleContext().setAccessibleName(Bundle.getMessage("ProgrammingModeLabel"));
140
141        // and execute the setup for 1st time
142        programmerSelected();
143        log.trace("ctor ends");
144    }
145
146    /**
147     * Reload the interface with the new programming modes
148     */
149    void programmerSelected() {
150        DefaultComboBoxModel<ProgrammingMode> model = new DefaultComboBoxModel<>();
151        Programmer p = getProgrammer();
152        if (p != null) {
153            for (ProgrammingMode mode : p.getSupportedModes()) {
154                model.addElement(mode);
155            }
156        }
157        log.trace("programmerSelected setting modes");
158        modeBox.setModel(model);
159        ProgrammingMode mode = (p != null) ? p.getMode() : null;
160        log.trace("programmerSelected set mode {}", mode);
161        modeBox.setSelectedItem(mode);
162    }
163
164    /**
165     * Listen to modeBox for mode changes
166     */
167    @Override
168    public void actionPerformed(java.awt.event.ActionEvent e) {
169        // convey change to programmer
170        log.debug("Selected mode: {}", modeBox.getSelectedItem());
171        if (modeBox.getSelectedItem() != null) {
172            getProgrammer().setMode((ProgrammingMode) modeBox.getSelectedItem());
173        }
174    }
175
176    /**
177     * Listen to programmer for mode changes
178     */
179    @Override
180    public void propertyChange(java.beans.PropertyChangeEvent e) {
181        if ("Mode".equals(e.getPropertyName()) && getProgrammer().equals(e.getSource())) {
182            // mode changed in programmer, change GUI here if needed
183            if (isSelected()) {  // if we're not holding a current mode, don't update
184                modeBox.setSelectedItem(e.getNewValue());
185            }
186        }
187    }
188
189    // no longer needed, disconnect if still connected
190    @Override
191    public void dispose() {
192    }
193    private static final Logger log = LoggerFactory.getLogger(ProgServiceModeComboBox.class);
194}