001package jmri.jmrit.display.palette; 002 003import java.awt.event.FocusAdapter; 004import java.awt.event.FocusEvent; 005import java.util.ArrayList; 006 007import javax.swing.BorderFactory; 008import javax.swing.Box; 009import javax.swing.BoxLayout; 010import javax.swing.JButton; 011import javax.swing.JCheckBox; 012import javax.swing.JFrame; 013import javax.swing.JLabel; 014import javax.swing.JPanel; 015import javax.swing.JTextField; 016 017import jmri.InstanceManager; 018import jmri.Sensor; 019import jmri.jmrit.logix.OBlock; 020import jmri.jmrit.logix.OPath; 021import jmri.jmrit.picker.PickListModel; 022import jmri.jmrit.picker.PickPanel; 023import jmri.util.swing.JmriJOptionPane; 024 025/** 026 * Panel for Occupancy and Error detection. 027 */ 028public class DetectionPanel extends JPanel { 029 030 private final JTextField _occDetectorName = new JTextField(); // can be either a Sensor or OBlock name 031 private JFrame _pickFrame; 032 private final JButton _openPicklistButton; 033 private final JPanel _trainIdPanel; 034 private JCheckBox _showTrainName; 035 private OBlock _block; 036 private final JPanel _blockPathPanel; 037 private final JPanel _sensorBlurbPanel; 038 private final ItemPanel _parent; 039 private ArrayList<JCheckBox> _pathBoxes; 040 private JPanel _checkBoxPanel; 041 042 /** 043 * Add _blockPathPanel to this ItemPanel. 044 * @param parent the indicator track item panel 045 */ 046 public DetectionPanel(ItemPanel parent) { 047 super(); 048 _parent = parent; 049 _occDetectorName.addActionListener(e -> checkDetection()); 050 _occDetectorName.addFocusListener(new FocusAdapter() { 051 @Override 052 public void focusLost(FocusEvent e) { 053 checkDetection(); 054 } 055 }); 056 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 057 JPanel panel = new JPanel(); 058 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 059 panel.add(makeSensorPanel(_occDetectorName, "OccupancySensor", "ToolTipOccupancySensor")); 060 _openPicklistButton = new JButton(Bundle.getMessage("OpenPicklist")); 061 _openPicklistButton.addActionListener(a -> { 062 if (_pickFrame == null) { 063 openPickList(); 064 } else { 065 closePickList(); 066 } 067 }); 068 JPanel p = new JPanel(); 069 p.add(_openPicklistButton); 070 panel.add(p); 071 add(panel); 072 073 _trainIdPanel = makeTrainIdPanel(); 074 add(_trainIdPanel); 075 076 _blockPathPanel = new JPanel(); 077 _blockPathPanel.setLayout(new BoxLayout(_blockPathPanel, BoxLayout.Y_AXIS)); 078 p = new JPanel(); 079 p.add(new JLabel(Bundle.getMessage("SelectPathIcons"))); 080 _blockPathPanel.add(p); 081 _checkBoxPanel = new JPanel(); 082 _blockPathPanel.add(_checkBoxPanel); 083 _blockPathPanel.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 084 _blockPathPanel.setToolTipText(Bundle.getMessage("ToolTipSelectPathIcons")); 085 add(_blockPathPanel); 086 087 _sensorBlurbPanel = new JPanel(); 088 JPanel blurb = new JPanel(); 089 blurb.setLayout(new BoxLayout(blurb, BoxLayout.Y_AXIS)); 090 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 091 blurb.add(new JLabel(Bundle.getMessage("DetectorNote"))); 092 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 093 _sensorBlurbPanel.add(blurb); 094 add(_sensorBlurbPanel); 095 } 096 097 JPanel makeSensorPanel(JTextField field, String text, String toolTip) { 098 JPanel panel = new JPanel(); 099 JLabel label = new JLabel(Bundle.getMessage(text)); 100 panel.add(label); 101 java.awt.Dimension dim = field.getPreferredSize(); 102 dim.width = 500; 103 field.setMaximumSize(dim); 104 dim.width = 200; 105 field.setMinimumSize(dim); 106 field.setColumns(20); 107 field.setDragEnabled(true); 108 field.setTransferHandler(new jmri.util.DnDStringImportHandler()); 109 label.setToolTipText(Bundle.getMessage(toolTip)); 110 field.setToolTipText(Bundle.getMessage(toolTip)); 111 panel.setToolTipText(Bundle.getMessage(toolTip)); 112 panel.add(field); 113 return panel; 114 } 115 116// @SuppressWarnings("raw") 117 void openPickList() { 118 _pickFrame = new JFrame(); 119 JPanel content = new JPanel(); 120 content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); 121 122 JPanel blurb = new JPanel(); 123 blurb.setLayout(new BoxLayout(blurb, BoxLayout.Y_AXIS)); 124 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 125 blurb.add(new JLabel(Bundle.getMessage("DragOccupancyName", Bundle.getMessage("OccupancySensor")))); 126 blurb.add(new JLabel(Bundle.getMessage("DetectorNote"))); 127// blurb.add(new JLabel(Bundle.getMessage("DragErrorName", Bundle.getMessage("ErrorSensor")))); 128 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 129 JPanel panel = new JPanel(); 130 panel.add(blurb); 131 content.add(panel); 132 PickListModel<?>[] models = {PickListModel.oBlockPickModelInstance(), 133 PickListModel.sensorPickModelInstance() 134 }; 135 content.add(new PickPanel(models)); 136 137 _pickFrame.setContentPane(content); 138 _pickFrame.addWindowListener(new java.awt.event.WindowAdapter() { 139 @Override 140 public void windowClosing(java.awt.event.WindowEvent e) { 141 closePickList(); 142 } 143 }); 144 _pickFrame.setLocationRelativeTo(this); 145 _pickFrame.toFront(); 146 _pickFrame.setVisible(true); 147 _pickFrame.pack(); 148 _openPicklistButton.setText(Bundle.getMessage("ClosePicklist")); 149 } 150 151 void closePickList() { 152 _pickFrame.dispose(); 153 _pickFrame = null; 154 _openPicklistButton.setText(Bundle.getMessage("OpenPicklist")); 155 } 156 157 private JPanel makeTrainIdPanel() { 158 JPanel panel = new JPanel(); 159 _showTrainName = new JCheckBox(Bundle.getMessage("ShowTrainName")); 160 _showTrainName.setToolTipText(Bundle.getMessage("ToolTipShowTrainName")); 161 JPanel p = new JPanel(); 162 p.add(_showTrainName); 163 p.setToolTipText(Bundle.getMessage("ToolTipShowTrainName")); 164 panel.add(p); 165 return panel; 166 } 167 168 public void dispose() { 169 if (_pickFrame != null) { 170 _pickFrame.dispose(); 171 _pickFrame = null; 172 } 173 } 174 175 /* 176 * **************** Getters & Setters ************************** 177 */ 178 public boolean getShowTrainName() { 179 return _showTrainName.isSelected(); 180 } 181 182 public void setShowTrainName(boolean show) { 183 _showTrainName.setSelected(show); 184 } 185 186 public String getOccSensor() { 187 String name = _occDetectorName.getText(); 188 if (name != null && name.trim().length() > 0) { 189 if (InstanceManager.sensorManagerInstance().getSensor(name) != null) { 190 return name; 191 } 192 } 193 return null; 194 } 195 196 public String getOccBlock() { 197 String name = _occDetectorName.getText(); 198 if (name != null && name.trim().length() > 0) { 199 if (InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).getOBlock(name) != null) { 200 return name; 201 } 202 } 203 return null; 204 } 205 206 /** 207 * Name of either Sensor or OBlock for detection 208 * @param name detector name 209 */ 210 public void setOccDetector(String name) { 211 _occDetectorName.setText(name); 212 checkDetection(); 213 } 214 215 public ArrayList<String> getPaths() { 216 ArrayList<String> paths = new ArrayList<>(); 217 if (_pathBoxes != null) { 218 for (JCheckBox pathBox : _pathBoxes) { 219 if (pathBox.isSelected()) { 220 // displayed path names are padded to 25 charts 221 paths.add(pathBox.getName().trim()); 222 } 223 } 224 } 225 return paths; 226 } 227 228 public void setPaths(ArrayList<String> iconPath) { 229 if (iconPath == null || _block == null) { 230 _pathBoxes = null; 231 return; 232 } 233 for (String s : iconPath) { 234 for (JCheckBox pathBox : _pathBoxes) { 235 // displayed path names are padded to 25 chars 236 String name = pathBox.getName().trim(); 237 if (s.equals(name)) { 238 pathBox.setSelected(true); 239 } 240 } 241 } 242 } 243 244 /* 245 * ****************************************** 246 */ 247 private void checkDetection() { 248 String name = _occDetectorName.getText(); 249 if (name != null && name.trim().length() > 0) { 250 OBlock block = InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).getOBlock(name); 251 if (block != null) { 252 if (block.equals(_block)) { 253 return; 254 } 255 makePathList(block); 256 showPanels(true); 257 } else { 258 Sensor sensor = InstanceManager.sensorManagerInstance().getSensor(name); 259 if (sensor == null) { 260 JmriJOptionPane.showMessageDialog(_parent._frame, 261 Bundle.getMessage("InvalidOccDetector", name), 262 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 263 _occDetectorName.setText(null); 264 } 265 showPanels(false); 266 } 267 } else { 268 showPanels(false); 269 } 270 } 271 272 private void showPanels(boolean hasOBlock) { 273 _trainIdPanel.setVisible(hasOBlock); 274 _blockPathPanel.setVisible(hasOBlock); 275 _sensorBlurbPanel.setVisible(!hasOBlock); 276 if (!hasOBlock) { 277 _block = null; 278 } 279 invalidate(); 280 _parent.hideIcons(); // resizes panel properly 281 } 282 283 private void makePathList(OBlock block) { 284 _blockPathPanel.remove(_checkBoxPanel); 285 _checkBoxPanel = new JPanel(); 286 _checkBoxPanel.setLayout(new BoxLayout(_checkBoxPanel, BoxLayout.Y_AXIS)); 287 _checkBoxPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(java.awt.Color.black), 288 Bundle.getMessage("circuitPaths"))); 289 _checkBoxPanel.add(Box.createHorizontalStrut(100)); 290 _block = block; 291 _pathBoxes = new ArrayList<>(); 292 _block.getPaths().stream().filter(o -> o instanceof OPath) 293 .map(o -> ((OPath) o).getName()).forEach( name -> { 294 if (name.length() < 25) { 295 char[] ca = new char[25]; 296 for (int j = 0; j < name.length(); j++) { 297 ca[j] = name.charAt(j); 298 } 299 for (int j = name.length(); j < 25; j++) { 300 ca[j] = ' '; 301 } 302 name = new String(ca); 303 } 304 JCheckBox box = new JCheckBox(name); 305 box.setName(name); 306 _pathBoxes.add(box); 307 _checkBoxPanel.add(box); 308 }); 309 _blockPathPanel.add(_checkBoxPanel, 1); 310 } 311 312}