[wpilib] Remove Shuffleboard API (#7730)

This commit is contained in:
Peter Johnson
2025-01-24 23:47:42 -08:00
committed by GitHub
parent 01e71e73ce
commit adbe95e610
82 changed files with 60 additions and 6776 deletions

View File

@@ -14,7 +14,6 @@
#include "frc/DSControlWord.h"
#include "frc/Errors.h"
#include "frc/livewindow/LiveWindow.h"
#include "frc/shuffleboard/Shuffleboard.h"
#include "frc/smartdashboard/SmartDashboard.h"
using namespace frc;
@@ -153,7 +152,6 @@ void IterativeRobotBase::LoopFunc() {
} else if (m_lastMode == Mode::kTest) {
if (m_lwEnabledInTest) {
LiveWindow::SetEnabled(false);
Shuffleboard::DisableActuatorWidgets();
}
TestExit();
}
@@ -171,7 +169,6 @@ void IterativeRobotBase::LoopFunc() {
} else if (mode == Mode::kTest) {
if (m_lwEnabledInTest) {
LiveWindow::SetEnabled(true);
Shuffleboard::EnableActuatorWidgets();
}
TestInit();
m_watchdog.AddEpoch("TestInit()");
@@ -206,8 +203,6 @@ void IterativeRobotBase::LoopFunc() {
m_watchdog.AddEpoch("SmartDashboard::UpdateValues()");
LiveWindow::UpdateValues();
m_watchdog.AddEpoch("LiveWindow::UpdateValues()");
Shuffleboard::Update();
m_watchdog.AddEpoch("Shuffleboard::Update()");
if constexpr (IsSimulation()) {
HAL_SimPeriodicBefore();

View File

@@ -1,46 +0,0 @@
// 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.
#include "frc/shuffleboard/ComplexWidget.h"
#include <memory>
#include <wpi/sendable/Sendable.h>
#include "frc/smartdashboard/SendableBuilderImpl.h"
using namespace frc;
ComplexWidget::ComplexWidget(ShuffleboardContainer& parent,
std::string_view title, wpi::Sendable& sendable)
: ShuffleboardValue(title),
ShuffleboardWidget(parent, title),
m_sendable(sendable) {}
ComplexWidget::~ComplexWidget() = default;
void ComplexWidget::EnableIfActuator() {
if (m_builder && static_cast<SendableBuilderImpl&>(*m_builder).IsActuator()) {
static_cast<SendableBuilderImpl&>(*m_builder).StartLiveWindowMode();
}
}
void ComplexWidget::DisableIfActuator() {
if (m_builder && static_cast<SendableBuilderImpl&>(*m_builder).IsActuator()) {
static_cast<SendableBuilderImpl&>(*m_builder).StopLiveWindowMode();
}
}
void ComplexWidget::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) {
BuildMetadata(metaTable);
if (!m_builder) {
m_builder = std::make_unique<SendableBuilderImpl>();
static_cast<SendableBuilderImpl&>(*m_builder)
.SetTable(parentTable->GetSubTable(GetTitle()));
m_sendable.InitSendable(static_cast<SendableBuilderImpl&>(*m_builder));
static_cast<SendableBuilderImpl&>(*m_builder).StartListeners();
}
m_builder->Update();
}

View File

@@ -1,11 +0,0 @@
// 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.
#include "frc/shuffleboard/LayoutType.h"
using namespace frc;
std::string_view LayoutType::GetLayoutName() const {
return m_layoutName;
}

View File

@@ -1,50 +0,0 @@
// 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.
#include "frc/shuffleboard/RecordingController.h"
#include <string>
#include "frc/Errors.h"
using namespace frc;
using namespace frc::detail;
RecordingController::RecordingController(nt::NetworkTableInstance ntInstance) {
m_recordingControlEntry =
ntInstance.GetBooleanTopic("/Shuffleboard/.recording/RecordData")
.Publish();
m_recordingFileNameFormatEntry =
ntInstance.GetStringTopic("/Shuffleboard/.recording/FileNameFormat")
.Publish();
m_eventsTable = ntInstance.GetTable("/Shuffleboard/.recording/events");
}
void RecordingController::StartRecording() {
m_recordingControlEntry.Set(true);
}
void RecordingController::StopRecording() {
m_recordingControlEntry.Set(false);
}
void RecordingController::SetRecordingFileNameFormat(std::string_view format) {
m_recordingFileNameFormatEntry.Set(format);
}
void RecordingController::ClearRecordingFileNameFormat() {
m_recordingFileNameFormatEntry.Set("");
}
void RecordingController::AddEventMarker(
std::string_view name, std::string_view description,
ShuffleboardEventImportance importance) {
if (name.empty()) {
FRC_ReportError(err::Error, "Shuffleboard event name was not specified");
return;
}
m_eventsTable->GetSubTable(name)->GetEntry("Info").SetStringArray(
{{std::string{description},
std::string{ShuffleboardEventImportanceName(importance)}}});
}

View File

@@ -1,32 +0,0 @@
// 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.
#include "frc/shuffleboard/SendableCameraWrapper.h"
#include <functional>
#include <memory>
#include <string>
#include <wpi/StringMap.h>
#include <wpi/sendable/SendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
namespace frc {
namespace detail {
std::shared_ptr<SendableCameraWrapper>& GetSendableCameraWrapper(
std::string_view cameraName) {
static wpi::StringMap<std::shared_ptr<SendableCameraWrapper>> wrappers;
return wrappers[cameraName];
}
void AddToSendableRegistry(wpi::Sendable* sendable, std::string_view name) {
wpi::SendableRegistry::Add(sendable, name);
}
} // namespace detail
void SendableCameraWrapper::InitSendable(wpi::SendableBuilder& builder) {
builder.AddStringProperty(
".ShuffleboardURI", [this] { return m_uri; }, nullptr);
}
} // namespace frc

View File

@@ -1,92 +0,0 @@
// 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.
#include "frc/shuffleboard/Shuffleboard.h"
#include <memory>
#include <networktables/NetworkTableInstance.h>
#include "frc/shuffleboard/ShuffleboardTab.h"
using namespace frc;
void Shuffleboard::Update() {
GetInstance().Update();
}
ShuffleboardTab& Shuffleboard::GetTab(std::string_view title) {
return GetInstance().GetTab(title);
}
void Shuffleboard::SelectTab(int index) {
GetInstance().SelectTab(index);
}
void Shuffleboard::SelectTab(std::string_view title) {
GetInstance().SelectTab(title);
}
void Shuffleboard::EnableActuatorWidgets() {
GetInstance().EnableActuatorWidgets();
}
void Shuffleboard::DisableActuatorWidgets() {
// Need to update to make sure the sendable builders are initialized
Update();
GetInstance().DisableActuatorWidgets();
}
void Shuffleboard::StartRecording() {
GetRecordingController().StartRecording();
}
void Shuffleboard::StopRecording() {
GetRecordingController().StopRecording();
}
void Shuffleboard::SetRecordingFileNameFormat(std::string_view format) {
GetRecordingController().SetRecordingFileNameFormat(format);
}
void Shuffleboard::ClearRecordingFileNameFormat() {
GetRecordingController().ClearRecordingFileNameFormat();
}
void Shuffleboard::AddEventMarker(std::string_view name,
std::string_view description,
ShuffleboardEventImportance importance) {
GetRecordingController().AddEventMarker(name, description, importance);
}
void Shuffleboard::AddEventMarker(std::string_view name,
ShuffleboardEventImportance importance) {
AddEventMarker(name, "", importance);
}
static std::unique_ptr<detail::ShuffleboardInstance>& GetInstanceHolder() {
static std::unique_ptr<detail::ShuffleboardInstance> instance =
std::make_unique<detail::ShuffleboardInstance>(
nt::NetworkTableInstance::GetDefault());
return instance;
}
#ifndef __FRC_ROBORIO__
namespace frc::impl {
void ResetShuffleboardInstance() {
GetInstanceHolder() = std::make_unique<detail::ShuffleboardInstance>(
nt::NetworkTableInstance::GetDefault());
}
} // namespace frc::impl
#endif
detail::ShuffleboardInstance& Shuffleboard::GetInstance() {
return *GetInstanceHolder();
}
detail::RecordingController& Shuffleboard::GetRecordingController() {
static detail::RecordingController inst(
nt::NetworkTableInstance::GetDefault());
return inst;
}

View File

@@ -1,66 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
#include <memory>
#include <string>
using namespace frc;
ShuffleboardComponentBase::ShuffleboardComponentBase(
ShuffleboardContainer& parent, std::string_view title,
std::string_view type)
: ShuffleboardValue(title), m_parent(parent), m_type(type) {}
void ShuffleboardComponentBase::SetType(std::string_view type) {
m_type = type;
m_metadataDirty = true;
}
void ShuffleboardComponentBase::BuildMetadata(
std::shared_ptr<nt::NetworkTable> metaTable) {
if (!m_metadataDirty) {
return;
}
// Component type
if (!GetType().empty()) {
metaTable->GetEntry("PreferredComponent").SetString(GetType());
}
// Tile size
if (m_width > 0 && m_height > 0) {
metaTable->GetEntry("Size").SetDoubleArray(
{{static_cast<double>(m_width), static_cast<double>(m_height)}});
}
// Tile position
if (m_column >= 0 && m_row >= 0) {
metaTable->GetEntry("Position")
.SetDoubleArray(
{{static_cast<double>(m_column), static_cast<double>(m_row)}});
}
// Custom properties
if (GetProperties().size() > 0) {
auto propTable = metaTable->GetSubTable("Properties");
for (auto& entry : GetProperties()) {
propTable->GetEntry(entry.first).SetValue(entry.second);
}
}
m_metadataDirty = false;
}
ShuffleboardContainer& ShuffleboardComponentBase::GetParent() {
return m_parent;
}
const std::string& ShuffleboardComponentBase::GetType() const {
return m_type;
}
const wpi::StringMap<nt::Value>& ShuffleboardComponentBase::GetProperties()
const {
return m_properties;
}

View File

@@ -1,404 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardContainer.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <ntcore_cpp.h>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/Errors.h"
#include "frc/shuffleboard/ComplexWidget.h"
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/ShuffleboardLayout.h"
#include "frc/shuffleboard/SimpleWidget.h"
using namespace frc;
static constexpr const char* layoutStrings[] = {"List Layout", "Grid Layout"};
static constexpr const char* GetStringFromBuiltInLayout(BuiltInLayouts layout) {
return layoutStrings[static_cast<int>(layout)];
}
ShuffleboardContainer::ShuffleboardContainer(std::string_view title)
: ShuffleboardValue(title) {}
const std::vector<std::unique_ptr<ShuffleboardComponentBase>>&
ShuffleboardContainer::GetComponents() const {
return m_components;
}
ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title,
BuiltInLayouts type) {
return GetLayout(title, GetStringFromBuiltInLayout(type));
}
ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title,
const LayoutType& type) {
return GetLayout(title, type.GetLayoutName());
}
ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title,
std::string_view type) {
if (m_layouts.count(title) == 0) {
auto layout = std::make_unique<ShuffleboardLayout>(*this, title, type);
auto ptr = layout.get();
m_components.emplace_back(std::move(layout));
m_layouts.insert(std::pair{title, ptr});
}
return *m_layouts[title];
}
ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title) {
if (m_layouts.count(title) == 0) {
throw FRC_MakeError(err::InvalidParameter,
"No layout with title {} has been defined", title);
}
return *m_layouts[title];
}
ComplexWidget& ShuffleboardContainer::Add(std::string_view title,
wpi::Sendable& sendable) {
CheckTitle(title);
auto widget = std::make_unique<ComplexWidget>(*this, title, sendable);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
ComplexWidget& ShuffleboardContainer::Add(wpi::Sendable& sendable) {
auto name = wpi::SendableRegistry::GetName(&sendable);
if (name.empty()) {
FRC_ReportError(err::Error, "Sendable must have a name");
}
return Add(name, sendable);
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
const nt::Value& defaultValue) {
CheckTitle(title);
auto widget = std::make_unique<SimpleWidget>(*this, title);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
ptr->GetEntry(nt::GetStringFromType(defaultValue.type()))
->SetDefault(defaultValue);
return *ptr;
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
bool defaultValue) {
return Add(title, nt::Value::MakeBoolean(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
double defaultValue) {
return Add(title, nt::Value::MakeDouble(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
float defaultValue) {
return Add(title, nt::Value::MakeFloat(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
int defaultValue) {
return Add(title, nt::Value::MakeInteger(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
std::string_view defaultValue) {
return Add(title, nt::Value::MakeString(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
const char* defaultValue) {
return Add(title, nt::Value::MakeString(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
std::span<const bool> defaultValue) {
return Add(title, nt::Value::MakeBooleanArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
std::span<const double> defaultValue) {
return Add(title, nt::Value::MakeDoubleArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
std::span<const float> defaultValue) {
return Add(title, nt::Value::MakeFloatArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(
std::string_view title, std::span<const int64_t> defaultValue) {
return Add(title, nt::Value::MakeIntegerArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::Add(
std::string_view title, std::span<const std::string> defaultValue) {
return Add(title, nt::Value::MakeStringArray(defaultValue));
}
SuppliedValueWidget<std::string>& ShuffleboardContainer::AddString(
std::string_view title, std::function<std::string()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, std::string value) {
entry.SetString(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::string>>(
*this, title, "string", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<double>& ShuffleboardContainer::AddNumber(
std::string_view title, std::function<double()> supplier) {
return AddDouble(title, std::move(supplier));
}
SuppliedValueWidget<double>& ShuffleboardContainer::AddDouble(
std::string_view title, std::function<double()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, double value) {
entry.SetDouble(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<double>>(
*this, title, "double", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<float>& ShuffleboardContainer::AddFloat(
std::string_view title, std::function<float()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, float value) {
entry.SetFloat(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<float>>(
*this, title, "float", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<int64_t>& ShuffleboardContainer::AddInteger(
std::string_view title, std::function<int64_t()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, int64_t value) {
entry.SetInteger(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<int64_t>>(
*this, title, "int", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<bool>& ShuffleboardContainer::AddBoolean(
std::string_view title, std::function<bool()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, bool value) {
entry.SetBoolean(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<bool>>(
*this, title, "boolean", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<std::string>>&
ShuffleboardContainer::AddStringArray(
std::string_view title,
std::function<std::vector<std::string>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry,
std::vector<std::string> value) {
entry.SetStringArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<std::string>>>(
*this, title, "string[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddNumberArray(
std::string_view title, std::function<std::vector<double>()> supplier) {
return AddDoubleArray(title, std::move(supplier));
}
SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddDoubleArray(
std::string_view title, std::function<std::vector<double>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry,
std::vector<double> value) {
entry.SetDoubleArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<double>>>(
*this, title, "double[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<float>>& ShuffleboardContainer::AddFloatArray(
std::string_view title, std::function<std::vector<float>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry,
std::vector<float> value) {
entry.SetFloatArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<float>>>(
*this, title, "float[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<int64_t>>&
ShuffleboardContainer::AddIntegerArray(
std::string_view title, std::function<std::vector<int64_t>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry,
std::vector<int64_t> value) {
entry.SetIntegerArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<int64_t>>>(
*this, title, "int[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<int>>& ShuffleboardContainer::AddBooleanArray(
std::string_view title, std::function<std::vector<int>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry, std::vector<int> value) {
entry.SetBooleanArray(value);
};
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<int>>>(
*this, title, "boolean[]", supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
std::string_view title, std::function<std::vector<uint8_t>()> supplier) {
return AddRaw(title, "raw", std::move(supplier));
}
SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
std::string_view title, std::string_view typeString,
std::function<std::vector<uint8_t>()> supplier) {
static auto setter = [](nt::GenericPublisher& entry,
std::vector<uint8_t> value) { entry.SetRaw(value); };
CheckTitle(title);
auto widget = std::make_unique<SuppliedValueWidget<std::vector<uint8_t>>>(
*this, title, typeString, supplier, setter);
auto ptr = widget.get();
m_components.emplace_back(std::move(widget));
return *ptr;
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, const nt::Value& defaultValue) {
auto& widget = Add(title, defaultValue);
widget.GetEntry(nt::GetStringFromType(defaultValue.type()))
->GetTopic()
.SetPersistent(true);
return widget;
}
SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
bool defaultValue) {
return AddPersistent(title, nt::Value::MakeBoolean(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
double defaultValue) {
return AddPersistent(title, nt::Value::MakeDouble(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
float defaultValue) {
return AddPersistent(title, nt::Value::MakeFloat(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
int defaultValue) {
return AddPersistent(title, nt::Value::MakeInteger(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::string_view defaultValue) {
return AddPersistent(title, nt::Value::MakeString(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::span<const bool> defaultValue) {
return AddPersistent(title, nt::Value::MakeBooleanArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::span<const double> defaultValue) {
return AddPersistent(title, nt::Value::MakeDoubleArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::span<const float> defaultValue) {
return AddPersistent(title, nt::Value::MakeFloatArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::span<const int64_t> defaultValue) {
return AddPersistent(title, nt::Value::MakeIntegerArray(defaultValue));
}
SimpleWidget& ShuffleboardContainer::AddPersistent(
std::string_view title, std::span<const std::string> defaultValue) {
return AddPersistent(title, nt::Value::MakeStringArray(defaultValue));
}
void ShuffleboardContainer::EnableIfActuator() {
for (auto& component : GetComponents()) {
component->EnableIfActuator();
}
}
void ShuffleboardContainer::DisableIfActuator() {
for (auto& component : GetComponents()) {
component->DisableIfActuator();
}
}
void ShuffleboardContainer::CheckTitle(std::string_view title) {
std::string titleStr{title};
if (m_usedTitles.count(titleStr) > 0) {
FRC_ReportError(err::Error, "Title is already in use: {}", title);
return;
}
m_usedTitles.insert(titleStr);
}

View File

@@ -1,94 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardInstance.h"
#include <memory>
#include <string>
#include <hal/FRCUsageReporting.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/SmallVector.h>
#include <wpi/StringMap.h>
#include "frc/shuffleboard/Shuffleboard.h"
using namespace frc::detail;
struct ShuffleboardInstance::Impl {
wpi::StringMap<ShuffleboardTab> tabs;
bool tabsChanged = false;
std::shared_ptr<nt::NetworkTable> rootTable;
std::shared_ptr<nt::NetworkTable> rootMetaTable;
nt::StringPublisher selectedTabPub;
};
ShuffleboardInstance::ShuffleboardInstance(nt::NetworkTableInstance ntInstance)
: m_impl(new Impl) {
m_impl->rootTable = ntInstance.GetTable(Shuffleboard::kBaseTableName);
m_impl->rootMetaTable = m_impl->rootTable->GetSubTable(".metadata");
m_impl->selectedTabPub =
m_impl->rootMetaTable->GetStringTopic("Selected")
.Publish(nt::PubSubOptions{.keepDuplicates = true});
}
ShuffleboardInstance::~ShuffleboardInstance() = default;
static bool gReported = false;
frc::ShuffleboardTab& ShuffleboardInstance::GetTab(std::string_view title) {
if (!gReported) {
HAL_Report(HALUsageReporting::kResourceType_Shuffleboard, 0);
gReported = true;
}
auto [it, added] = m_impl->tabs.try_emplace(title, *this, title);
if (added) {
m_impl->tabsChanged = true;
}
return it->second;
}
void ShuffleboardInstance::Update() {
if (m_impl->tabsChanged) {
wpi::SmallVector<std::string, 16> tabTitles;
for (auto& entry : m_impl->tabs) {
tabTitles.emplace_back(entry.second.GetTitle());
}
m_impl->rootMetaTable->GetEntry("Tabs").SetStringArray(tabTitles);
m_impl->tabsChanged = false;
}
for (auto& entry : m_impl->tabs) {
auto& tab = entry.second;
tab.BuildInto(m_impl->rootTable,
m_impl->rootMetaTable->GetSubTable(tab.GetTitle()));
}
}
void ShuffleboardInstance::EnableActuatorWidgets() {
for (auto& entry : m_impl->tabs) {
auto& tab = entry.second;
for (auto& component : tab.GetComponents()) {
component->EnableIfActuator();
}
}
}
void ShuffleboardInstance::DisableActuatorWidgets() {
for (auto& entry : m_impl->tabs) {
auto& tab = entry.second;
for (auto& component : tab.GetComponents()) {
component->DisableIfActuator();
}
}
}
void ShuffleboardInstance::SelectTab(int index) {
m_impl->selectedTabPub.Set(std::to_string(index));
}
void ShuffleboardInstance::SelectTab(std::string_view title) {
m_impl->selectedTabPub.Set(title);
}

View File

@@ -1,35 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardLayout.h"
#include <memory>
#include <wpi/json.h>
using namespace frc;
static constexpr std::string_view kSmartDashboardType = "ShuffleboardLayout";
ShuffleboardLayout::ShuffleboardLayout(ShuffleboardContainer& parent,
std::string_view title,
std::string_view type)
: ShuffleboardValue(title),
ShuffleboardComponent(parent, title, type),
ShuffleboardContainer(title) {
m_isLayout = true;
}
void ShuffleboardLayout::BuildInto(
std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) {
BuildMetadata(metaTable);
auto table = parentTable->GetSubTable(GetTitle());
table->GetEntry(".type").SetString(kSmartDashboardType);
table->GetEntry(".type").GetTopic().SetProperty("SmartDashboard",
kSmartDashboardType);
for (auto& component : GetComponents()) {
component->BuildInto(table, metaTable->GetSubTable(component->GetTitle()));
}
}

View File

@@ -1,32 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardTab.h"
#include <memory>
#include <wpi/json.h>
using namespace frc;
static constexpr std::string_view kSmartDashboardType = "ShuffleboardLayout";
ShuffleboardTab::ShuffleboardTab(ShuffleboardRoot& root, std::string_view title)
: ShuffleboardValue(title), ShuffleboardContainer(title), m_root(root) {}
ShuffleboardRoot& ShuffleboardTab::GetRoot() {
return m_root;
}
void ShuffleboardTab::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) {
auto tabTable = parentTable->GetSubTable(GetTitle());
tabTable->GetEntry(".type").SetString(kSmartDashboardType);
tabTable->GetEntry(".type").GetTopic().SetProperty("SmartDashboard",
kSmartDashboardType);
for (auto& component : GetComponents()) {
component->BuildInto(tabTable,
metaTable->GetSubTable(component->GetTitle()));
}
}

View File

@@ -1,39 +0,0 @@
// 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.
#include "frc/shuffleboard/ShuffleboardWidget.h"
using namespace frc;
static constexpr const char* widgetStrings[] = {
"Text View",
"Number Slider",
"Number Bar",
"Simple Dial",
"Graph",
"Boolean Box",
"Toggle Button",
"Toggle Switch",
"Voltage View",
"PDP",
"ComboBox Chooser",
"Split Button Chooser",
"Encoder",
"Motor Controller",
"Command",
"PID Command",
"PID Controller",
"Accelerometer",
"3-Axis Accelerometer",
"Gyro",
"Relay",
"Differential Drivebase",
"Mecanum Drivebase",
"Camera Stream",
"Field",
};
const char* detail::GetStringForWidgetType(BuiltInWidgets type) {
return widgetStrings[static_cast<int>(type)];
}

View File

@@ -1,51 +0,0 @@
// 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.
#include "frc/shuffleboard/SimpleWidget.h"
#include <memory>
#include "frc/shuffleboard/Shuffleboard.h"
#include "frc/shuffleboard/ShuffleboardLayout.h"
#include "frc/shuffleboard/ShuffleboardTab.h"
using namespace frc;
SimpleWidget::SimpleWidget(ShuffleboardContainer& parent,
std::string_view title)
: ShuffleboardValue(title), ShuffleboardWidget(parent, title), m_entry() {}
nt::GenericEntry* SimpleWidget::GetEntry() {
if (!m_entry) {
ForceGenerate();
}
return &m_entry;
}
nt::GenericEntry* SimpleWidget::GetEntry(std::string_view typeString) {
if (!m_entry) {
m_typeString = typeString;
ForceGenerate();
}
return &m_entry;
}
void SimpleWidget::BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) {
BuildMetadata(metaTable);
if (!m_entry) {
m_entry = parentTable->GetTopic(GetTitle()).GetGenericEntry(m_typeString);
}
}
void SimpleWidget::ForceGenerate() {
ShuffleboardContainer* parent = &GetParent();
while (parent->m_isLayout) {
parent = &(static_cast<ShuffleboardLayout*>(parent)->GetParent());
}
auto& tab = *static_cast<ShuffleboardTab*>(parent);
tab.GetRoot().Update();
}

View File

@@ -1,11 +0,0 @@
// 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.
#include "frc/shuffleboard/WidgetType.h"
using namespace frc;
std::string_view WidgetType::GetWidgetName() const {
return m_widgetName;
}

View File

@@ -1,49 +0,0 @@
// 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 "frc/shuffleboard/LayoutType.h"
namespace frc {
/**
* The types of layouts bundled with Shuffleboard.
*
* <pre>{@code
* ShuffleboardLayout myList = Shuffleboard::GetTab("My Tab")
* .GetLayout(BuiltinLayouts::kList, "My List");
* }</pre>
*/
enum class BuiltInLayouts {
/**
* Groups components in a vertical list. New widgets added to the layout will
* be placed at the bottom of the list. <br>Custom properties: <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Label position</td><td>String</td><td>"BOTTOM"</td>
* <td>The position of component labels inside the grid. One of
* {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}</td></tr>
* </table>
*/
kList,
/**
* Groups components in an <i>n</i> x <i>m</i> grid. Grid layouts default to
* 3x3. <br>Custom properties: <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Number of columns</td><td>Number</td><td>3</td><td>Must be in the
* range [1,15]</td>
* </tr>
* <tr><td>Number of rows</td><td>Number</td><td>3</td><td>Must be in the
* range [1,15]</td></tr> <tr> <td>Label position</td> <td>String</td>
* <td>"BOTTOM"</td>
* <td>The position of component labels inside the grid.
* One of {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}</td>
* </tr>
* </table>
*/
kGrid
};
} // namespace frc

View File

@@ -1,385 +0,0 @@
// 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 "frc/shuffleboard/WidgetType.h"
namespace frc {
/**
* The types of the widgets bundled with Shuffleboard.
*
* <p>For example, setting a number to be displayed with a slider:
* <pre>{@code
* NetworkTableEntry example = Shuffleboard.getTab("My Tab")
* .add("My Number", 0)
* .withWidget(BuiltInWidgets.kNumberSlider)
* .getEntry();
* }</pre>
*
* <p>Each value in this enum goes into detail on what data types that widget
* can support, as well as the custom properties that widget uses.
*/
enum class BuiltInWidgets {
/**
* Displays a value with a simple text field.
* <br>Supported types:
* <ul>
* <li>String</li>
* <li>Number</li>
* <li>Boolean</li>
* </ul>
* <br>This widget has no custom properties.
*/
kTextView,
/**
* Displays a number with a controllable slider.
* <br>Supported types:
* <ul>
* <li>Number</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Min</td><td>Number</td><td>-1.0</td><td>The minimum value of the
* slider</td></tr> <tr><td>Max</td><td>Number</td><td>1.0</td><td>The maximum
* value of the slider</td></tr> <tr><td>Block
* increment</td><td>Number</td><td>0.0625</td> <td>How much to move the
* slider by with the arrow keys</td></tr>
* </table>
*/
kNumberSlider,
/**
* Displays a number with a view-only bar.
* <br>Supported types:
* <ul>
* <li>Number</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Min</td><td>Number</td><td>-1.0</td><td>The minimum value of the
* bar</td></tr> <tr><td>Max</td><td>Number</td><td>1.0</td><td>The maximum
* value of the bar</td></tr>
* <tr><td>Center</td><td>Number</td><td>0</td><td>The center ("zero") value
* of the bar</td></tr>
* </table>
*/
kNumberBar,
/**
* Displays a number with a view-only dial. Displayed values are rounded to
* the nearest integer. <br>Supported types: <ul> <li>Number</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Min</td><td>Number</td><td>0</td><td>The minimum value of the
* dial</td></tr> <tr><td>Max</td><td>Number</td><td>100</td><td>The maximum
* value of the dial</td></tr> <tr><td>Show
* value</td><td>Boolean</td><td>true</td> <td>Whether or not to show the
* value as text</td></tr>
* </table>
*/
kDial,
/**
* Displays a number with a graph. <strong>NOTE:</strong> graphs can be taxing
* on the computer running the dashboard. Keep the number of visible data
* points to a minimum. Making the widget smaller also helps with performance,
* but may cause the graph to become difficult to read. <br>Supported types:
* <ul>
* <li>Number</li>
* <li>Number array</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Visible time</td><td>Number</td><td>30</td>
* <td>How long, in seconds, should past data be visible for</td></tr>
* </table>
*/
kGraph,
/**
* Displays a boolean value as a large colored box.
* <br>Supported types:
* <ul>
* <li>Boolean</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Color when true</td><td>Color</td><td>"green"</td>
* <td>Can be specified as a string ({@code "#00FF00"}) or a rgba integer
* ({@code 0x00FF0000})
* </td></tr>
* <tr><td>Color when false</td><td>Color</td><td>"red"</td>
* <td>Can be specified as a string or a number</td></tr>
* </table>
*/
kBooleanBox,
/**
* Displays a boolean with a large interactive toggle button.
* <br>Supported types:
* <ul>
* <li>Boolean</li>
* </ul>
* <br>This widget has no custom properties.
*/
kToggleButton,
/**
* Displays a boolean with a fixed-size toggle switch.
* <br>Supported types:
* <ul>
* <li>Boolean</li>
* </ul>
* <br>This widget has no custom properties.
*/
kToggleSwitch,
/**
* Displays an analog input or a raw number with a number bar.
* <br>Supported types:
* <ul>
* <li>Number</li>
* <li>AnalogInput</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Min</td><td>Number</td><td>0</td><td>The minimum value of the
* bar</td></tr> <tr><td>Max</td><td>Number</td><td>5</td><td>The maximum
* value of the bar</td></tr>
* <tr><td>Center</td><td>Number</td><td>0</td><td>The center ("zero") value
* of the bar</td></tr>
* <tr><td>Orientation</td><td>String</td><td>"HORIZONTAL"</td>
* <td>The orientation of the bar. One of {@code ["HORIZONTAL",
* "VERTICAL"]}</td></tr> <tr><td>Number of tick
* marks</td><td>Number</td><td>5</td> <td>The number of discrete ticks on the
* bar</td></tr>
* </table>
*/
kVoltageView,
/**
* Displays a PowerDistribution. <br>Supported types: <ul> <li>
* PowerDistribution</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Show voltage and current values</td><td>Boolean</td><td>true</td>
* <td>Whether or not to display the voltage and current draw</td></tr>
* </table>
*/
kPowerDistribution,
/**
* Displays a SendableChooser with a dropdown combo box with a list of
* options.
* <br>Supported types:
* <ul>
* <li>SendableChooser</li>
* </ul>
* <br>This widget has no custom properties.
*/
kComboBoxChooser,
/**
* Displays a SendableChooserwith a toggle button for each available option.
* <br>Supported types:
* <ul>
* <li>SendableChooser</li>
* </ul>
* <br>This widget has no custom properties.
*/
kSplitButtonChooser,
/**
* Displays an Encoder displaying its speed,
* total traveled distance, and its distance per tick. <br>Supported types:
* <ul>
* <li>Encoder</li>
* </ul>
* <br>This widget has no custom properties.
*/
kEncoder,
/**
* Displays a MotorController.
* The motor controller will be controllable from the dashboard when test mode
* is enabled, but will otherwise be view-only. <br>Supported types: <ul>
* <li>PWMMotorController</li>
* <li>DMC60</li>
* <li>Jaguar</li>
* <li>PWMTalonSRX</li>
* <li>PWMVictorSPX</li>
* <li>SD540</li>
* <li>Spark</li>
* <li>Talon</li>
* <li>Victor</li>
* <li>VictorSP</li>
* <li>MotorControllerGroup</li>
* <li>Any custom subclass of {@code SpeedContorller}</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Orientation</td><td>String</td><td>"HORIZONTAL"</td>
* <td>One of {@code ["HORIZONTAL", "VERTICAL"]}</td></tr>
* </table>
*/
kMotorController,
/**
* Displays a command with a toggle button. Pressing the button will start the
* command, and the button will automatically release when the command
* completes. <br>Supported types: <ul> <li>Command</li> <li>CommandGroup</li>
* <li>Any custom subclass of {@code Command} or {@code CommandGroup}</li>
* </ul>
* <br>This widget has no custom properties.
*/
kCommand,
/**
* Displays a PID command with a checkbox and an editor for the PIDF
* constants. Selecting the checkbox will start the command, and the checkbox
* will automatically deselect when the command completes. <br>Supported
* types: <ul> <li>PIDCommand</li>
* <li>Any custom subclass of {@code PIDCommand}</li>
* </ul>
* <br>This widget has no custom properties.
*/
kPIDCommand,
/**
* Displays a PID controller with an editor for the PIDF constants and a
* toggle switch for enabling and disabling the controller. <br>Supported
* types: <ul> <li>PIDController</li>
* </ul>
* <br>This widget has no custom properties.
*/
kPIDController,
/**
* Displays an accelerometer with a number bar displaying the magnitude of the
* acceleration and text displaying the exact value. <br>Supported types: <ul>
* <li>AnalogAccelerometer</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Min</td><td>Number</td><td>-1</td>
* <td>The minimum acceleration value to display</td></tr>
* <tr><td>Max</td><td>Number</td><td>1</td>
* <td>The maximum acceleration value to display</td></tr>
* <tr><td>Show text</td><td>Boolean</td><td>true</td>
* <td>Show or hide the acceleration values</td></tr>
* <tr><td>Precision</td><td>Number</td><td>2</td>
* <td>How many numbers to display after the decimal point</td></tr>
* <tr><td>Show tick marks</td><td>Boolean</td><td>false</td>
* <td>Show or hide the tick marks on the number bars</td></tr>
* </table>
*/
kAccelerometer,
/**
* Displays a 3-axis accelerometer with a number bar for each axis'
* acceleration. <br>Supported types: <ul> <li>ADXL345_I2C</li> <li>
* ADXL345_SPI</li> <li>ADXL362</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Range</td><td>Range</td><td>k16G</td><td>The accelerometer
* range</td></tr> <tr><td>Show value</td><td>Boolean</td><td>true</td>
* <td>Show or hide the acceleration values</td></tr>
* <tr><td>Precision</td><td>Number</td><td>2</td>
* <td>How many numbers to display after the decimal point</td></tr>
* <tr><td>Show tick marks</td><td>Boolean</td><td>false</td>
* <td>Show or hide the tick marks on the number bars</td></tr>
* </table>
*/
k3AxisAccelerometer,
/**
* Displays a gyro with a dial from 0 to 360 degrees.
* <br>Supported types:
* <ul>
* <li>ADXRS450_Gyro</li>
* <li>AnalogGyro</li>
* <li>Any custom subclass of {@code GyroBase} (such as a MXP gyro)</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Major tick
* spacing</td><td>Number</td><td>45</td><td>Degrees</td></tr>
* <tr><td>Starting angle</td><td>Number</td><td>180</td>
* <td>How far to rotate the entire dial, in degrees</td></tr>
* <tr><td>Show tick mark ring</td><td>Boolean</td><td>true</td></tr>
* </table>
*/
kGyro,
/**
* Displays a relay with toggle buttons for each supported mode (off, on,
* forward, reverse). <br>Supported types: <ul> <li>Relay</li>
* </ul>
* <br>This widget has no custom properties.
*/
kRelay,
/**
* Displays a differential drive with a widget that displays the speed of each
* side of the drivebase and a vector for the direction and rotation of the
* drivebase. The widget will be controllable if the robot is in test mode.
* <br>Supported types:
* <ul>
* <li>DifferentialDrive</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Number of wheels</td><td>Number</td><td>4</td><td>Must be a
* positive even integer
* </td></tr>
* <tr><td>Wheel diameter</td><td>Number</td><td>80</td><td>Pixels</td></tr>
* <tr><td>Show velocity vectors</td><td>Boolean</td><td>true</td></tr>
* </table>
*/
kDifferentialDrive,
/**
* Displays a mecanum drive with a widget that displays the speed of each
* wheel, and vectors for the direction and rotation of the drivebase. The
* widget will be controllable if the robot is in test mode. <br>Supported
* types: <ul> <li>MecanumDrive</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Show velocity vectors</td><td>Boolean</td><td>true</td></tr>
* </table>
*/
kMecanumDrive,
/**
* Displays a camera stream.
* <br>Supported types:
* <ul>
* <li>VideoSource (as long as it is streaming on an MJPEG server)</li>
* </ul>
* <br>Custom properties:
* <table>
* <tr><th>Name</th><th>Type</th><th>Default Value</th><th>Notes</th></tr>
* <tr><td>Show crosshair</td><td>Boolean</td><td>true</td>
* <td>Show or hide a crosshair on the image</td></tr>
* <tr><td>Crosshair color</td><td>Color</td><td>"white"</td>
* <td>Can be a string or a rgba integer</td></tr>
* <tr><td>Show controls</td><td>Boolean</td><td>true</td><td>Show or hide the
* stream controls
* </td></tr>
* <tr><td>Rotation</td><td>String</td><td>"NONE"</td>
* <td>Rotates the displayed image. One of {@code ["NONE", "QUARTER_CW",
* "QUARTER_CCW", "HALF"]}
* </td></tr>
* </table>
*/
kCameraStream,
/**
* Displays a field2d object.<br>
* Supported types:
*
* <ul>
* <li>Field2d
* </ul>
*/
kField,
};
} // namespace frc

View File

@@ -1,46 +0,0 @@
// 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 <memory>
#include <string_view>
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardWidget.h"
namespace wpi {
class Sendable;
class SendableBuilder;
} // namespace wpi
namespace frc {
class ShuffleboardContainer;
/**
* A Shuffleboard widget that handles a Sendable object such as a motor
* controller or sensor.
*/
class ComplexWidget final : public ShuffleboardWidget<ComplexWidget> {
public:
ComplexWidget(ShuffleboardContainer& parent, std::string_view title,
wpi::Sendable& sendable);
~ComplexWidget() override;
void EnableIfActuator() override;
void DisableIfActuator() override;
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override;
private:
wpi::Sendable& m_sendable;
std::unique_ptr<wpi::SendableBuilder> m_builder;
};
} // namespace frc

View File

@@ -1,34 +0,0 @@
// 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 <string_view>
namespace frc {
/**
* Represents the type of a layout in Shuffleboard. Using this is preferred over
* specifying raw strings, to avoid typos and having to know or look up the
* exact string name for a desired layout.
*
* @see BuiltInLayouts the built-in layout types
*/
class LayoutType {
public:
explicit constexpr LayoutType(const char* layoutName)
: m_layoutName(layoutName) {}
~LayoutType() = default;
/**
* Gets the string type of the layout as defined by that layout in
* Shuffleboard.
*/
std::string_view GetLayoutName() const;
private:
const char* m_layoutName;
};
} // namespace frc

View File

@@ -1,40 +0,0 @@
// 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 <memory>
#include <string>
#include <string_view>
#include <networktables/BooleanTopic.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#include <networktables/StringTopic.h>
#include <wpi/SmallVector.h>
#include "frc/shuffleboard/ShuffleboardEventImportance.h"
namespace frc::detail {
class RecordingController final {
public:
explicit RecordingController(nt::NetworkTableInstance ntInstance);
virtual ~RecordingController() = default;
void StartRecording();
void StopRecording();
void SetRecordingFileNameFormat(std::string_view format);
void ClearRecordingFileNameFormat();
void AddEventMarker(std::string_view name, std::string_view description,
ShuffleboardEventImportance importance);
private:
nt::BooleanPublisher m_recordingControlEntry;
nt::StringPublisher m_recordingFileNameFormatEntry;
std::shared_ptr<nt::NetworkTable> m_eventsTable;
};
} // namespace frc::detail

View File

@@ -1,136 +0,0 @@
// 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 <functional>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#ifndef DYNAMIC_CAMERA_SERVER
#include <cscore_oo.h>
#include <fmt/format.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#else
namespace cs {
class VideoSource;
} // namespace cs
using CS_Handle = int; // NOLINT
using CS_Source = CS_Handle; // NOLINT
#endif
#include <networktables/StringArrayTopic.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
namespace frc {
class SendableCameraWrapper;
namespace detail {
constexpr const char* kProtocol = "camera_server://";
std::shared_ptr<SendableCameraWrapper>& GetSendableCameraWrapper(
std::string_view cameraName);
void AddToSendableRegistry(wpi::Sendable* sendable, std::string_view name);
} // namespace detail
/**
* A wrapper to make video sources sendable and usable from Shuffleboard.
*/
class SendableCameraWrapper
: public wpi::Sendable,
public wpi::SendableHelper<SendableCameraWrapper> {
private:
struct private_init {};
public:
/**
* Creates a new sendable wrapper. Private constructor to avoid direct
* instantiation with multiple wrappers floating around for the same camera.
*
* @param cameraName the name of the camera to wrap
*/
SendableCameraWrapper(std::string_view cameraName, const private_init&);
/**
* Creates a new sendable wrapper. Private constructor to avoid direct
* instantiation with multiple wrappers floating around for the same camera.
*
* @param cameraName the name of the camera to wrap
* @param cameraUrls camera URLs
*/
SendableCameraWrapper(std::string_view cameraName,
std::span<const std::string> cameraUrls,
const private_init&);
/**
* Gets a sendable wrapper object for the given video source, creating the
* wrapper if one does not already exist for the source.
*
* @param source the video source to wrap
* @return a sendable wrapper object for the video source, usable in
* Shuffleboard via ShuffleboardTab::Add() and ShuffleboardLayout::Add()
*/
static SendableCameraWrapper& Wrap(const cs::VideoSource& source);
static SendableCameraWrapper& Wrap(CS_Source source);
static SendableCameraWrapper& Wrap(std::string_view cameraName,
std::span<const std::string> cameraUrls);
void InitSendable(wpi::SendableBuilder& builder) override;
private:
std::string m_uri;
nt::StringArrayPublisher m_streams;
};
#ifndef DYNAMIC_CAMERA_SERVER
inline SendableCameraWrapper::SendableCameraWrapper(std::string_view name,
const private_init&)
: m_uri(detail::kProtocol) {
detail::AddToSendableRegistry(this, name);
m_uri += name;
}
inline SendableCameraWrapper::SendableCameraWrapper(
std::string_view cameraName, std::span<const std::string> cameraUrls,
const private_init&)
: SendableCameraWrapper(cameraName, private_init{}) {
m_streams = nt::NetworkTableInstance::GetDefault()
.GetStringArrayTopic(
fmt::format("/CameraPublisher/{}/streams", cameraName))
.Publish();
m_streams.Set(cameraUrls);
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
const cs::VideoSource& source) {
return Wrap(source.GetHandle());
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(CS_Source source) {
CS_Status status = 0;
auto name = cs::GetSourceName(source, &status);
auto& wrapper = detail::GetSendableCameraWrapper(name);
if (!wrapper) {
wrapper = std::make_shared<SendableCameraWrapper>(name, private_init{});
}
return *wrapper;
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
std::string_view cameraName, std::span<const std::string> cameraUrls) {
auto& wrapper = detail::GetSendableCameraWrapper(cameraName);
if (!wrapper) {
wrapper = std::make_shared<SendableCameraWrapper>(cameraName, cameraUrls,
private_init{});
}
return *wrapper;
}
#endif
} // namespace frc

View File

@@ -1,196 +0,0 @@
// 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 <string_view>
#include "frc/shuffleboard/RecordingController.h"
#include "frc/shuffleboard/ShuffleboardEventImportance.h"
#include "frc/shuffleboard/ShuffleboardInstance.h"
namespace frc {
class ShuffleboardTab;
/**
* The Shuffleboard class provides a mechanism with which data can be added and
* laid out in the Shuffleboard dashboard application from a robot program. Tabs
* and layouts can be specified, as well as choosing which widgets to display
* with and setting properties of these widgets; for example, programmers can
* specify a specific {@code boolean} value to be displayed with a toggle button
* instead of the default colored box, or set custom colors for that box.
*
* For example, displaying a boolean entry with a toggle button:
* <pre>{@code
* NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
* .add("My Boolean", false)
* .withWidget("Toggle Button")
* .getEntry();
* }</pre>
*
* Changing the colors of the boolean box:
* <pre>{@code
* NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
* .add("My Boolean", false)
* .withWidget("Boolean Box")
* .withProperties(Map.of("colorWhenTrue", "green", "colorWhenFalse",
* "maroon")) .getEntry();
* }</pre>
*
* Specifying a parent layout. Note that the layout type must <i>always</i> be
* specified, even if the layout has already been generated by a previously
* defined entry.
* <pre>{@code
* NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
* .getLayout("List", "Example List")
* .add("My Boolean", false)
* .withWidget("Toggle Button")
* .getEntry();
* }</pre>
* </p>
*
* Teams are encouraged to set up shuffleboard layouts at the start of the robot
* program.
*/
class Shuffleboard final {
public:
/**
* The name of the base NetworkTable into which all Shuffleboard data will be
* added.
*/
static constexpr const char* kBaseTableName = "/Shuffleboard";
/**
* Updates all the values in Shuffleboard. Iterative and timed robots are
* pre-configured to call this method in the main robot loop; teams using
* custom robot base classes, or subclass SampleRobot, should make sure to
* call this repeatedly to keep data on the dashboard up to date.
*/
static void Update();
/**
* Gets the Shuffleboard tab with the given title, creating it if it does not
* already exist.
*
* @param title the title of the tab
* @return the tab with the given title
*/
static ShuffleboardTab& GetTab(std::string_view title);
/**
* Selects the tab in the dashboard with the given index in the range
* [0..n-1], where <i>n</i> is the number of tabs in the dashboard at the time
* this method is called.
*
* @param index the index of the tab to select
*/
static void SelectTab(int index);
/**
* Selects the tab in the dashboard with the given title.
*
* @param title the title of the tab to select
*/
static void SelectTab(std::string_view title);
/**
* Enables user control of widgets containing actuators: motor controllers,
* relays, etc. This should only be used when the robot is in test mode.
* IterativeRobotBase and SampleRobot are both configured to call this method
* when entering test mode; most users should not need to use this method
* directly.
*/
static void EnableActuatorWidgets();
/**
* Disables user control of widgets containing actuators. For safety reasons,
* actuators should only be controlled while in test mode. IterativeRobotBase
* and SampleRobot are both configured to call this method when exiting in
* test mode; most users should not need to use this method directly.
*/
static void DisableActuatorWidgets();
/**
* Starts data recording on the dashboard. Has no effect if recording is
* already in progress.
*/
static void StartRecording();
/**
* Stops data recording on the dashboard. Has no effect if no recording is in
* progress.
*/
static void StopRecording();
/**
* Sets the file name format for new recording files to use. If recording is
* in progress when this method is called, it will continue to use the same
* file. New recordings will use the format.
*
* <p>To avoid recording files overwriting each other, make sure to use unique
* recording file names. File name formats accept templates for inserting the
* date and time when the recording started with the {@code ${date}} and
* {@code ${time}} templates, respectively. For example, the default format is
* {@code "recording-${time}"} and recording files created with it will have
* names like {@code "recording-2018.01.15.sbr"}. Users are
* <strong>strongly</strong> recommended to use the {@code ${time}} template
* to ensure unique file names.
* </p>
*
* @param format the format for the
*/
static void SetRecordingFileNameFormat(std::string_view format);
/**
* Clears the custom name format for recording files. New recordings will use
* the default format.
*
* @see SetRecordingFileNameFormat(std::string_view)
*/
static void ClearRecordingFileNameFormat();
/**
* Notifies Shuffleboard of an event. Events can range from as trivial as a
* change in a command state to as critical as a total power loss or component
* failure. If Shuffleboard is recording, the event will also be recorded.
*
* <p>If {@code name} is {@code null} or empty, no event will be sent and an
* error will be printed to the driver station.
*
* @param name the name of the event
* @param description a description of the event
* @param importance the importance of the event
*/
static void AddEventMarker(std::string_view name,
std::string_view description,
ShuffleboardEventImportance importance);
/**
* Notifies Shuffleboard of an event. Events can range from as trivial as a
* change in a command state to as critical as a total power loss or component
* failure. If Shuffleboard is recording, the event will also be recorded.
*
* <p>If {@code name} is {@code null} or empty, no event will be sent and an
* error will be printed to the driver station.
*
* @param name the name of the event
* @param importance the importance of the event
*/
static void AddEventMarker(std::string_view name,
ShuffleboardEventImportance importance);
private:
static detail::ShuffleboardInstance& GetInstance();
static detail::RecordingController& GetRecordingController();
// TODO usage reporting
Shuffleboard() = default;
};
} // namespace frc
// Make use of references returned by member functions usable
#include "frc/shuffleboard/ShuffleboardTab.h"

View File

@@ -1,89 +0,0 @@
// 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 <string_view>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableValue.h>
#include <wpi/StringMap.h>
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
namespace frc {
class ShuffleboardContainer;
/**
* A generic component in Shuffleboard.
*
* @tparam Derived the self type
*/
template <typename Derived>
class ShuffleboardComponent : public ShuffleboardComponentBase {
public:
/**
* Constructs a ShuffleboardComponent.
*
* @param parent The parent container.
* @param title The component title.
* @param type The component type.
*/
ShuffleboardComponent(ShuffleboardContainer& parent, std::string_view title,
std::string_view type = "")
: ShuffleboardValue(title),
ShuffleboardComponentBase(parent, title, type) {}
/**
* Sets custom properties for this component. Property names are
* case-sensitive and whitespace-insensitive (capitalization and spaces do not
* matter).
*
* @param properties the properties for this component
* @return this component
*/
Derived& WithProperties(const wpi::StringMap<nt::Value>& properties) {
m_properties = properties;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
/**
* Sets the position of this component in the tab. This has no effect if this
* component is inside a layout.
*
* If the position of a single component is set, it is recommended to set the
* positions of <i>all</i> components inside a tab to prevent Shuffleboard
* from automatically placing another component there before the one with the
* specific position is sent.
*
* @param columnIndex the column in the tab to place this component
* @param rowIndex the row in the tab to place this component
* @return this component
*/
Derived& WithPosition(int columnIndex, int rowIndex) {
m_column = columnIndex;
m_row = rowIndex;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
/**
* Sets the size of this component in the tab. This has no effect if this
* component is inside a layout.
*
* @param width how many columns wide the component should be
* @param height how many rows high the component should be
* @return this component
*/
Derived& WithSize(int width, int height) {
m_width = width;
m_height = height;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
};
} // namespace frc

View File

@@ -1,55 +0,0 @@
// 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 <memory>
#include <string>
#include <string_view>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableValue.h>
#include <wpi/StringMap.h>
#include "frc/shuffleboard/ShuffleboardValue.h"
namespace frc {
class ShuffleboardContainer;
/**
* A shim class to allow storing ShuffleboardComponents in arrays.
*/
class ShuffleboardComponentBase : public virtual ShuffleboardValue {
public:
ShuffleboardComponentBase(ShuffleboardContainer& parent,
std::string_view title, std::string_view type = "");
void SetType(std::string_view type);
void BuildMetadata(std::shared_ptr<nt::NetworkTable> metaTable);
ShuffleboardContainer& GetParent();
const std::string& GetType() const;
protected:
wpi::StringMap<nt::Value> m_properties;
bool m_metadataDirty = true;
int m_column = -1;
int m_row = -1;
int m_width = -1;
int m_height = -1;
private:
ShuffleboardContainer& m_parent;
std::string m_type;
/**
* Gets the custom properties for this component. May be null.
*/
const wpi::StringMap<nt::Value>& GetProperties() const;
};
} // namespace frc

View File

@@ -1,727 +0,0 @@
// 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 <functional>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <vector>
#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableValue.h>
#include <wpi/SmallSet.h>
#include <wpi/StringMap.h>
#include "frc/shuffleboard/BuiltInLayouts.h"
#include "frc/shuffleboard/LayoutType.h"
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
#include "frc/shuffleboard/ShuffleboardValue.h"
#include "frc/shuffleboard/SuppliedValueWidget.h"
namespace cs {
class VideoSource;
} // namespace cs
namespace wpi {
class Sendable;
} // namespace wpi
namespace frc {
class ComplexWidget;
class ShuffleboardLayout;
class SimpleWidget;
/**
* Common interface for objects that can contain shuffleboard components.
*/
class ShuffleboardContainer : public virtual ShuffleboardValue {
public:
explicit ShuffleboardContainer(std::string_view title);
ShuffleboardContainer(ShuffleboardContainer&& rhs) = default;
~ShuffleboardContainer() override = default;
/**
* Gets the components that are direct children of this container.
*/
const std::vector<std::unique_ptr<ShuffleboardComponentBase>>& GetComponents()
const;
/**
* Gets the layout with the given type and title, creating it if it does not
* already exist at the time this method is called.
*
* @param title the title of the layout
* @param type the type of the layout, eg "List" or "Grid"
* @return the layout
*/
ShuffleboardLayout& GetLayout(std::string_view title, BuiltInLayouts type);
/**
* Gets the layout with the given type and title, creating it if it does not
* already exist at the time this method is called.
*
* @param title the title of the layout
* @param type the type of the layout, eg "List" or "Grid"
* @return the layout
*/
ShuffleboardLayout& GetLayout(std::string_view title, const LayoutType& type);
/**
* Gets the layout with the given type and title, creating it if it does not
* already exist at the time this method is called. Note: this method should
* only be used to use a layout type that is not already built into
* Shuffleboard. To use a layout built into Shuffleboard, use
* GetLayout(std::string_view, const LayoutType&) and the layouts in
* BuiltInLayouts.
*
* @param title the title of the layout
* @param type the type of the layout, eg "List Layout" or "Grid Layout"
* @return the layout
* @see GetLayout(std::string_view, const LayoutType&)
*/
ShuffleboardLayout& GetLayout(std::string_view title, std::string_view type);
/**
* Gets the already-defined layout in this container with the given title.
*
* <pre>{@code
* Shuffleboard::GetTab("Example Tab")->getLayout("My Layout",
* &BuiltInLayouts.kList);
*
* // Later...
* Shuffleboard::GetTab("Example Tab")->GetLayout("My Layout");
* }</pre>
*
* @param title the title of the layout to get
* @return the layout with the given title
* @throws if no layout has yet been defined with the given title
*/
ShuffleboardLayout& GetLayout(std::string_view title);
/**
* Adds a widget to this container to display the given sendable.
*
* @param title the title of the widget
* @param sendable the sendable to display
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
*/
ComplexWidget& Add(std::string_view title, wpi::Sendable& sendable);
/**
* Adds a widget to this container to display the given video stream.
*
* @param title the title of the widget
* @param video the video stream to display
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
*/
ComplexWidget& Add(std::string_view title, const cs::VideoSource& video);
/**
* Adds a widget to this container to display a video stream.
*
* @param title the title of the widget
* @param cameraName the name of the streamed camera
* @param cameraUrls the URLs with which the dashboard can access the camera
* stream
* @return a widget to display the camera stream
*/
ComplexWidget& AddCamera(std::string_view title, std::string_view cameraName,
std::span<const std::string> cameraUrls);
/**
* Adds a widget to this container to display the given sendable.
*
* @param sendable the sendable to display
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title, or if the sendable's name has not been
* specified
*/
ComplexWidget& Add(wpi::Sendable& sendable);
/**
* Adds a widget to this container to display the given video stream.
*
* @param video the video to display
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the same title as the video source
*/
ComplexWidget& Add(const cs::VideoSource& video);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::shared_ptr<nt::Value>)
* Add(std::string_view title, std::shared_ptr<nt::Value> defaultValue)
*/
SimpleWidget& Add(std::string_view title, const nt::Value& defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, bool)
* Add(std::string_view title, bool defaultValue)
*/
SimpleWidget& Add(std::string_view title, bool defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, double)
* Add(std::string_view title, double defaultValue)
*/
SimpleWidget& Add(std::string_view title, double defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, double)
* Add(std::string_view title, double defaultValue)
*/
SimpleWidget& Add(std::string_view title, float defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, int)
* Add(std::string_view title, int defaultValue)
*/
SimpleWidget& Add(std::string_view title, int defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::string_view)
* Add(std::string_view title, std::string_view defaultValue)
*/
SimpleWidget& Add(std::string_view title, std::string_view defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, const char*)
* Add(std::string_view title, const char* defaultValue)
*/
SimpleWidget& Add(std::string_view title, const char* defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::span<const bool>)
* Add(std::string_view title, std::span<const bool> defaultValue)
*/
SimpleWidget& Add(std::string_view title, std::span<const bool> defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::span<const double>)
* Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
std::span<const double> defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::span<const double>)
* Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
std::span<const float> defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::span<const double>)
* Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
std::span<const int64_t> defaultValue);
/**
* Adds a widget to this container to display the given data.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @throws IllegalArgumentException if a widget already exists in this
* container with the given title
* @see AddPersistent(std::string_view, std::span<const std::string>)
* Add(std::string_view title, std::span<const std::string> defaultValue)
*/
SimpleWidget& Add(std::string_view title,
std::span<const std::string> defaultValue);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::string>& AddString(
std::string_view title, std::function<std::string()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<double>& AddNumber(std::string_view title,
std::function<double()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<double>& AddDouble(std::string_view title,
std::function<double()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<float>& AddFloat(std::string_view title,
std::function<float()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<int64_t>& AddInteger(std::string_view title,
std::function<int64_t()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<bool>& AddBoolean(std::string_view title,
std::function<bool()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<std::string>>& AddStringArray(
std::string_view title,
std::function<std::vector<std::string>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<double>>& AddNumberArray(
std::string_view title, std::function<std::vector<double>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<double>>& AddDoubleArray(
std::string_view title, std::function<std::vector<double>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<float>>& AddFloatArray(
std::string_view title, std::function<std::vector<float>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<int64_t>>& AddIntegerArray(
std::string_view title, std::function<std::vector<int64_t>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<int>>& AddBooleanArray(
std::string_view title, std::function<std::vector<int>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<uint8_t>>& AddRaw(
std::string_view title, std::function<std::vector<uint8_t>()> supplier);
/**
* Adds a widget to this container. The widget will display the data provided
* by the value supplier. Changes made on the dashboard will not propagate to
* the widget object, and will be overridden by values from the value
* supplier.
*
* @param title the title of the widget
* @param typeString the NT type string
* @param supplier the supplier for values
* @return a widget to display data
*/
SuppliedValueWidget<std::vector<uint8_t>>& AddRaw(
std::string_view title, std::string_view typeString,
std::function<std::vector<uint8_t>()> supplier);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::shared_ptr<nt::Value>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(stdd::string_view, std::shared_ptr<nt::Value>)
* Add(std::string_view title, std::shared_ptr<nt::Value> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
const nt::Value& defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, bool), the value in the widget will be saved
* on the robot and will be used when the robot program next starts rather
* than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, bool)
* Add(std::string_view title, bool defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title, bool defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, double), the value in the widget will be saved
* on the robot and will be used when the robot program next starts rather
* than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, double)
* Add(std::string_view title, double defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title, double defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, float), the value in the widget will be saved
* on the robot and will be used when the robot program next starts rather
* than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, float)
* Add(std::string_view title, float defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title, float defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, int64_t), the value in the widget will be
* saved on the robot and will be used when the robot program next starts
* rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std:string_view, int64_t)
* Add(std::string_view title, int64_t defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title, int defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::string_view), the value in the widget
* will be saved on the robot and will be used when the robot program next
* starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::string_view)
* Add(std::string_view title, std::string_view defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::string_view defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::span<const bool>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::span<const bool>)
* Add(std::string_view title, std::span<const bool> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::span<const bool> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::span<const double>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::span<const double>)
* Add(std::string_view title, std::span<const double> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::span<const double> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::span<const float>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::span<const float>)
* Add(std::string_view title, std::span<const float> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::span<const float> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::span<const int64_t>), the value in the
* widget will be saved on the robot and will be used when the robot program
* next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::span<const int64_t>)
* Add(std::string_view title, std::span<const int64_t> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::span<const int64_t> defaultValue);
/**
* Adds a widget to this container to display a simple piece of data.
*
* Unlike Add(std::string_view, std::span<const std::string>), the value in
* the widget will be saved on the robot and will be used when the robot
* program next starts rather than {@code defaultValue}.
*
* @param title the title of the widget
* @param defaultValue the default value of the widget
* @return a widget to display the sendable data
* @see Add(std::string_view, std::span<const std::string>)
* Add(std::string_view title, std::span<const std::string> defaultValue)
*/
SimpleWidget& AddPersistent(std::string_view title,
std::span<const std::string> defaultValue);
void EnableIfActuator() override;
void DisableIfActuator() override;
protected:
bool m_isLayout = false;
private:
wpi::SmallSet<std::string, 32> m_usedTitles;
std::vector<std::unique_ptr<ShuffleboardComponentBase>> m_components;
wpi::StringMap<ShuffleboardLayout*> m_layouts;
/**
* Adds title to internal set if it hasn't already.
*
* @return True if title isn't in use; false otherwise.
*/
void CheckTitle(std::string_view title);
friend class SimpleWidget;
};
} // namespace frc
// Make use of references returned by member functions usable
#include "frc/shuffleboard/ComplexWidget.h"
#include "frc/shuffleboard/ShuffleboardLayout.h"
#include "frc/shuffleboard/SimpleWidget.h"
#ifndef DYNAMIC_CAMERA_SERVER
#include "frc/shuffleboard/SendableCameraWrapper.h"
inline frc::ComplexWidget& frc::ShuffleboardContainer::Add(
const cs::VideoSource& video) {
return Add(frc::SendableCameraWrapper::Wrap(video));
}
inline frc::ComplexWidget& frc::ShuffleboardContainer::Add(
std::string_view title, const cs::VideoSource& video) {
return Add(title, frc::SendableCameraWrapper::Wrap(video));
}
inline frc::ComplexWidget& frc::ShuffleboardContainer::AddCamera(
std::string_view title, std::string_view cameraName,
std::span<const std::string> cameraUrls) {
return Add(title, frc::SendableCameraWrapper::Wrap(cameraName, cameraUrls));
}
#endif

View File

@@ -1,40 +0,0 @@
// 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 <string_view>
namespace frc {
// Maintainer note: this enum is mirrored in WPILibJ and in Shuffleboard
// Modifying the enum or enum strings requires a corresponding change to the
// Java enum and the enum in Shuffleboard
enum ShuffleboardEventImportance { kTrivial, kLow, kNormal, kHigh, kCritical };
/**
* Returns name of the given enum.
*
* @return Name of the given enum.
*/
inline std::string_view ShuffleboardEventImportanceName(
ShuffleboardEventImportance importance) {
switch (importance) {
case kTrivial:
return "TRIVIAL";
case kLow:
return "LOW";
case kNormal:
return "NORMAL";
case kHigh:
return "HIGH";
case kCritical:
return "CRITICAL";
default:
return "NORMAL";
}
}
} // namespace frc

View File

@@ -1,40 +0,0 @@
// 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 <memory>
#include <string_view>
#include "frc/shuffleboard/ShuffleboardRoot.h"
#include "frc/shuffleboard/ShuffleboardTab.h"
namespace frc::detail {
class ShuffleboardInstance final : public ShuffleboardRoot {
public:
explicit ShuffleboardInstance(nt::NetworkTableInstance ntInstance);
virtual ~ShuffleboardInstance();
ShuffleboardInstance(ShuffleboardInstance&&) = default;
ShuffleboardInstance& operator=(ShuffleboardInstance&&) = default;
frc::ShuffleboardTab& GetTab(std::string_view title) override;
void Update() override;
void EnableActuatorWidgets() override;
void DisableActuatorWidgets() override;
void SelectTab(int index) override;
void SelectTab(std::string_view) override;
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace frc::detail

View File

@@ -1,40 +0,0 @@
// 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 <memory>
#include <string_view>
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/ShuffleboardContainer.h"
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4250)
#endif
namespace frc {
/**
* A layout in a Shuffleboard tab. Layouts can contain widgets and other
* layouts.
*/
class ShuffleboardLayout : public ShuffleboardComponent<ShuffleboardLayout>,
public ShuffleboardContainer {
public:
ShuffleboardLayout(ShuffleboardContainer& parent, std::string_view name,
std::string_view type);
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override;
};
} // namespace frc
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -1,63 +0,0 @@
// 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 <string_view>
namespace frc {
class ShuffleboardTab;
/**
* The root of the data placed in Shuffleboard. It contains the tabs, but no
* data is placed directly in the root.
*
* This class is package-private to minimize API surface area.
*/
class ShuffleboardRoot {
public:
/**
* Gets the tab with the given title, creating it if it does not already
* exist.
*
* @param title the title of the tab
* @return the tab with the given title
*/
virtual ShuffleboardTab& GetTab(std::string_view title) = 0;
/**
* Updates all tabs.
*/
virtual void Update() = 0;
/**
* Enables all widgets in Shuffleboard that offer user control over actuators.
*/
virtual void EnableActuatorWidgets() = 0;
/**
* Disables all widgets in Shuffleboard that offer user control over
* actuators.
*/
virtual void DisableActuatorWidgets() = 0;
/**
* Selects the tab in the dashboard with the given index in the range
* [0..n-1], where <i>n</i> is the number of tabs in the dashboard at the time
* this method is called.
*
* @param index the index of the tab to select
*/
virtual void SelectTab(int index) = 0;
/**
* Selects the tab in the dashboard with the given title.
*
* @param title the title of the tab to select
*/
virtual void SelectTab(std::string_view title) = 0;
};
} // namespace frc

View File

@@ -1,39 +0,0 @@
// 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 <memory>
#include <string_view>
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardContainer.h"
namespace frc {
class ShuffleboardRoot;
/**
* Represents a tab in the Shuffleboard dashboard. Widgets can be added to the
* tab with Add(Sendable), Add(std::string_view, Object), and
* Add(String, Sendable). Widgets can also be added to layouts with
* GetLayout(std::string_view, std::string_view); layouts can be nested
* arbitrarily deep (note that too many levels may make deeper components
* unusable).
*/
class ShuffleboardTab final : public ShuffleboardContainer {
public:
ShuffleboardTab(ShuffleboardRoot& root, std::string_view title);
ShuffleboardRoot& GetRoot();
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override;
private:
ShuffleboardRoot& m_root;
};
} // namespace frc

View File

@@ -1,67 +0,0 @@
// 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 <memory>
#include <string>
#include <string_view>
#include <networktables/NetworkTable.h>
namespace frc {
class ShuffleboardValue {
public:
explicit ShuffleboardValue(std::string_view title) : m_title(title) {}
virtual ~ShuffleboardValue() = default;
ShuffleboardValue(const ShuffleboardValue&) = delete;
ShuffleboardValue& operator=(const ShuffleboardValue&) = delete;
/**
* Gets the title of this Shuffleboard value.
*/
const std::string& GetTitle() const { return m_title; }
/**
* Builds the entries for this value.
*
* @param parentTable The table containing all the data for the parent. Values
* that require a complex entry or table structure should
* call {@code parentTable.getSubtable(getTitle())} to get
* the table to put data into. Values that only use a
* single entry should call
* {@code parentTable.getEntry(getTitle())} to get that
* entry.
* @param metaTable The table containing all the metadata for this value and
* its sub-values
*/
virtual void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) = 0;
/**
* Enables user control of this widget in the Shuffleboard application.
*
* This method is package-private to prevent users from enabling control
* themselves. Has no effect if the sendable is not marked as an actuator with
* SendableBuilder::SetActuator().
*/
virtual void EnableIfActuator() {}
/**
* Disables user control of this widget in the Shuffleboard application.
*
* This method is package-private to prevent users from enabling control
* themselves. Has no effect if the sendable is not marked as an actuator with
* SendableBuilder::SetActuator().
*/
virtual void DisableIfActuator() {}
private:
std::string m_title;
};
} // namespace frc

View File

@@ -1,74 +0,0 @@
// 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 <string_view>
#include "frc/shuffleboard/BuiltInWidgets.h"
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/WidgetType.h"
namespace frc {
class ShuffleboardContainer;
namespace detail {
const char* GetStringForWidgetType(BuiltInWidgets type);
} // namespace detail
/**
* Abstract superclass for widgets.
*
* <p>This class is package-private to minimize API surface area.
*
* @tparam Derived the self type
*/
template <typename Derived>
class ShuffleboardWidget : public ShuffleboardComponent<Derived> {
public:
ShuffleboardWidget(ShuffleboardContainer& parent, std::string_view title)
: ShuffleboardValue(title),
ShuffleboardComponent<Derived>(parent, title) {}
/**
* Sets the type of widget used to display the data. If not set, the default
* widget type will be used.
*
* @param widgetType the type of the widget used to display the data
* @return this widget object
* @see BuiltInWidgets
*/
Derived& WithWidget(BuiltInWidgets widgetType) {
return WithWidget(detail::GetStringForWidgetType(widgetType));
}
/**
* Sets the type of widget used to display the data. If not set, the default
* widget type will be used.
*
* @param widgetType the type of the widget used to display the data
* @return this widget object
*/
Derived& WithWidget(const WidgetType& widgetType) {
return WithWidget(widgetType.GetWidgetName());
}
/**
* Sets the type of widget used to display the data. If not set, the default
* widget type will be used. This method should only be used to use a widget
* that does not come built into Shuffleboard (i.e. one that comes with a
* custom or third-party plugin). To use a widget that is built into
* Shuffleboard, use WithWidget(WidgetType) and BuiltInWidgets.
*
* @param widgetType the type of the widget used to display the data
* @return this widget object
*/
Derived& WithWidget(std::string_view widgetType) {
this->SetType(widgetType);
return *static_cast<Derived*>(this);
}
};
} // namespace frc

View File

@@ -1,54 +0,0 @@
// 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 <memory>
#include <string>
#include <string_view>
#include <networktables/GenericEntry.h>
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardWidget.h"
namespace frc {
class ShuffleboardContainer;
/**
* A Shuffleboard widget that handles a single data point such as a number or
* string.
*/
class SimpleWidget final : public ShuffleboardWidget<SimpleWidget> {
public:
SimpleWidget(ShuffleboardContainer& parent, std::string_view title);
/**
* Gets the NetworkTable entry that contains the data for this widget.
* The widget owns the entry; the returned pointer's lifetime is the same as
* that of the widget.
*/
nt::GenericEntry* GetEntry();
/**
* Gets the NetworkTable entry that contains the data for this widget.
* The widget owns the entry; the returned pointer's lifetime is the same as
* that of the widget.
*
* @param typeString NT type string
*/
nt::GenericEntry* GetEntry(std::string_view typeString);
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override;
private:
nt::GenericEntry m_entry;
std::string m_typeString;
void ForceGenerate();
};
} // namespace frc

View File

@@ -1,58 +0,0 @@
// 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 <functional>
#include <memory>
#include <string>
#include <string_view>
#include <networktables/BooleanTopic.h>
#include <networktables/GenericEntry.h>
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
#include "frc/shuffleboard/ShuffleboardWidget.h"
namespace frc {
class ShuffleboardContainer;
template <typename T>
class SuppliedValueWidget : public ShuffleboardWidget<SuppliedValueWidget<T>> {
public:
SuppliedValueWidget(ShuffleboardContainer& parent, std::string_view title,
std::string_view typeString, std::function<T()> supplier,
std::function<void(nt::GenericPublisher&, T)> setter)
: ShuffleboardValue(title),
ShuffleboardWidget<SuppliedValueWidget<T>>(parent, title),
m_typeString(typeString),
m_supplier(supplier),
m_setter(setter) {}
void BuildInto(std::shared_ptr<nt::NetworkTable> parentTable,
std::shared_ptr<nt::NetworkTable> metaTable) override {
this->BuildMetadata(metaTable);
if (!m_controllablePub) {
m_controllablePub =
nt::BooleanTopic{metaTable->GetTopic("Controllable")}.Publish();
m_controllablePub.Set(false);
}
if (!m_entry) {
m_entry =
parentTable->GetTopic(this->GetTitle()).GenericPublish(m_typeString);
}
m_setter(m_entry, m_supplier());
}
private:
std::string m_typeString;
std::function<T()> m_supplier;
std::function<void(nt::GenericPublisher&, T)> m_setter;
nt::BooleanPublisher m_controllablePub;
nt::GenericPublisher m_entry;
};
} // namespace frc

View File

@@ -1,34 +0,0 @@
// 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 <string_view>
namespace frc {
/**
* Represents the type of a widget in Shuffleboard. Using this is preferred over
* specifying raw strings, to avoid typos and having to know or look up the
* exact string name for a desired widget.
*
* @see BuiltInWidgets the built-in widget types
*/
class WidgetType {
public:
explicit constexpr WidgetType(const char* widgetName)
: m_widgetName(widgetName) {}
~WidgetType() = default;
/**
* Gets the string type of the widget as defined by that widget in
* Shuffleboard.
*/
std::string_view GetWidgetName() const;
private:
const char* m_widgetName;
};
} // namespace frc