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}