001package jmri.jmrit.symbolicprog; 002 003import java.awt.event.ActionListener; 004import java.util.List; 005import javax.swing.BoxLayout; 006import javax.swing.JButton; 007import javax.swing.JComboBox; 008import javax.swing.JLabel; 009import javax.swing.JPanel; 010import javax.swing.border.EmptyBorder; 011 012import jmri.GlobalProgrammerManager; 013import jmri.Programmer; 014import jmri.jmrit.decoderdefn.DecoderFile; 015import jmri.jmrit.progsupport.ProgModeSelector; 016import jmri.jmrit.roster.IdentifyLoco; 017import jmri.jmrit.roster.Roster; 018import jmri.jmrit.roster.RosterEntry; 019import jmri.jmrit.roster.swing.RosterEntrySelectorPanel; 020import jmri.util.swing.JmriJOptionPane; 021 022/** 023 * Provide GUI controls to select a known loco via the Roster. 024 * <p> 025 * When the "open programmer" button is pushed, i.e. the user is ready to 026 * continue, the startProgrammer method is invoked. This should be overridden 027 * (e.g. in a local anonymous class) to create the programmer frame you're 028 * interested in. 029 * 030 * @author Bob Jacobsen Copyright (C) 2001, 2002 031 */ 032abstract public class KnownLocoSelPane extends LocoSelPane { 033 034 public KnownLocoSelPane(JLabel s, boolean ident, ProgModeSelector selector) { 035 mCanIdent = ident; 036 mStatusLabel = s; 037 this.selector = selector; 038 init(); 039 } 040 041 public KnownLocoSelPane(boolean ident) { 042 this(null, ident, null); 043 } 044 045 boolean mCanIdent; 046 047 JComboBox<String> programmerBox; 048 ProgModeSelector selector; 049 050 protected void init() { 051 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 052 JPanel pane2a = new JPanel(); 053 pane2a.setLayout(new BoxLayout(pane2a, BoxLayout.X_AXIS)); 054 pane2a.add(new JLabel(java.util.ResourceBundle.getBundle("jmri/jmrit/symbolicprog/SymbolicProgBundle").getString("UseExisting"))); 055 056 if (mCanIdent) { 057 JButton idloco = new JButton(java.util.ResourceBundle.getBundle("jmri/jmrit/symbolicprog/SymbolicProgBundle").getString("ReadAndSelect")); 058 idloco.addActionListener(new ActionListener() { 059 @Override 060 public void actionPerformed(java.awt.event.ActionEvent e) { 061 if (log.isDebugEnabled()) { 062 log.debug("Identify locomotive pressed"); 063 } 064 startIdentify(); 065 } 066 }); 067 pane2a.add(idloco); 068 pane2a.setAlignmentX(JLabel.LEFT_ALIGNMENT); 069 } 070 add(pane2a); 071 072 locoBox = new RosterEntrySelectorPanel(); 073 locoBox.setNonSelectedItem("Locomotive"); 074 add(locoBox); 075 076 addProgrammerBox(); 077 078 JButton go2 = new JButton(Bundle.getMessage("OpenProgrammer")); 079 go2.getAccessibleContext().setAccessibleName(Bundle.getMessage("OpenProgrammer")); 080 go2.addActionListener(new ActionListener() { 081 @Override 082 public void actionPerformed(java.awt.event.ActionEvent e) { 083 if (log.isDebugEnabled()) { 084 log.debug("Open programmer pressed"); 085 } 086 openButton(); 087 } 088 }); 089 add(go2); 090 setBorder(new EmptyBorder(6, 6, 6, 6)); 091 } 092 093 /** 094 * Add the GUI for selecting a specific programmer 095 */ 096 private void addProgrammerBox() { 097 JPanel pane3a = new JPanel(); 098 pane3a.setLayout(new BoxLayout(pane3a, BoxLayout.X_AXIS)); 099 pane3a.add(new JLabel(Bundle.getMessage("ProgrammerFormat"))); 100 101 // create the programmer box 102 programmerBox = new JComboBox<String>(ProgDefault.findListOfProgFiles()); 103 programmerBox.setSelectedIndex(0); 104 if (ProgDefault.getDefaultProgFile() != null) { 105 programmerBox.setSelectedItem(ProgDefault.getDefaultProgFile()); 106 } 107 pane3a.add(programmerBox); 108 // pane3a.setAlignmentX(JLabel.RIGHT_ALIGNMENT); 109 add(pane3a); 110 } 111 112 JLabel mStatusLabel = null; 113 114 private void startIdentify() { 115 // start identifying a loco 116 final KnownLocoSelPane me = this; 117 Programmer p = null; 118 if (selector != null && selector.isSelected()) p = selector.getProgrammer(); 119 if (p == null) { 120 log.warn("Selector did not provide a programmer, use default"); 121 p = jmri.InstanceManager.getDefault(GlobalProgrammerManager.class).getGlobalProgrammer(); 122 } 123 IdentifyLoco id = new IdentifyLoco(p) { 124 private KnownLocoSelPane who = me; 125 126 @Override 127 protected void done(int dccAddress) { 128 // if Done, updated the selected decoder 129 who.selectLoco(dccAddress); 130 } 131 132 @Override 133 protected void message(String m) { 134 if (mStatusLabel != null) { 135 mStatusLabel.setText(m); 136 } 137 } 138 139 @Override 140 public void error() { 141 } 142 }; 143 id.start(); 144 } 145 146 protected void selectLoco(int dccAddress) { 147 // locate that loco 148 List<RosterEntry> l = Roster.getDefault().matchingList(null, null, Integer.toString(dccAddress), 149 null, null, null, null); 150 if (log.isDebugEnabled()) { 151 log.debug("selectLoco found {} matches", l.size()); 152 } 153 if (l.size() > 0) { 154 RosterEntry r = l.get(0); 155 String id = r.getId(); 156 if (log.isDebugEnabled()) { 157 log.debug("Loco id is {}", id); 158 } 159 String group = locoBox.getSelectedRosterGroup(); 160 if (group != null && !group.equals(Roster.ALLENTRIES)) { 161 List<RosterEntry> entries = Roster.getDefault().getEntriesWithAttributeKeyValue(Roster.getRosterGroupProperty(group), "yes"); 162 if (entries.contains(r)) { 163 locoBox.setSelectedRosterEntry(r); 164 } else { 165 locoBox.setSelectedRosterEntryAndGroup(r, Roster.ALLENTRIES); 166 } 167 } else { 168 locoBox.setSelectedRosterEntry(r); 169 } 170 } else { 171 log.warn("Read address {}, but no such loco in roster", dccAddress); 172 } 173 } 174 175 private RosterEntrySelectorPanel locoBox = null; 176 177 /** 178 * handle pushing the open programmer button by finding names, then calling 179 * a template method 180 */ 181 protected void openButton() { 182 183 if (locoBox.getSelectedRosterEntries().length != 0) { 184 RosterEntry re = locoBox.getSelectedRosterEntries()[0]; 185 startProgrammer(null, re, (String) programmerBox.getSelectedItem()); 186 } else { 187 JmriJOptionPane.showMessageDialog(this, 188 Bundle.getMessage("LocoMustSelected"), 189 Bundle.getMessage("NoSelection"), 190 JmriJOptionPane.ERROR_MESSAGE); 191 } 192 } 193 194 195 /* 196 * Start the programming operation(s). 197 * @param decoderFile contains decoder definition 198 * @param r contains locomotive-specific roster information 199 * @param programmerName used to find the right programmer for the operation. 200 */ 201 abstract protected void startProgrammer(DecoderFile decoderFile, RosterEntry r, 202 String programmerName); 203 204 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(KnownLocoSelPane.class); 205 206}