Add constants for built-in Shuffleboard widgets and layouts (#1468)

Prevents users from having to remember (and correctly type) the names of Shuffleboard widgets.
This commit is contained in:
Sam Carlberg
2018-12-29 20:22:47 -05:00
committed by Peter Johnson
parent ceed1d74dc
commit 01d1322066
24 changed files with 1278 additions and 52 deletions

View File

@@ -75,6 +75,7 @@ S(SmartDashboardMissingKey, -43, "SmartDashboard data does not exist");
S(CommandIllegalUse, -50, "Illegal use of Command");
S(UnsupportedInSimulation, -80, "Unsupported in simulation");
S(CameraServerError, -90, "CameraServer error");
S(InvalidParameter, -100, "Invalid parameter value");
// Warnings
S(SampleRateTooHigh, 1, "Analog module sample rate is too high");

View File

@@ -0,0 +1,53 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "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>
*/
class BuiltInLayouts {
public:
/**
* 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>
*/
static const LayoutType 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>
*/
static const LayoutType kGrid;
};
} // namespace frc

View File

@@ -0,0 +1,387 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "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.
*/
class BuiltInWidgets {
public:
/**
* 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.
*/
static const WidgetType 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>
*/
static const WidgetType 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>
*/
static const WidgetType 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>
*/
static const WidgetType 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>
*/
static const WidgetType 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>
*/
static const WidgetType 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.
*/
static const WidgetType 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.
*/
static const WidgetType kToggleSwitch;
/**
* Displays an analog input or a raw number with a number bar.
* <br>Supported types:
* <ul>
* <li>Number</li>
* <li>{@link edu.wpi.first.wpilibj.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>
*/
static const WidgetType kVoltageView;
/**
* Displays a {@link edu.wpi.first.wpilibj.PowerDistributionPanel
* PowerDistributionPanel}. <br>Supported types: <ul> <li>{@link
* edu.wpi.first.wpilibj.PowerDistributionPanel}</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>
*/
static const WidgetType kPowerDistributionPanel;
/**
* Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser
* SendableChooser} with a dropdown combo box with a list of options.
* <br>Supported types:
* <ul>
* <li>{@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType kComboBoxChooser;
/**
* Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser
* SendableChooser} with a toggle button for each available option.
* <br>Supported types:
* <ul>
* <li>{@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType kSplitButtonChooser;
/**
* Displays an {@link edu.wpi.first.wpilibj.Encoder} displaying its speed,
* total travelled distance, and its distance per tick. <br>Supported types:
* <ul>
* <li>{@link edu.wpi.first.wpilibj.Encoder}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType kEncoder;
/**
* Displays a {@link edu.wpi.first.wpilibj.SpeedController SpeedController}.
* The speed controller will be controllable from the dashboard when test mode
* is enabled, but will otherwise be view-only. <br>Supported types: <ul>
* <li>{@link edu.wpi.first.wpilibj.PWMSpeedController}</li>
* <li>{@link edu.wpi.first.wpilibj.DMC60}</li>
* <li>{@link edu.wpi.first.wpilibj.Jaguar}</li>
* <li>{@link edu.wpi.first.wpilibj.PWMTalonSRX}</li>
* <li>{@link edu.wpi.first.wpilibj.PWMVictorSPX}</li>
* <li>{@link edu.wpi.first.wpilibj.SD540}</li>
* <li>{@link edu.wpi.first.wpilibj.Spark}</li>
* <li>{@link edu.wpi.first.wpilibj.Talon}</li>
* <li>{@link edu.wpi.first.wpilibj.Victor}</li>
* <li>{@link edu.wpi.first.wpilibj.VictorSP}</li>
* <li>{@link edu.wpi.first.wpilibj.SpeedControllerGroup}</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>
*/
static const WidgetType kSpeedController;
/**
* 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>{@link
* edu.wpi.first.wpilibj.command.Command}</li> <li>{@link
* edu.wpi.first.wpilibj.command.CommandGroup}</li> <li>Any custom subclass of
* {@code Command} or {@code CommandGroup}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType 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>{@link edu.wpi.first.wpilibj.command.PIDCommand}</li>
* <li>Any custom subclass of {@code PIDCommand}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType 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>{@link edu.wpi.first.wpilibj.PIDController}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType 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>{@link edu.wpi.first.wpilibj.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>
*/
static const WidgetType kAccelerometer;
/**
* Displays a 3-axis accelerometer with a number bar for each axis'
* accleration. <br>Supported types: <ul> <li>{@link
* edu.wpi.first.wpilibj.ADXL345_I2C}</li> <li>{@link
* edu.wpi.first.wpilibj.ADXL345_SPI}</li> <li>{@link
* edu.wpi.first.wpilibj.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>{@link 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>
*/
static const WidgetType k3AxisAccelerometer;
/**
* Displays a gyro with a dial from 0 to 360 degrees.
* <br>Supported types:
* <ul>
* <li>{@link edu.wpi.first.wpilibj.ADXRS450_Gyro}</li>
* <li>{@link edu.wpi.first.wpilibj.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>
*/
static const WidgetType kGyro;
/**
* Displays a relay with toggle buttons for each supported mode (off, on,
* forward, reverse). <br>Supported types: <ul> <li>{@link
* edu.wpi.first.wpilibj.Relay}</li>
* </ul>
* <br>This widget has no custom properties.
*/
static const WidgetType 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>{@link edu.wpi.first.wpilibj.drive.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>
*/
static const WidgetType 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>{@link edu.wpi.first.wpilibj.drive.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>
*/
static const WidgetType kMecanumDrive;
/**
* Displays a camera stream.
* <br>Supported types:
* <ul>
* <li>{@link edu.wpi.cscore.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>
*/
static const WidgetType kCameraStream;
};
} // namespace frc

View File

@@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
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 LayoutType(const char* layoutName) : m_layoutName(layoutName) {}
~LayoutType() = default;
/**
* Gets the string type of the layout as defined by that layout in
* Shuffleboard.
*/
wpi::StringRef GetLayoutName() const;
private:
wpi::StringRef m_layoutName;
};
} // namespace frc

View File

@@ -18,6 +18,9 @@
#include <wpi/StringMap.h>
#include <wpi/Twine.h>
#include "frc/ErrorBase.h"
#include "frc/WPIErrors.h"
#include "frc/shuffleboard/LayoutType.h"
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
#include "frc/shuffleboard/ShuffleboardValue.h"
@@ -31,7 +34,8 @@ class SimpleWidget;
/**
* Common interface for objects that can contain shuffleboard components.
*/
class ShuffleboardContainer : public virtual ShuffleboardValue {
class ShuffleboardContainer : public virtual ShuffleboardValue,
public ErrorBase {
public:
explicit ShuffleboardContainer(const wpi::Twine& title);
@@ -49,12 +53,45 @@ class ShuffleboardContainer : public virtual ShuffleboardValue {
* 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 type the type of the layout, eg "List" or "Grid"
* @param title the title of the layout
* @param title the title of the layout
* @param layoutType the type of the layout, eg "List" or "Grid"
* @return the layout
*/
ShuffleboardLayout& GetLayout(const wpi::Twine& type,
const wpi::Twine& title);
ShuffleboardLayout& GetLayout(const wpi::Twine& 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
* {@link #GetLayout(String, LayoutType)} and the layouts in {@link
* 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(String, LayoutType)
*/
ShuffleboardLayout& GetLayout(const wpi::Twine& title,
const wpi::Twine& 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(const wpi::Twine& title);
/**
* Adds a widget to this container to display the given sendable.

View File

@@ -10,6 +10,7 @@
#include <wpi/Twine.h>
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/WidgetType.h"
namespace frc {
@@ -36,6 +37,22 @@ class ShuffleboardWidget
*
* @param widgetType the type of the widget used to display the data
* @return this widget object
* @see BuiltInWidgets
*/
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 thrid-party plugin). To use a widget that is built into
* Shuffleboard, use {@link #withWidget(WidgetType)} and {@link
* BuiltInWidgets}.
*
* @param widgetType the type of the widget used to display the data
* @return this widget object
*/
Derived& WithWidget(const wpi::Twine& widgetType) {
this->SetType(widgetType);

View File

@@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <wpi/Twine.h>
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 WidgetType(const char* widgetName) : m_widgetName(widgetName) {}
~WidgetType() = default;
/**
* Gets the string type of the widget as defined by that widget in
* Shuffleboard.
*/
wpi::StringRef GetWidgetName() const;
private:
wpi::StringRef m_widgetName;
};
} // namespace frc