[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

@@ -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