001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003    /* Open Source Software - may be modified and shared by FRC teams. The code   */
004    /* must be accompanied by the FIRST BSD license file in the root directory of */
005    /* the project.                                                               */
006    /*----------------------------------------------------------------------------*/
007    package edu.wpi.first.wpilibj.smartdashboard;
008    
009    import edu.wpi.first.wpilibj.Sendable;
010    import edu.wpi.first.wpilibj.command.Command;
011    import edu.wpi.first.wpilibj.networktables2.type.StringArray;
012    import edu.wpi.first.wpilibj.networktables2.util.List;
013    import edu.wpi.first.wpilibj.tables.ITable;
014    
015    /**
016     * The {@link SendableChooser} class is a useful tool for presenting a selection
017     * of options to the {@link SmartDashboard}.
018     *
019     * <p>For instance, you may wish to be able to select between multiple
020     * autonomous modes. You can do this by putting every possible {@link Command}
021     * you want to run as an autonomous into a {@link SendableChooser} and then put
022     * it into the {@link SmartDashboard} to have a list of options appear on the
023     * laptop. Once autonomous starts, simply ask the {@link SendableChooser} what
024     * the selected value is.</p>
025     *
026     * @author Joe Grinstead
027     */
028    public class SendableChooser implements Sendable {
029    
030        /**
031         * The key for the default value
032         */
033        private static final String DEFAULT = "default";
034        /**
035         * The key for the selected option
036         */
037        private static final String SELECTED = "selected";
038        /**
039         * The key for the option array
040         */
041        private static final String OPTIONS = "options";
042        /**
043         * A table linking strings to the objects the represent
044         */
045        private StringArray choices = new StringArray();
046        private List values = new List();
047        private String defaultChoice = null;
048        private Object defaultValue = null;
049    
050        /**
051         * Instantiates a {@link SendableChooser}.
052         */
053        public SendableChooser() {
054        }
055    
056        /**
057         * Adds the given object to the list of options. On the
058         * {@link SmartDashboard} on the desktop, the object will appear as the
059         * given name.
060         *
061         * @param name the name of the option
062         * @param object the option
063         */
064        public void addObject(String name, Object object) {
065            //if we don't have a default, set the default automatically
066            if (defaultChoice == null) {
067                addDefault(name, object);
068                return;
069            }
070            for (int i = 0; i < choices.size(); ++i) {
071                if (choices.get(i).equals(name)) {
072                    choices.set(i, name);
073                    values.set(i, object);
074                    return;
075                }
076            }
077            //not found
078            choices.add(name);
079            values.add(object);
080            if (table != null) {
081                table.putValue(OPTIONS, choices);
082            }
083        }
084    
085        /**
086         * Add the given object to the list of options and marks it as the default.
087         * Functionally, this is very close to
088         * {@link SendableChooser#addObject(java.lang.String, java.lang.Object) addObject(...)}
089         * except that it will use this as the default option if none other is
090         * explicitly selected.
091         *
092         * @param name the name of the option
093         * @param object the option
094         */
095        public void addDefault(String name, Object object) {
096            if (name == null) {
097                throw new NullPointerException("Name cannot be null");
098            }
099            defaultChoice = name;
100            defaultValue = object;
101            if (table != null) {
102                table.putString(DEFAULT, defaultChoice);
103            }
104            addObject(name, object);
105        }
106    
107        /**
108         * Returns the selected option. If there is none selected, it will return
109         * the default. If there is none selected and no default, then it will
110         * return {@code null}.
111         *
112         * @return the option selected
113         */
114        public Object getSelected() {
115            String selected = table.getString(SELECTED, null);
116            for (int i = 0; i < values.size(); ++i) {
117                if (choices.get(i).equals(selected)) {
118                    return values.get(i);
119                }
120            }
121            return defaultValue;
122    
123        }
124    
125        public String getSmartDashboardType() {
126            return "String Chooser";
127        }
128        private ITable table;
129    
130        public void initTable(ITable table) {
131            this.table = table;
132            if (table != null) {
133                table.putValue(OPTIONS, choices);
134                if (defaultChoice != null) {
135                    table.putString(DEFAULT, defaultChoice);
136                }
137            }
138        }
139    
140        /**
141         * {@inheritDoc}
142         */
143        public ITable getTable() {
144            return table;
145        }
146    }