From 5aa5e3e09e4d463d7bad73f66bd39517577f5ff1 Mon Sep 17 00:00:00 2001 From: Austin Shalit Date: Tue, 3 Jan 2017 14:40:31 -0800 Subject: [PATCH] SendableChooser generic value (#433) * Java SendableChooser now decorates with type (non-breaking change) * C++ SendableChooser now is templated on the type instead of using void* and stores values (breaking change) * C++ SendableChooser now uses llvm::StringMap instead of std::map --- .../include/SmartDashboard/SendableChooser.h | 23 +++++----- .../SmartDashboard/SendableChooser.inc} | 44 +++++++++++-------- .../SmartDashboard/SendableChooserBase.h | 40 +++++++++++++++++ .../SmartDashboard/SendableChooserBase.cpp | 22 ++++++++++ .../smartdashboard/SendableChooser.java | 12 ++--- 5 files changed, 106 insertions(+), 35 deletions(-) rename wpilibc/shared/{src/SmartDashboard/SendableChooser.cpp => include/SmartDashboard/SendableChooser.inc} (68%) create mode 100644 wpilibc/shared/include/SmartDashboard/SendableChooserBase.h create mode 100644 wpilibc/shared/src/SmartDashboard/SendableChooserBase.cpp diff --git a/wpilibc/shared/include/SmartDashboard/SendableChooser.h b/wpilibc/shared/include/SmartDashboard/SendableChooser.h index a372098f62..5dbee54aee 100644 --- a/wpilibc/shared/include/SmartDashboard/SendableChooser.h +++ b/wpilibc/shared/include/SmartDashboard/SendableChooser.h @@ -7,11 +7,12 @@ #pragma once -#include #include #include -#include "SmartDashboard/Sendable.h" +#include "SmartDashboard/SendableChooserBase.h" +#include "llvm/StringMap.h" +#include "llvm/StringRef.h" #include "tables/ITable.h" namespace frc { @@ -27,24 +28,24 @@ namespace frc { * laptop. Once autonomous starts, simply ask the {@link SendableChooser} what * the selected value is.

* + * @tparam T The type of values to be stored * @see SmartDashboard */ -class SendableChooser : public Sendable { +template +class SendableChooser : public SendableChooserBase { public: virtual ~SendableChooser() = default; - void AddObject(const std::string& name, void* object); - void AddDefault(const std::string& name, void* object); - void* GetSelected(); + void AddObject(llvm::StringRef name, const T& object); + void AddDefault(llvm::StringRef name, const T& object); + T GetSelected(); void InitTable(std::shared_ptr subtable) override; - std::shared_ptr GetTable() const override; - std::string GetSmartDashboardType() const override; private: - std::string m_defaultChoice; - std::map m_choices; - std::shared_ptr m_table; + llvm::StringMap m_choices; }; } // namespace frc + +#include "SendableChooser.inc" diff --git a/wpilibc/shared/src/SmartDashboard/SendableChooser.cpp b/wpilibc/shared/include/SmartDashboard/SendableChooser.inc similarity index 68% rename from wpilibc/shared/src/SmartDashboard/SendableChooser.cpp rename to wpilibc/shared/include/SmartDashboard/SendableChooser.inc index 177ea126a9..ba9363f1e8 100644 --- a/wpilibc/shared/src/SmartDashboard/SendableChooser.cpp +++ b/wpilibc/shared/include/SmartDashboard/SendableChooser.inc @@ -5,13 +5,15 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -#include "SmartDashboard/SendableChooser.h" +#pragma once -using namespace frc; +#include +#include +#include +#include +#include -static const std::string kDefault = "default"; -static const std::string kOptions = "options"; -static const std::string kSelected = "selected"; +namespace frc { /** * Adds the given object to the list of options. @@ -22,7 +24,8 @@ static const std::string kSelected = "selected"; * @param name the name of the option * @param object the option */ -void SendableChooser::AddObject(const std::string& name, void* object) { +template +void SendableChooser::AddObject(llvm::StringRef name, const T& object) { m_choices[name] = object; } @@ -36,7 +39,8 @@ void SendableChooser::AddObject(const std::string& name, void* object) { * @param name the name of the option * @param object the option */ -void SendableChooser::AddDefault(const std::string& name, void* object) { +template +void SendableChooser::AddDefault(llvm::StringRef name, const T& object) { m_defaultChoice = name; AddObject(name, object); } @@ -49,29 +53,31 @@ void SendableChooser::AddDefault(const std::string& name, void* object) { * * @return the option selected */ -void* SendableChooser::GetSelected() { +template +T SendableChooser::GetSelected() { std::string selected = m_table->GetString(kSelected, m_defaultChoice); - if (selected == "") + if (selected == "") { return nullptr; - else + } else { return m_choices[selected]; + } } -void SendableChooser::InitTable(std::shared_ptr subtable) { +template +void SendableChooser::InitTable(std::shared_ptr subtable) { std::vector keys; m_table = subtable; if (m_table != nullptr) { - std::map::iterator iter; - for (iter = m_choices.begin(); iter != m_choices.end(); iter++) { - keys.push_back(iter->first); + for (const auto& choice : m_choices) { + keys.push_back(choice.first()); } + + // Unlike std::map, llvm::StringMap elements are not sorted + std::sort(keys.begin(), keys.end()); + m_table->PutValue(kOptions, nt::Value::MakeStringArray(std::move(keys))); m_table->PutString(kDefault, m_defaultChoice); } } -std::shared_ptr SendableChooser::GetTable() const { return m_table; } - -std::string SendableChooser::GetSmartDashboardType() const { - return "String Chooser"; -} +} // namespace frc diff --git a/wpilibc/shared/include/SmartDashboard/SendableChooserBase.h b/wpilibc/shared/include/SmartDashboard/SendableChooserBase.h new file mode 100644 index 0000000000..04102eec80 --- /dev/null +++ b/wpilibc/shared/include/SmartDashboard/SendableChooserBase.h @@ -0,0 +1,40 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2017. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include "SmartDashboard/Sendable.h" +#include "tables/ITable.h" + +namespace frc { + +/** + * This class is a non-template base class for {@link SendableChooser}. + * + * It contains static, non-templated variables to avoid their duplication in the + * template class. + */ +class SendableChooserBase : public Sendable { + public: + virtual ~SendableChooserBase() = default; + + std::shared_ptr GetTable() const override; + std::string GetSmartDashboardType() const override; + + protected: + static const char* kDefault; + static const char* kOptions; + static const char* kSelected; + + std::string m_defaultChoice; + std::shared_ptr m_table; +}; + +} // namespace frc diff --git a/wpilibc/shared/src/SmartDashboard/SendableChooserBase.cpp b/wpilibc/shared/src/SmartDashboard/SendableChooserBase.cpp new file mode 100644 index 0000000000..9552e9b14c --- /dev/null +++ b/wpilibc/shared/src/SmartDashboard/SendableChooserBase.cpp @@ -0,0 +1,22 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2017. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "SmartDashboard/SendableChooserBase.h" + +using namespace frc; + +const char* SendableChooserBase::kDefault = "default"; +const char* SendableChooserBase::kOptions = "options"; +const char* SendableChooserBase::kSelected = "selected"; + +std::shared_ptr SendableChooserBase::GetTable() const { + return m_table; +} + +std::string SendableChooserBase::GetSmartDashboardType() const { + return "String Chooser"; +} diff --git a/wpilibj/src/shared/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooser.java b/wpilibj/src/shared/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooser.java index 62e4f6de42..3c3262518d 100644 --- a/wpilibj/src/shared/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooser.java +++ b/wpilibj/src/shared/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooser.java @@ -22,8 +22,10 @@ import edu.wpi.first.wpilibj.tables.ITable; * SendableChooser} and then put it into the {@link SmartDashboard} to have a list of options appear * on the laptop. Once autonomous starts, simply ask the {@link SendableChooser} what the selected * value is. + * + * @param The type of the values to be stored */ -public class SendableChooser implements Sendable { +public class SendableChooser implements Sendable { /** * The key for the default value. @@ -40,7 +42,7 @@ public class SendableChooser implements Sendable { /** * A map linking strings to the objects the represent. */ - private final HashMap m_map = new HashMap<>(); + private final HashMap m_map = new HashMap<>(); private String m_defaultChoice = null; /** @@ -56,7 +58,7 @@ public class SendableChooser implements Sendable { * @param name the name of the option * @param object the option */ - public void addObject(String name, Object object) { + public void addObject(String name, V object) { // if we don't have a default, set the default automatically if (m_defaultChoice == null) { addDefault(name, object); @@ -78,7 +80,7 @@ public class SendableChooser implements Sendable { * @param name the name of the option * @param object the option */ - public void addDefault(String name, Object object) { + public void addDefault(String name, V object) { if (name == null) { throw new NullPointerException("Name cannot be null"); } @@ -95,7 +97,7 @@ public class SendableChooser implements Sendable { * * @return the option selected */ - public Object getSelected() { + public V getSelected() { String selected = m_table.getString(SELECTED, null); return m_map.getOrDefault(selected, m_map.get(m_defaultChoice)); }