From e8b24717c76098e162a87e18f0393dc30c83e214 Mon Sep 17 00:00:00 2001 From: Sam Carlberg Date: Thu, 14 Feb 2019 23:44:30 -0500 Subject: [PATCH] C++ Shuffleboard fixes (#1595) * Fix C++ ShuffleboardComponent template type * Fix `WithWidget(WidgetType&)`not being properly capitalized * Fix data members across dll boundaries by using enum for built in types --- wpilibc/src/main/native/cpp/Watchdog.cpp | 2 +- .../cpp/shuffleboard/BuiltInLayouts.cpp | 13 ---- .../cpp/shuffleboard/BuiltInWidgets.cpp | 35 ---------- .../shuffleboard/ShuffleboardContainer.cpp | 11 ++++ .../cpp/shuffleboard/ShuffleboardWidget.cpp | 41 ++++++++++++ .../include/frc/shuffleboard/BuiltInLayouts.h | 7 +- .../include/frc/shuffleboard/BuiltInWidgets.h | 51 +++++++-------- .../include/frc/shuffleboard/LayoutType.h | 7 +- .../frc/shuffleboard/ShuffleboardContainer.h | 11 ++++ .../frc/shuffleboard/ShuffleboardWidget.h | 23 +++++-- .../include/frc/shuffleboard/WidgetType.h | 7 +- .../shuffleboard/ShuffleboardWidgetTest.cpp | 65 +++++++++++++++++++ 12 files changed, 184 insertions(+), 89 deletions(-) delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp create mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp create mode 100644 wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardWidgetTest.cpp diff --git a/wpilibc/src/main/native/cpp/Watchdog.cpp b/wpilibc/src/main/native/cpp/Watchdog.cpp index 043abac0035..f7c1778b0ef 100644 --- a/wpilibc/src/main/native/cpp/Watchdog.cpp +++ b/wpilibc/src/main/native/cpp/Watchdog.cpp @@ -18,7 +18,7 @@ constexpr std::chrono::milliseconds Watchdog::kMinPrintPeriod; class Watchdog::Thread : public wpi::SafeThread { public: template - struct DerefGreater : public std::binary_function { + struct DerefGreater { constexpr bool operator()(const T& lhs, const T& rhs) const { return *lhs > *rhs; } diff --git a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp deleted file mode 100644 index 5d09310318a..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInLayouts.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* 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. */ -/*----------------------------------------------------------------------------*/ - -#include "frc/shuffleboard/BuiltInLayouts.h" - -using namespace frc; - -const LayoutType BuiltInLayouts::kList{"List Layout"}; -const LayoutType BuiltInLayouts::kGrid{"Grid Layout"}; diff --git a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp b/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp deleted file mode 100644 index df6a1f3334c..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/BuiltInWidgets.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* 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. */ -/*----------------------------------------------------------------------------*/ - -#include "frc/shuffleboard/BuiltInWidgets.h" - -using namespace frc; - -const WidgetType BuiltInWidgets::kTextView{"Text View"}; -const WidgetType BuiltInWidgets::kNumberSlider{"Number Slider"}; -const WidgetType BuiltInWidgets::kNumberBar{"Number Bar"}; -const WidgetType BuiltInWidgets::kDial{"Simple Dial"}; -const WidgetType BuiltInWidgets::kGraph{"Graph"}; -const WidgetType BuiltInWidgets::kBooleanBox{"Boolean Box"}; -const WidgetType BuiltInWidgets::kToggleButton{"Toggle Button"}; -const WidgetType BuiltInWidgets::kToggleSwitch{"Toggle Switch"}; -const WidgetType BuiltInWidgets::kVoltageView{"Voltage View"}; -const WidgetType BuiltInWidgets::kPowerDistributionPanel{"PDP"}; -const WidgetType BuiltInWidgets::kComboBoxChooser{"ComboBox Chooser"}; -const WidgetType BuiltInWidgets::kSplitButtonChooser{"Split Button Chooser"}; -const WidgetType BuiltInWidgets::kEncoder{"Encoder"}; -const WidgetType BuiltInWidgets::kSpeedController{"Speed Controller"}; -const WidgetType BuiltInWidgets::kCommand{"Command"}; -const WidgetType BuiltInWidgets::kPIDCommand{"PID Command"}; -const WidgetType BuiltInWidgets::kPIDController{"PID Controller"}; -const WidgetType BuiltInWidgets::kAccelerometer{"Accelerometer"}; -const WidgetType BuiltInWidgets::k3AxisAccelerometer{"3-Axis Accelerometer"}; -const WidgetType BuiltInWidgets::kGyro{"Gyro"}; -const WidgetType BuiltInWidgets::kRelay{"Relay"}; -const WidgetType BuiltInWidgets::kDifferentialDrive{"Differential Drivebase"}; -const WidgetType BuiltInWidgets::kMecanumDrive{"Mecanum Drivebase"}; -const WidgetType BuiltInWidgets::kCameraStream{"Camera Stream"}; diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp index 4954cff4e98..f13116d1846 100644 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp +++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp @@ -18,6 +18,12 @@ using namespace frc; +static constexpr const char* layoutStrings[] = {"List Layout", "Grid Layout"}; + +static constexpr const char* GetStringFromBuiltInLayout(BuiltInLayouts layout) { + return layoutStrings[static_cast(layout)]; +} + ShuffleboardContainer::ShuffleboardContainer(const wpi::Twine& title) : ShuffleboardValue(title) {} @@ -26,6 +32,11 @@ ShuffleboardContainer::GetComponents() const { return m_components; } +ShuffleboardLayout& ShuffleboardContainer::GetLayout(const wpi::Twine& title, + BuiltInLayouts type) { + return GetLayout(title, GetStringFromBuiltInLayout(type)); +} + ShuffleboardLayout& ShuffleboardContainer::GetLayout(const wpi::Twine& title, const LayoutType& type) { return GetLayout(title, type.GetLayoutName()); diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp new file mode 100644 index 00000000000..4573516668b --- /dev/null +++ b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp @@ -0,0 +1,41 @@ +/*----------------------------------------------------------------------------*/ +/* 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. */ +/*----------------------------------------------------------------------------*/ + +#include "frc/shuffleboard/ShuffleboardWidget.h" + +using namespace frc; + +static constexpr const char* widgetStrings[] = { + "Text View", + "Number Slider", + "Number Bar", + "Simple Dial", + "Graph", + "Boolean Box", + "Toggle Button", + "Toggle Switch", + "Voltage View", + "PDP", + "ComboBox Chooser", + "Split Button Chooser", + "Encoder", + "Speed Controller", + "Command", + "PID Command", + "PID Controller", + "Accelerometer", + "3-Axis Accelerometer", + "Gyro", + "Relay", + "Differential Drivebase", + "Mecanum Drivebase", + "Camera Stream", +}; + +const char* detail::GetStringForWidgetType(BuiltInWidgets type) { + return widgetStrings[static_cast(type)]; +} diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h index 6a61b870ba5..c958baafc51 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h @@ -19,8 +19,7 @@ namespace frc { * .GetLayout(BuiltinLayouts::kList, "My List"); * } */ -class BuiltInLayouts { - public: +enum class BuiltInLayouts { /** * Groups components in a vertical list. New widgets added to the layout will * be placed at the bottom of the list.
Custom properties: @@ -30,7 +29,7 @@ class BuiltInLayouts { * {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"} *
*/ - static const LayoutType kList; + kList, /** * Groups components in an n x m grid. Grid layouts default to @@ -47,7 +46,7 @@ class BuiltInLayouts { * * */ - static const LayoutType kGrid; + kGrid }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h index 1fd720fbda3..bdd201158b9 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h @@ -25,8 +25,7 @@ namespace frc { *

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: +enum class BuiltInWidgets { /** * Displays a value with a simple text field. *
Supported types: @@ -37,7 +36,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kTextView; + kTextView, /** * Displays a number with a controllable slider. *
Supported types: @@ -54,7 +53,7 @@ class BuiltInWidgets { * slider by with the arrow keys * */ - static const WidgetType kNumberSlider; + kNumberSlider, /** * Displays a number with a view-only bar. *
Supported types: @@ -71,7 +70,7 @@ class BuiltInWidgets { * of the bar * */ - static const WidgetType kNumberBar; + kNumberBar, /** * Displays a number with a view-only dial. Displayed values are rounded to * the nearest integer.
Supported types:

  • Number
  • @@ -86,7 +85,7 @@ class BuiltInWidgets { * value as text * */ - static const WidgetType kDial; + kDial, /** * Displays a number with a graph. NOTE: graphs can be taxing * on the computer running the dashboard. Keep the number of visible data @@ -103,7 +102,7 @@ class BuiltInWidgets { * How long, in seconds, should past data be visible for * */ - static const WidgetType kGraph; + kGraph, /** * Displays a boolean value as a large colored box. *
    Supported types: @@ -121,7 +120,7 @@ class BuiltInWidgets { * Can be specified as a string or a number * */ - static const WidgetType kBooleanBox; + kBooleanBox, /** * Displays a boolean with a large interactive toggle button. *
    Supported types: @@ -130,7 +129,7 @@ class BuiltInWidgets { *
*
This widget has no custom properties. */ - static const WidgetType kToggleButton; + kToggleButton, /** * Displays a boolean with a fixed-size toggle switch. *
Supported types: @@ -139,7 +138,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kToggleSwitch; + kToggleSwitch, /** * Displays an analog input or a raw number with a number bar. *
Supported types: @@ -162,7 +161,7 @@ class BuiltInWidgets { * bar * */ - static const WidgetType kVoltageView; + kVoltageView, /** * Displays a {@link edu.wpi.first.wpilibj.PowerDistributionPanel * PowerDistributionPanel}.
Supported types:
  • {@link @@ -175,7 +174,7 @@ class BuiltInWidgets { * Whether or not to display the voltage and current draw * */ - static const WidgetType kPowerDistributionPanel; + kPowerDistributionPanel, /** * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser * SendableChooser} with a dropdown combo box with a list of options. @@ -185,7 +184,7 @@ class BuiltInWidgets { *
*
This widget has no custom properties. */ - static const WidgetType kComboBoxChooser; + kComboBoxChooser, /** * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser * SendableChooser} with a toggle button for each available option. @@ -195,7 +194,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kSplitButtonChooser; + kSplitButtonChooser, /** * Displays an {@link edu.wpi.first.wpilibj.Encoder} displaying its speed, * total travelled distance, and its distance per tick.
Supported types: @@ -204,7 +203,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kEncoder; + kEncoder, /** * Displays a {@link edu.wpi.first.wpilibj.SpeedController SpeedController}. * The speed controller will be controllable from the dashboard when test mode @@ -228,7 +227,7 @@ class BuiltInWidgets { * One of {@code ["HORIZONTAL", "VERTICAL"]} * */ - static const WidgetType kSpeedController; + kSpeedController, /** * Displays a command with a toggle button. Pressing the button will start the * command, and the button will automatically release when the command @@ -239,7 +238,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kCommand; + 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 @@ -249,7 +248,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kPIDCommand; + kPIDCommand, /** * Displays a PID controller with an editor for the PIDF constants and a * toggle switch for enabling and disabling the controller.
Supported @@ -257,7 +256,7 @@ class BuiltInWidgets { * *
This widget has no custom properties. */ - static const WidgetType kPIDController; + kPIDController, /** * Displays an accelerometer with a number bar displaying the magnitude of the * acceleration and text displaying the exact value.
Supported types:
    @@ -278,7 +277,7 @@ class BuiltInWidgets { * Show or hide the tick marks on the number bars * */ - static const WidgetType kAccelerometer; + kAccelerometer, /** * Displays a 3-axis accelerometer with a number bar for each axis' * accleration.
    Supported types:
    • {@link @@ -298,7 +297,7 @@ class BuiltInWidgets { * Show or hide the tick marks on the number bars * */ - static const WidgetType k3AxisAccelerometer; + k3AxisAccelerometer, /** * Displays a gyro with a dial from 0 to 360 degrees. *
      Supported types: @@ -317,7 +316,7 @@ class BuiltInWidgets { * Show tick mark ringBooleantrue * */ - static const WidgetType kGyro; + kGyro, /** * Displays a relay with toggle buttons for each supported mode (off, on, * forward, reverse).
      Supported types:
      • {@link @@ -325,7 +324,7 @@ class BuiltInWidgets { *
      *
      This widget has no custom properties. */ - static const WidgetType kRelay; + 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 @@ -344,7 +343,7 @@ class BuiltInWidgets { * Show velocity vectorsBooleantrue * */ - static const WidgetType kDifferentialDrive; + 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 @@ -357,7 +356,7 @@ class BuiltInWidgets { * Show velocity vectorsBooleantrue * */ - static const WidgetType kMecanumDrive; + kMecanumDrive, /** * Displays a camera stream. *
      Supported types: @@ -381,7 +380,7 @@ class BuiltInWidgets { * * */ - static const WidgetType kCameraStream; + kCameraStream }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h b/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h index 22fe3617047..50e448b2d55 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace frc { @@ -20,7 +20,8 @@ namespace frc { */ class LayoutType { public: - explicit LayoutType(const char* layoutName) : m_layoutName(layoutName) {} + explicit constexpr LayoutType(const char* layoutName) + : m_layoutName(layoutName) {} ~LayoutType() = default; /** @@ -30,7 +31,7 @@ class LayoutType { wpi::StringRef GetLayoutName() const; private: - wpi::StringRef m_layoutName; + const char* m_layoutName; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h index e53bcfc3098..ab0309953af 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h @@ -20,6 +20,7 @@ #include "frc/ErrorBase.h" #include "frc/WPIErrors.h" +#include "frc/shuffleboard/BuiltInLayouts.h" #include "frc/shuffleboard/LayoutType.h" #include "frc/shuffleboard/ShuffleboardComponentBase.h" #include "frc/shuffleboard/ShuffleboardValue.h" @@ -53,6 +54,16 @@ class ShuffleboardContainer : public virtual ShuffleboardValue, const std::vector>& 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 layoutType the type of the layout, eg "List" or "Grid" + * @return the layout + */ + ShuffleboardLayout& GetLayout(const wpi::Twine& 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. diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h index 2e67160d3fc..3b1b0a8aea5 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h @@ -9,6 +9,7 @@ #include +#include "frc/shuffleboard/BuiltInWidgets.h" #include "frc/shuffleboard/ShuffleboardComponent.h" #include "frc/shuffleboard/WidgetType.h" @@ -16,6 +17,10 @@ namespace frc { class ShuffleboardContainer; +namespace detail { +const char* GetStringForWidgetType(BuiltInWidgets type); +} // namespace detail + /** * Abstract superclass for widgets. * @@ -24,12 +29,11 @@ class ShuffleboardContainer; * @tparam Derived the self type */ template -class ShuffleboardWidget - : public ShuffleboardComponent> { +class ShuffleboardWidget : public ShuffleboardComponent { public: ShuffleboardWidget(ShuffleboardContainer& parent, const wpi::Twine& title) : ShuffleboardValue(title), - ShuffleboardComponent>(parent, title) {} + ShuffleboardComponent(parent, title) {} /** * Sets the type of widget used to display the data. If not set, the default @@ -39,7 +43,18 @@ class ShuffleboardWidget * @return this widget object * @see BuiltInWidgets */ - Derived& withWidget(const WidgetType& widgetType) { + 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()); } diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h b/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h index f96e9b60e4e..057d594a18d 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h @@ -7,7 +7,7 @@ #pragma once -#include +#include namespace frc { @@ -20,7 +20,8 @@ namespace frc { */ class WidgetType { public: - explicit WidgetType(const char* widgetName) : m_widgetName(widgetName) {} + explicit constexpr WidgetType(const char* widgetName) + : m_widgetName(widgetName) {} ~WidgetType() = default; /** @@ -30,7 +31,7 @@ class WidgetType { wpi::StringRef GetWidgetName() const; private: - wpi::StringRef m_widgetName; + const char* m_widgetName; }; } // namespace frc diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardWidgetTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardWidgetTest.cpp new file mode 100644 index 00000000000..3dd9dbf790c --- /dev/null +++ b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardWidgetTest.cpp @@ -0,0 +1,65 @@ +/*----------------------------------------------------------------------------*/ +/* 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. */ +/*----------------------------------------------------------------------------*/ + +#include +#include +#include + +#include +#include + +#include "frc/commands/InstantCommand.h" +#include "frc/shuffleboard/BuiltInWidgets.h" +#include "frc/shuffleboard/ShuffleboardInstance.h" +#include "frc/shuffleboard/ShuffleboardTab.h" +#include "frc/shuffleboard/ShuffleboardWidget.h" +#include "frc/smartdashboard/Sendable.h" +#include "gtest/gtest.h" + +using namespace frc; + +class ShuffleboardWidgetTest : public testing::Test { + void SetUp() override { + m_ntInstance = nt::NetworkTableInstance::Create(); + m_instance = std::make_unique(m_ntInstance); + m_tab = &(m_instance->GetTab("Tab")); + } + + protected: + nt::NetworkTableInstance m_ntInstance; + ShuffleboardTab* m_tab; + std::unique_ptr m_instance; +}; + +TEST_F(ShuffleboardWidgetTest, UseBuiltInWidget) { + auto entry = + m_tab->Add("Name", "").WithWidget(BuiltInWidgets::kTextView).GetEntry(); + EXPECT_EQ("/Shuffleboard/Tab/Name", entry.GetName()) + << "The widget entry has the wrong name"; +} + +TEST_F(ShuffleboardWidgetTest, WithProperties) { + wpi::StringMap> properties{ + std::make_pair("min", nt::Value::MakeDouble(0)), + std::make_pair("max", nt::Value::MakeDouble(1))}; + auto entry = + m_tab->Add("WithProperties", "").WithProperties(properties).GetEntry(); + + // Update the instance to generate + // the metadata entries for the widget properties + m_instance->Update(); + + auto propertiesTable = m_ntInstance.GetTable( + "/Shuffleboard/.metadata/Tab/WithProperties/Properties"); + + EXPECT_EQ("/Shuffleboard/Tab/WithProperties", entry.GetName()) + << "The widget entry has the wrong name"; + EXPECT_FLOAT_EQ(0, propertiesTable->GetEntry("min").GetDouble(-1)) + << "The 'min' property should be 0"; + EXPECT_FLOAT_EQ(1, propertiesTable->GetEntry("max").GetDouble(-1)) + << "The 'max' property should be 1"; +}