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}