WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
SendableChooser.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <algorithm>
8#include <concepts>
9#include <functional>
10#include <memory>
11#include <string>
12#include <string_view>
13#include <utility>
14#include <vector>
15
19
20namespace wpi {
21
22/**
23 * The SendableChooser class is a useful tool for presenting a selection of
24 * options to the SmartDashboard.
25 *
26 * For instance, you may wish to be able to select between multiple autonomous
27 * modes. You can do this by putting every possible Command you want to run as
28 * an autonomous into a SendableChooser and then put it into the SmartDashboard
29 * to have a list of options appear on the laptop. Once autonomous starts,
30 * simply ask the SendableChooser what the selected value is.
31 *
32 * @tparam T The type of values to be stored
33 * @see SmartDashboard
34 */
35template <class T>
36 requires std::copy_constructible<T> && std::default_initializable<T>
39 std::function<void(T)> m_listener;
40 template <class U>
41 static U _unwrap_smart_ptr(const U& value) {
42 return value;
43 }
44
45 template <class U>
46 static std::weak_ptr<U> _unwrap_smart_ptr(const std::shared_ptr<U>& value) {
47 return value;
48 }
49
50 public:
51 using CopyType = decltype(_unwrap_smart_ptr(m_choices.find("")->second));
52
53 SendableChooser() = default;
54 ~SendableChooser() override = default;
57
58 /**
59 * Adds the given object to the list of options.
60 *
61 * On the SmartDashboard on the desktop, the object will appear as the given
62 * name.
63 *
64 * @param name the name of the option
65 * @param object the option
66 */
67 void AddOption(std::string_view name, T object) {
68 m_choices[name] = std::move(object);
69 }
70
71 /**
72 * Add the given object to the list of options and marks it as the default.
73 *
74 * Functionally, this is very close to AddOption() except that it will use
75 * this as the default option if none other is explicitly selected.
76 *
77 * @param name the name of the option
78 * @param object the option
79 */
80 void SetDefaultOption(std::string_view name, T object) {
82 AddOption(name, std::move(object));
83 }
84
85 /**
86 * Returns a copy of the selected option (a std::weak_ptr&lt;U&gt; if T =
87 * std::shared_ptr&lt;U&gt;).
88 *
89 * If there is none selected, it will return the default. If there is none
90 * selected and no default, then it will return a value-initialized instance.
91 * For integer types, this is 0. For container types like std::string, this is
92 * an empty string.
93 *
94 * @return The option selected
95 */
97 std::string selected = m_defaultChoice;
98 {
99 std::scoped_lock lock(m_mutex);
100 if (m_haveSelected) {
101 selected = m_selected;
102 }
103 }
104 if (selected.empty()) {
105 return CopyType{};
106 } else {
107 auto it = m_choices.find(selected);
108 if (it == m_choices.end()) {
109 return CopyType{};
110 }
111 return _unwrap_smart_ptr(it->second);
112 }
113 }
114
115 /**
116 * Bind a listener that's called when the selected value changes.
117 * Only one listener can be bound. Calling this function will replace the
118 * previous listener.
119 * @param listener The function to call that accepts the new value
120 */
121 void OnChange(std::function<void(T)> listener) {
122 std::scoped_lock lock(m_mutex);
123 m_listener = listener;
124 }
125
126 void InitSendable(wpi::util::SendableBuilder& builder) override {
127 builder.SetSmartDashboardType("String Chooser");
130 kOptions,
131 [=, this] {
132 std::vector<std::string> keys;
133 for (const auto& choice : m_choices) {
134 keys.emplace_back(choice.first);
135 }
136 return keys;
137 },
138 nullptr);
140 kDefault,
141 [=, this](wpi::util::SmallVectorImpl<char>&) -> std::string_view {
142 return m_defaultChoice;
143 },
144 nullptr);
146 kActive,
147 [=, this](wpi::util::SmallVectorImpl<char>& buf) -> std::string_view {
148 std::scoped_lock lock(m_mutex);
149 if (m_haveSelected) {
150 buf.assign(m_selected.begin(), m_selected.end());
151 return {buf.data(), buf.size()};
152 } else {
153 return m_defaultChoice;
154 }
155 },
156 nullptr);
157 builder.AddStringProperty(kSelected, nullptr,
158 [=, this](std::string_view val) {
159 T choice{};
160 std::function<void(T)> listener;
161 {
162 std::scoped_lock lock(m_mutex);
163 m_haveSelected = true;
164 m_selected = val;
165 if (m_previousVal != val && m_listener) {
166 choice = m_choices[val];
167 listener = m_listener;
168 }
169 m_previousVal = val;
170 }
171 if (listener) {
172 listener(choice);
173 }
174 });
175 }
176};
177
178} // namespace wpi
@ name
Definition base.h:690
std::string m_selected
Definition SendableChooserBase.hpp:40
wpi::util::mutex m_mutex
Definition SendableChooserBase.hpp:42
static constexpr const char * kDefault
Definition SendableChooserBase.hpp:33
bool m_haveSelected
Definition SendableChooserBase.hpp:41
static constexpr const char * kOptions
Definition SendableChooserBase.hpp:34
std::string m_previousVal
Definition SendableChooserBase.hpp:44
static constexpr const char * kActive
Definition SendableChooserBase.hpp:36
std::string m_defaultChoice
Definition SendableChooserBase.hpp:39
int m_instance
Definition SendableChooserBase.hpp:43
static constexpr const char * kInstance
Definition SendableChooserBase.hpp:37
static constexpr const char * kSelected
Definition SendableChooserBase.hpp:35
void SetDefaultOption(std::string_view name, T object)
Add the given object to the list of options and marks it as the default.
Definition SendableChooser.hpp:80
SendableChooser & operator=(SendableChooser &&rhs)=default
CopyType GetSelected() const
Returns a copy of the selected option (a std::weak_ptr<U> if T = std::shared_ptr<U>).
Definition SendableChooser.hpp:96
SendableChooser(SendableChooser &&rhs)=default
decltype(_unwrap_smart_ptr(m_choices.find("") ->second)) CopyType
Definition SendableChooser.hpp:51
void AddOption(std::string_view name, T object)
Adds the given object to the list of options.
Definition SendableChooser.hpp:67
~SendableChooser() override=default
SendableChooser()=default
void OnChange(std::function< void(T)> listener)
Bind a listener that's called when the selected value changes.
Definition SendableChooser.hpp:121
void InitSendable(wpi::util::SendableBuilder &builder) override
Initializes this Sendable object.
Definition SendableChooser.hpp:126
Helper class for building Sendable dashboard representations.
Definition SendableBuilder.hpp:21
virtual void AddStringProperty(std::string_view key, std::function< std::string()> getter, std::function< void(std::string_view)> setter)=0
Add a string property.
virtual void SetSmartDashboardType(std::string_view type)=0
Set the string representation of the named data type that will be used by the smart dashboard for thi...
virtual void AddStringArrayProperty(std::string_view key, std::function< std::vector< std::string >()> getter, std::function< void(std::span< const std::string >)> setter)=0
Add a string array property.
virtual void AddSmallStringProperty(std::string_view key, std::function< std::string_view(wpi::util::SmallVectorImpl< char > &buf)> getter, std::function< void(std::string_view)> setter)=0
Add a string property (SmallString form).
virtual void PublishConstInteger(std::string_view key, int64_t value)=0
Add a constant integer property.
Definition BooleanTopic.hpp:24
StringMap is a sorted associative container that contains key-value pairs with unique string keys.
Definition StringMap.hpp:26
Definition CvSource.hpp:15