001package jmri.jmrix.jinput.treecontrol; 002 003import java.awt.BorderLayout; 004import java.awt.event.ActionEvent; 005import java.awt.event.ActionListener; 006import java.beans.PropertyChangeEvent; 007import java.beans.PropertyChangeListener; 008import javax.swing.Box; 009import javax.swing.BoxLayout; 010import javax.swing.JCheckBox; 011import javax.swing.JLabel; 012import javax.swing.JPanel; 013import javax.swing.JScrollPane; 014import javax.swing.JSeparator; 015import javax.swing.JTextField; 016import javax.swing.JTree; 017import javax.swing.event.TreeSelectionEvent; 018import javax.swing.event.TreeSelectionListener; 019import javax.swing.tree.DefaultTreeSelectionModel; 020import javax.swing.tree.TreePath; 021import jmri.jmrix.jinput.TreeModel; 022import jmri.jmrix.jinput.UsbNode; 023import net.java.games.input.Component; 024import net.java.games.input.Controller; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028/** 029 * Create a JPanel containing a tree of JInput sources. 030 * 031 * @author Bob Jacobsen Copyright 2008 032 */ 033public class TreePanel extends JPanel { 034 035 public TreePanel() { 036 037 super(true); 038 039 // create basic GUI 040 dTree = new JTree(TreeModel.instance()); 041 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 042 043 // build the main GUI 044 JScrollPane treePanel = new JScrollPane(dTree); 045 JPanel nodePanel = new JPanel(); 046 add(new javax.swing.JSplitPane(javax.swing.JSplitPane.HORIZONTAL_SPLIT, treePanel, nodePanel)); 047 048 // configure the tree 049 dTree.setRootVisible(false); 050 dTree.setShowsRootHandles(true); 051 dTree.setScrollsOnExpand(true); 052 dTree.setExpandsSelectedPaths(true); 053 054 dTree.getSelectionModel().setSelectionMode(DefaultTreeSelectionModel.SINGLE_TREE_SELECTION); 055 056 dTree.addTreeSelectionListener(new TreeSelectionListener() { 057 @Override 058 public void valueChanged(TreeSelectionEvent e) { 059 if (!dTree.isSelectionEmpty() && dTree.getSelectionPath() != null) { 060 // node has been selected 061 currentNode = getSelectedElement(); 062 update(); 063 } else { 064 currentNode = null; 065 // no node selected, clear 066 sensorBox.setSelected(false); 067 memoryBox.setSelected(false); 068 sensorName.setText(""); 069 memoryName.setText(""); 070 } 071 } 072 }); 073 074 // configure the view pane 075 JPanel p2 = new JPanel(); 076 nodePanel.setLayout(new BorderLayout()); 077 nodePanel.add(p2, BorderLayout.NORTH); 078 079 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS)); 080 081 JPanel p = new JPanel(); 082 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 083 p.add(new JLabel(Bundle.getMessage("USBController") + ": ")); 084 p.add(controllerName); 085 p.add(Box.createHorizontalGlue()); 086 p2.add(p); 087 p = new JPanel(); 088 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 089 p.add(new JLabel(Bundle.getMessage("USBType") + ": ")); 090 p.add(controllerType); 091 p.add(Box.createHorizontalGlue()); 092 p2.add(p); 093 094 p2.add(new JSeparator(JSeparator.HORIZONTAL), BorderLayout.NORTH); 095 096 p = new JPanel(); 097 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 098 p.add(new JLabel(Bundle.getMessage("USBComponent") + ": ")); 099 p.add(componentName); 100 p.add(Box.createHorizontalGlue()); 101 p2.add(p); 102 103 p = new JPanel(); 104 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 105 p.add(new JLabel(Bundle.getMessage("USBIdentifier") + ": ")); 106 p.add(componentId); 107 p.add(Box.createHorizontalGlue()); 108 p2.add(p); 109 110 p2.add(new JSeparator(JSeparator.HORIZONTAL), BorderLayout.NORTH); 111 112 p = new JPanel(); 113 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 114 p.add(new JLabel(Bundle.getMessage("USBAnalog") + ": ")); 115 p.add(componentAnalog); 116 p.add(new JLabel(" " + Bundle.getMessage("USBRelative") + ": ")); 117 p.add(componentRelative); 118 p.add(Box.createHorizontalGlue()); 119 p2.add(p); 120 121 p2.add(new JSeparator(JSeparator.HORIZONTAL), BorderLayout.NORTH); 122 123 p = new JPanel(); 124 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 125 p.add(new JLabel(Bundle.getMessage("USBValue") + ": ")); 126 p.add(componentValue); 127 p.add(Box.createHorizontalGlue()); 128 p2.add(p); 129 130 p2.add(new JSeparator(JSeparator.HORIZONTAL)); 131 132 p = new JPanel(); 133 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 134 p.add(sensorBox); 135 p.add(new JLabel(Bundle.getMessage("USBName") + ": ")); 136 p.add(sensorName); 137 p.add(Box.createHorizontalGlue()); 138 p2.add(p); 139 140 p = new JPanel(); 141 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); 142 p.add(memoryBox); 143 p.add(new JLabel(Bundle.getMessage("USBName") + ": ")); 144 p.add(memoryName); 145 p.add(Box.createHorizontalGlue()); 146 p2.add(p); 147 148 // attach controls 149 sensorBox.addActionListener(new ActionListener() { 150 @Override 151 public void actionPerformed(ActionEvent e) { 152 checkSensorBox(); 153 } 154 }); 155 memoryBox.addActionListener(new ActionListener() { 156 @Override 157 public void actionPerformed(ActionEvent e) { 158 checkMemoryBox(); 159 } 160 }); 161 162 // initial states 163 sensorBox.setSelected(false); 164 memoryBox.setSelected(false); 165 sensorName.setEditable(true); 166 memoryName.setEditable(true); 167 168 // starting listening for changes 169 TreeModel.instance().addPropertyChangeListener( 170 new PropertyChangeListener() { 171 @Override 172 public void propertyChange(PropertyChangeEvent e) { 173 if ((currentNode != null) && (e.getOldValue() == currentNode)) { 174 // right place, update 175 float value = ((Float) e.getNewValue()).floatValue(); 176 if (currentNode.getComponent().isAnalog()) { 177 componentValue.setText("" + value); 178 } else { 179 componentValue.setText((value > 0.0) ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo")); 180 } 181 } 182 } 183 }); 184 } 185 186 void checkSensorBox() { 187 if (currentNode == null) { 188 return; 189 } 190 if (sensorBox.isSelected()) { 191 // checked box, if anything there, set the node 192 currentNode.setAttachedSensor(sensorName.getText()); 193 sensorName.setEditable(false); 194 } else { 195 // unchecked box, reset the node 196 currentNode.setAttachedSensor(""); 197 sensorName.setEditable(true); 198 } 199 200 } 201 202 void checkMemoryBox() { 203 if (currentNode == null) { 204 return; 205 } 206 if (memoryBox.isSelected()) { 207 // checked box, if anything there, set the node 208 currentNode.setAttachedMemory(memoryName.getText()); 209 memoryName.setEditable(false); 210 } else { 211 // unchecked box, reset the node 212 currentNode.setAttachedMemory(""); 213 memoryName.setEditable(true); 214 } 215 } 216 217 UsbNode currentNode = null; 218 219 void update() { 220 Controller controller = currentNode.getController(); 221 if (controller != null) { 222 controllerName.setText(controller.getName()); 223 controllerType.setText(controller.getType().toString()); 224 } else { 225 controllerName.setText(""); 226 controllerType.setText(""); 227 } 228 Component component = currentNode.getComponent(); 229 if (component != null) { 230 componentName.setText(component.getName()); 231 componentId.setText(component.getIdentifier().toString()); 232 if (component.isAnalog()) { 233 componentAnalog.setText(Bundle.getMessage("ButtonYes")); 234 componentValue.setText("" + currentNode.getValue()); 235 componentRelative.setText(component.isRelative() ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo")); 236 } else { 237 componentAnalog.setText(Bundle.getMessage("ButtonNo")); 238 componentRelative.setText(""); 239 componentValue.setText((currentNode.getValue() > 0.0) ? Bundle.getMessage("ButtonYes") : Bundle.getMessage("ButtonNo")); 240 } 241 242 String attachedSensor = currentNode.getAttachedSensor(); 243 if ((attachedSensor != null) && !attachedSensor.isEmpty()) { 244 sensorName.setText(attachedSensor); 245 sensorName.setEditable(false); 246 sensorBox.setSelected(true); 247 } else { 248 sensorName.setText(""); 249 sensorName.setEditable(true); 250 sensorBox.setSelected(false); 251 } 252 253 String attachedMemory = currentNode.getAttachedMemory(); 254 if ((attachedMemory != null) && (!attachedMemory.equals(""))) { 255 memoryName.setText(attachedMemory); 256 memoryName.setEditable(false); 257 memoryBox.setSelected(true); 258 } else { 259 memoryName.setText(""); 260 memoryName.setEditable(true); 261 memoryBox.setSelected(false); 262 } 263 } else { 264 componentName.setText(""); 265 componentId.setText(""); 266 componentAnalog.setText(Bundle.getMessage("ButtonNo")); 267 componentRelative.setText(Bundle.getMessage("ButtonNo")); 268 componentValue.setText(""); 269 sensorName.setText(""); 270 sensorName.setEditable(true); 271 sensorBox.setSelected(false); 272 memoryName.setText(""); 273 memoryName.setEditable(true); 274 memoryBox.setSelected(false); 275 } 276 } 277 278 JLabel controllerName = new JLabel(); 279 JLabel controllerType = new JLabel(); 280 JLabel componentName = new JLabel(); 281 JLabel componentId = new JLabel(); 282 JLabel componentAnalog = new JLabel(); 283 JLabel componentRelative = new JLabel(); 284 JLabel componentValue = new JLabel(); 285 JCheckBox sensorBox = new JCheckBox(Bundle.getMessage("USBCopyJMRISensor") + " "); 286 JTextField sensorName = new JTextField(25); 287 JCheckBox memoryBox = new JCheckBox(Bundle.getMessage("USBCopyJMRIMemory") + " "); 288 JTextField memoryName = new JTextField(25); 289 290 public UsbNode getSelectedElement() { 291 if (!dTree.isSelectionEmpty() && dTree.getSelectionPath() != null) { 292 // somebody has been selected 293 log.debug("getSelectedIcon with {}", dTree.getSelectionPath().toString()); 294 TreePath path = dTree.getSelectionPath(); 295 296 int level = path.getPathCount(); 297 // specific items are at level 3, no action above that 298 299 return (UsbNode) path.getPathComponent(level - 1); 300 } else { 301 return null; 302 } 303 } 304 305 JTree dTree; 306 307 private final static Logger log = LoggerFactory.getLogger(TreePanel.class); 308}