001package jmri.jmrit.beantable.signalmast; 002 003import java.awt.*; 004import java.awt.event.*; 005import java.text.DecimalFormat; 006import java.util.*; 007 008import javax.annotation.Nonnull; 009import javax.swing.*; 010import javax.swing.border.TitledBorder; 011 012import jmri.*; 013import jmri.implementation.TurnoutSignalMast; 014import jmri.util.swing.BeanSelectCreatePanel; 015 016import org.openide.util.lookup.ServiceProvider; 017 018/** 019 * A pane for configuring TurnoutSignalMast objects. 020 * 021 * @see jmri.jmrit.beantable.signalmast.SignalMastAddPane 022 * @author Bob Jacobsen Copyright (C) 2017, 2018 023 * @since 4.11.2 024 */ 025public class TurnoutSignalMastAddPane extends SignalMastAddPane { 026 027 public TurnoutSignalMastAddPane() { 028 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 029 // lit/unlit controls 030 JPanel p = new JPanel(); 031 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 032 p.add(new JLabel(Bundle.getMessage("AllowUnLitLabel") + ": ")); 033 p.add(allowUnLit); 034 p.setAlignmentX(Component.LEFT_ALIGNMENT); 035 add(p); 036 037 turnoutMastScroll = new JScrollPane(turnoutMastPanel); 038 turnoutMastScroll.setBorder(BorderFactory.createEmptyBorder()); 039 add(turnoutMastScroll); 040 } 041 042 /** {@inheritDoc} */ 043 @Override 044 @Nonnull public String getPaneName() { 045 return Bundle.getMessage("TurnCtlMast"); 046 } 047 048 JPanel turnoutMastPanel = new JPanel(); 049 JScrollPane turnoutMastScroll; 050 JCheckBox resetPreviousState = new JCheckBox(Bundle.getMessage("ResetPrevious")); 051 052 JCheckBox allowUnLit = new JCheckBox(); 053 054 LinkedHashMap<String, TurnoutAspectPanel> turnoutAspect = new LinkedHashMap<>(NOTIONAL_ASPECT_COUNT); // only used once, see updateTurnoutAspectPanel() 055 JPanel disabledAspectsPanel = new JPanel(); 056 057 TurnoutSignalMast currentMast = null; 058 059 /** {@inheritDoc} */ 060 @Override 061 public void setAspectNames(@Nonnull SignalAppearanceMap map, @Nonnull SignalSystem sigSystem) { 062 Enumeration<String> aspects = map.getAspects(); 063 log.debug("setAspectNames(...)"); 064 065 turnoutAspect.clear(); 066 while (aspects.hasMoreElements()) { 067 String aspect = aspects.nextElement(); 068 TurnoutAspectPanel aPanel = new TurnoutAspectPanel(aspect); 069 turnoutAspect.put(aspect, aPanel); 070 } 071 072 turnoutMastPanel.removeAll(); 073 for (Map.Entry<String, TurnoutAspectPanel> entry : turnoutAspect.entrySet()) { 074 log.trace(" aspect: {}", entry.getKey()); 075 turnoutMastPanel.add(entry.getValue().getPanel()); 076 } 077 078 turnoutMastPanel.add(resetPreviousState); 079 resetPreviousState.setToolTipText(Bundle.getMessage("ResetPreviousToolTip")); 080 081 turnoutMastPanel.setLayout(new jmri.util.javaworld.GridLayout2(0, 2)); // 0 means enough 082 083 turnoutMastPanel.revalidate(); 084 turnoutMastScroll.revalidate(); 085 } 086 087 /** {@inheritDoc} */ 088 @Override 089 public boolean canHandleMast(@Nonnull SignalMast mast) { 090 return mast instanceof TurnoutSignalMast; 091 } 092 093 /** {@inheritDoc} */ 094 @Override 095 public void setMast(SignalMast mast) { 096 log.trace("setMast({}) start", mast); 097 if (mast == null) { 098 currentMast = null; 099 return; 100 } 101 102 if (! (mast instanceof TurnoutSignalMast) ) { 103 log.error("mast was wrong type: {} {}", mast.getSystemName(), mast.getClass().getName()); 104 return; 105 } 106 107 currentMast = (TurnoutSignalMast) mast; 108 SignalAppearanceMap appMap = mast.getAppearanceMap(); 109 110 if (appMap != null) { 111 Enumeration<String> aspects = appMap.getAspects(); 112 while (aspects.hasMoreElements()) { 113 String key = aspects.nextElement(); 114 Objects.requireNonNull(key, "only non-null keys are expected"); 115 TurnoutAspectPanel turnPanel = turnoutAspect.get(key); 116 Objects.requireNonNull(turnPanel, "a panel should exist for each aspect"); 117 turnPanel.setSelectedTurnout(currentMast.getTurnoutName(key)); 118 turnPanel.setTurnoutState(currentMast.getTurnoutState(key)); 119 turnPanel.setAspectDisabled(currentMast.isAspectDisabled(key)); 120 } 121 } 122 if (currentMast.resetPreviousStates()) { 123 resetPreviousState.setSelected(true); 124 } 125 if (currentMast.allowUnLit()) { 126 turnoutUnLitBox.setDefaultNamedBean(currentMast.getUnLitTurnout()); 127 if (currentMast.getUnLitTurnoutState() == Turnout.CLOSED) { 128 turnoutUnLitState.setSelectedItem(stateClosed); 129 } else { 130 turnoutUnLitState.setSelectedItem(stateThrown); 131 } 132 133 } 134 135 allowUnLit.setSelected(currentMast.allowUnLit()); 136 137 log.trace("setMast({}) end", mast); 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 public boolean createMast(@Nonnull String sigsysname, @Nonnull String mastname, @Nonnull String username) { 143 log.debug("createMast({},{})", sigsysname, mastname); 144 String name; 145 if (currentMast == null) { 146 name = "IF$tsm:" 147 + sigsysname 148 + ":" + mastname.substring(11, mastname.length() - 4); 149 name += "($" + (paddedNumber.format(TurnoutSignalMast.getLastRef() + 1)) + ")"; 150 currentMast = new TurnoutSignalMast(name); 151 152 InstanceManager.getDefault(jmri.SignalMastManager.class).register(currentMast); 153 } 154 name = currentMast.getSystemName(); 155 156 // load a new or existing mast 157 for (Map.Entry<String, TurnoutAspectPanel> entry : turnoutAspect.entrySet()) { 158 entry.getValue().setReference(name + ":" + entry.getKey()); 159 turnoutMastPanel.add(entry.getValue().getPanel()); 160 if (entry.getValue().isAspectDisabled()) { 161 currentMast.setAspectDisabled(entry.getKey()); 162 } else { 163 currentMast.setAspectEnabled(entry.getKey()); 164 currentMast.setTurnout(entry.getKey(), entry.getValue().getTurnoutName(), entry.getValue().getTurnoutState()); 165 } 166 } 167 currentMast.resetPreviousStates(resetPreviousState.isSelected()); 168 if (!username.isEmpty()) { 169 currentMast.setUserName(username); 170 } 171 currentMast.setAllowUnLit(allowUnLit.isSelected()); 172 if (allowUnLit.isSelected()) { 173 currentMast.setUnLitTurnout(turnoutUnLitBox.getDisplayName(), turnoutStateValues[turnoutUnLitState.getSelectedIndex()]); 174 } 175 return true; 176 } 177 178 String stateThrown = InstanceManager.turnoutManagerInstance().getThrownText(); 179 String stateClosed = InstanceManager.turnoutManagerInstance().getClosedText(); 180 181 String[] turnoutStates = new String[]{stateClosed, stateThrown}; 182 int[] turnoutStateValues = new int[]{Turnout.CLOSED, Turnout.THROWN}; 183 184 BeanSelectCreatePanel<Turnout> turnoutUnLitBox = new BeanSelectCreatePanel<>(InstanceManager.turnoutManagerInstance(), null); 185 JComboBox<String> turnoutUnLitState = new JComboBox<>(turnoutStates); 186 DecimalFormat paddedNumber = new DecimalFormat("0000"); 187 188 @ServiceProvider(service = SignalMastAddPane.SignalMastAddPaneProvider.class) 189 static public class SignalMastAddPaneProvider extends SignalMastAddPane.SignalMastAddPaneProvider { 190 /** {@inheritDoc} */ 191 @Override 192 @Nonnull public String getPaneName() { 193 return Bundle.getMessage("TurnCtlMast"); 194 } 195 /** {@inheritDoc} */ 196 @Override 197 @Nonnull public SignalMastAddPane getNewPane() { 198 return new TurnoutSignalMastAddPane(); 199 } 200 } 201 202 /** 203 * JPanel to define properties of an Aspect for a Turnout Signal Mast. 204 * <p> 205 * Invoked from the AddSignalMastPanel class when a Turnout Signal Mast is 206 * selected. 207 */ 208 class TurnoutAspectPanel { 209 210 BeanSelectCreatePanel<Turnout> beanBox = new BeanSelectCreatePanel<>(InstanceManager.turnoutManagerInstance(), null); 211 JCheckBox disabledCheck = new JCheckBox(Bundle.getMessage("DisableAspect")); 212 JLabel turnoutStateLabel = new JLabel(Bundle.getMessage("SetState")); 213 JComboBox<String> turnoutState = new JComboBox<>(turnoutStates); 214 215 String aspect = ""; 216 217 TurnoutAspectPanel(String aspect) { 218 this.aspect = aspect; 219 } 220 221 TurnoutAspectPanel(String turnoutName, int state) { 222 if (turnoutName == null || turnoutName.isEmpty()) { 223 return; 224 } 225 beanBox.setDefaultNamedBean(InstanceManager.turnoutManagerInstance().getTurnout(turnoutName)); 226 } 227 228 /** 229 * Store the mast name as comment in the turnout. 230 * 231 * @param reference Text to use as comment 232 */ 233 void setReference(String reference) { 234 beanBox.setReference(reference); 235 } 236 237 int getTurnoutState() { 238 return turnoutStateValues[turnoutState.getSelectedIndex()]; 239 } 240 241 void setSelectedTurnout(String name) { 242 if (name == null || name.isEmpty()) { 243 return; 244 } 245 beanBox.setDefaultNamedBean(InstanceManager.turnoutManagerInstance().getTurnout(name)); 246 } 247 248 void setTurnoutState(int state) { 249 if (state == Turnout.CLOSED) { 250 turnoutState.setSelectedItem(stateClosed); 251 } else { 252 turnoutState.setSelectedItem(stateThrown); 253 } 254 } 255 256 void setAspectDisabled(boolean boo) { 257 disabledCheck.setSelected(boo); 258 if (boo) { 259 beanBox.setEnabled(false); 260 turnoutStateLabel.setEnabled(false); 261 turnoutState.setEnabled(false); 262 } else { 263 beanBox.setEnabled(true); 264 turnoutStateLabel.setEnabled(true); 265 turnoutState.setEnabled(true); 266 } 267 } 268 269 boolean isAspectDisabled() { 270 return disabledCheck.isSelected(); 271 } 272 273 String getTurnoutName() { 274 return beanBox.getDisplayName(); 275 } 276 277 NamedBean getTurnout() { 278 try { 279 return beanBox.getNamedBean(); 280 } catch (jmri.JmriException ex) { 281 log.warn("skipping creation of turnout"); 282 return null; 283 } 284 } 285 286 JPanel panel; 287 288 JPanel getPanel() { 289 if (panel == null) { 290 panel = new JPanel(); 291 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 292 JPanel turnDetails = new JPanel(); 293 turnDetails.add(beanBox); 294 turnDetails.add(turnoutStateLabel); 295 turnDetails.add(turnoutState); 296 panel.add(turnDetails); 297 panel.add(disabledCheck); 298 TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black)); 299 border.setTitle(aspect); 300 panel.setBorder(border); 301 302 disabledCheck.addActionListener((ActionEvent e) -> { 303 setAspectDisabled(disabledCheck.isSelected()); 304 }); 305 306 } 307 return panel; 308 } 309 310 } 311 312 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TurnoutSignalMastAddPane.class); 313 314}