// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #pragma once #include #include #include #include #include #include #include #include #include "frc/smartdashboard/SendableChooser.h" namespace frc { template requires std::copy_constructible && std::default_initializable void SendableChooser::AddOption(std::string_view name, T object) { m_choices[name] = std::move(object); } template requires std::copy_constructible && std::default_initializable void SendableChooser::SetDefaultOption(std::string_view name, T object) { m_defaultChoice = name; AddOption(name, std::move(object)); } template requires std::copy_constructible && std::default_initializable auto SendableChooser::GetSelected() -> decltype(_unwrap_smart_ptr(m_choices[""])) { std::string selected = m_defaultChoice; { std::scoped_lock lock(m_mutex); if (m_haveSelected) { selected = m_selected; } } if (selected.empty()) { return decltype(_unwrap_smart_ptr(m_choices[""])){}; } else { return _unwrap_smart_ptr(m_choices[selected]); } } template requires std::copy_constructible && std::default_initializable void SendableChooser::OnChange(std::function listener) { std::scoped_lock lock(m_mutex); m_listener = listener; } template requires std::copy_constructible && std::default_initializable void SendableChooser::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("String Chooser"); builder.PublishConstInteger(kInstance, m_instance); builder.AddStringArrayProperty( kOptions, [=, this] { std::vector keys; for (const auto& choice : m_choices) { keys.emplace_back(choice.first()); } // Unlike std::map, wpi::StringMap elements // are not sorted std::sort(keys.begin(), keys.end()); return keys; }, nullptr); builder.AddSmallStringProperty( kDefault, [=, this](wpi::SmallVectorImpl&) -> std::string_view { return m_defaultChoice; }, nullptr); builder.AddSmallStringProperty( kActive, [=, this](wpi::SmallVectorImpl& buf) -> std::string_view { std::scoped_lock lock(m_mutex); if (m_haveSelected) { buf.assign(m_selected.begin(), m_selected.end()); return {buf.data(), buf.size()}; } else { return m_defaultChoice; } }, nullptr); builder.AddStringProperty(kSelected, nullptr, [=, this](std::string_view val) { T choice{}; std::function listener; { std::scoped_lock lock(m_mutex); m_haveSelected = true; m_selected = val; if (m_previousVal != val && m_listener) { choice = m_choices[val]; listener = m_listener; } m_previousVal = val; } if (listener) { listener(choice); } }); } template requires std::copy_constructible && std::default_initializable template U SendableChooser::_unwrap_smart_ptr(const U& value) { return value; } template requires std::copy_constructible && std::default_initializable template U* SendableChooser::_unwrap_smart_ptr(const std::unique_ptr& value) { return value.get(); } template requires std::copy_constructible && std::default_initializable template std::weak_ptr SendableChooser::_unwrap_smart_ptr( const std::shared_ptr& value) { return value; } } // namespace frc