001/*----------------------------------------------------------------------------*/
002/* Copyright (c) FIRST 2008-2017. 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
008package edu.wpi.first.wpilibj.smartdashboard;
009
010import java.util.HashMap;
011
012import edu.wpi.first.wpilibj.Sendable;
013import edu.wpi.first.wpilibj.command.Command;
014import edu.wpi.first.wpilibj.tables.ITable;
015
016/**
017 * The {@link SendableChooser} class is a useful tool for presenting a selection of options to the
018 * {@link SmartDashboard}.
019 *
020 * <p>For instance, you may wish to be able to select between multiple autonomous modes. You can do
021 * this by putting every possible {@link Command} you want to run as an autonomous into a {@link
022 * SendableChooser} and then put it into the {@link SmartDashboard} to have a list of options appear
023 * on the laptop. Once autonomous starts, simply ask the {@link SendableChooser} what the selected
024 * value is.
025 *
026 * @param <V> The type of the values to be stored
027 */
028public class SendableChooser<V> 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 map linking strings to the objects the represent.
044   */
045  private final HashMap<String, V> m_map = new HashMap<>();
046  private String m_defaultChoice = null;
047
048  /**
049   * Instantiates a {@link SendableChooser}.
050   */
051  public SendableChooser() {
052  }
053
054  /**
055   * Adds the given object to the list of options. On the {@link SmartDashboard} on the desktop, the
056   * object will appear as the given name.
057   *
058   * @param name   the name of the option
059   * @param object the option
060   */
061  public void addObject(String name, V object) {
062    m_map.put(name, object);
063
064    if (m_table != null) {
065      m_table.putStringArray(OPTIONS, m_map.keySet().toArray(new String[0]));
066    }
067  }
068
069  /**
070   * Add the given object to the list of options and marks it as the default. Functionally, this is
071   * very close to {@link #addObject(String, Object)} except that it will use this as the default
072   * option if none other is explicitly selected.
073   *
074   * @param name   the name of the option
075   * @param object the option
076   */
077  public void addDefault(String name, V object) {
078    if (name == null) {
079      throw new NullPointerException("Name cannot be null");
080    }
081    m_defaultChoice = name;
082    if (m_table != null) {
083      m_table.putString(DEFAULT, m_defaultChoice);
084    }
085    addObject(name, object);
086  }
087
088  /**
089   * Returns the selected option. If there is none selected, it will return the default. If there is
090   * none selected and no default, then it will return {@code null}.
091   *
092   * @return the option selected
093   */
094  public V getSelected() {
095    String selected = m_table.getString(SELECTED, null);
096    return m_map.getOrDefault(selected, m_map.get(m_defaultChoice));
097  }
098
099  @Override
100  public String getSmartDashboardType() {
101    return "String Chooser";
102  }
103
104  private ITable m_table;
105
106  @Override
107  public void initTable(ITable table) {
108    m_table = table;
109    if (table != null) {
110      table.putStringArray(OPTIONS, m_map.keySet().toArray(new String[0]));
111      if (m_defaultChoice != null) {
112        table.putString(DEFAULT, m_defaultChoice);
113      }
114    }
115  }
116
117  @Override
118  public ITable getTable() {
119    return m_table;
120  }
121}