Skip to content

Commit aa34aac

Browse files
authored
[wpilib] Shuffleboard: Keep duplicates on SelectTab() (#5198)
1 parent 63512bb commit aa34aac

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed

wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ struct ShuffleboardInstance::Impl {
2020
bool tabsChanged = false;
2121
std::shared_ptr<nt::NetworkTable> rootTable;
2222
std::shared_ptr<nt::NetworkTable> rootMetaTable;
23+
nt::StringPublisher selectedTabPub;
2324
};
2425

2526
ShuffleboardInstance::ShuffleboardInstance(nt::NetworkTableInstance ntInstance)
2627
: m_impl(new Impl) {
2728
m_impl->rootTable = ntInstance.GetTable(Shuffleboard::kBaseTableName);
2829
m_impl->rootMetaTable = m_impl->rootTable->GetSubTable(".metadata");
30+
m_impl->selectedTabPub =
31+
m_impl->rootMetaTable->GetStringTopic("Selected")
32+
.Publish(nt::PubSubOptions{.keepDuplicates = true});
2933
HAL_Report(HALUsageReporting::kResourceType_Shuffleboard, 0);
3034
}
3135

@@ -75,9 +79,9 @@ void ShuffleboardInstance::DisableActuatorWidgets() {
7579
}
7680

7781
void ShuffleboardInstance::SelectTab(int index) {
78-
m_impl->rootMetaTable->GetEntry("Selected").SetDouble(index);
82+
m_impl->selectedTabPub.Set(std::to_string(index));
7983
}
8084

8185
void ShuffleboardInstance::SelectTab(std::string_view title) {
82-
m_impl->rootMetaTable->GetEntry("Selected").SetString(title);
86+
m_impl->selectedTabPub.Set(title);
8387
}

wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <string_view>
88

99
#include <networktables/NetworkTableInstance.h>
10+
#include <networktables/NetworkTableListener.h>
11+
#include <networktables/StringTopic.h>
1012

1113
#include "frc/shuffleboard/ShuffleboardInstance.h"
1214
#include "gtest/gtest.h"
@@ -106,3 +108,22 @@ TEST(ShuffleboardInstanceTest, NestedActuatorWidgetsAreDisabled) {
106108
EXPECT_FALSE(controllable)
107109
<< "The nested actuator widget should have been disabled";
108110
}
111+
112+
TEST(ShuffleboardInstanceTest, DuplicateSelectTabs) {
113+
NTWrapper ntInst;
114+
frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst};
115+
std::atomic_int counter = 0;
116+
auto listener = nt::NetworkTableListener::CreateListener(
117+
ntInst.inst.GetStringTopic("/Shuffleboard/.metadata/Selected"),
118+
nt::EventFlags::kValueAll | nt::EventFlags::kImmediate,
119+
[&counter](auto& event) { counter++; });
120+
121+
// There shouldn't be anything there
122+
EXPECT_EQ(0, counter);
123+
124+
shuffleboardInst.SelectTab("tab1");
125+
shuffleboardInst.SelectTab("tab1");
126+
EXPECT_TRUE(ntInst.inst.WaitForListenerQueue(0.005))
127+
<< "Listener queue timed out!";
128+
EXPECT_EQ(2, counter);
129+
}

wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstance.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import edu.wpi.first.hal.HAL;
1111
import edu.wpi.first.networktables.NetworkTable;
1212
import edu.wpi.first.networktables.NetworkTableInstance;
13+
import edu.wpi.first.networktables.PubSubOption;
1314
import edu.wpi.first.networktables.StringPublisher;
1415
import java.util.LinkedHashMap;
1516
import java.util.Map;
@@ -32,7 +33,8 @@ final class ShuffleboardInstance implements ShuffleboardRoot {
3233
requireNonNullParam(ntInstance, "ntInstance", "ShuffleboardInstance");
3334
m_rootTable = ntInstance.getTable(Shuffleboard.kBaseTableName);
3435
m_rootMetaTable = m_rootTable.getSubTable(".metadata");
35-
m_selectedTabPub = m_rootMetaTable.getStringTopic("Selected").publish();
36+
m_selectedTabPub =
37+
m_rootMetaTable.getStringTopic("Selected").publish(PubSubOption.keepDuplicates(true));
3638
HAL.report(tResourceType.kResourceType_Shuffleboard, 0);
3739
}
3840

wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstanceTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
import edu.wpi.first.networktables.GenericEntry;
1313
import edu.wpi.first.networktables.NetworkTableEntry;
14+
import edu.wpi.first.networktables.NetworkTableEvent.Kind;
1415
import edu.wpi.first.networktables.NetworkTableInstance;
16+
import java.util.EnumSet;
17+
import java.util.concurrent.atomic.AtomicInteger;
1518
import org.junit.jupiter.api.AfterEach;
1619
import org.junit.jupiter.api.BeforeEach;
1720
import org.junit.jupiter.api.Test;
@@ -121,4 +124,28 @@ void testNestedActuatorWidgetsAreDisabled() {
121124
controllable = controllableEntry.getValue().getBoolean();
122125
assertFalse(controllable, "The nested actuator widget should have been disabled");
123126
}
127+
128+
@Test
129+
void testDuplicateSelectTabs() {
130+
int listener = 0;
131+
AtomicInteger counter = new AtomicInteger();
132+
try {
133+
listener =
134+
m_ntInstance.addListener(
135+
m_ntInstance.getStringTopic("/Shuffleboard/.metadata/Selected"),
136+
EnumSet.of(Kind.kValueAll, Kind.kImmediate),
137+
event -> counter.incrementAndGet());
138+
139+
// There shouldn't be anything there
140+
assertEquals(0, counter.get());
141+
142+
m_shuffleboardInstance.selectTab("tab1");
143+
m_shuffleboardInstance.selectTab("tab1");
144+
assertTrue(m_ntInstance.waitForListenerQueue(0.005), "Listener queue timed out!");
145+
assertEquals(2, counter.get());
146+
147+
} finally {
148+
m_ntInstance.removeListener(listener);
149+
}
150+
}
124151
}

0 commit comments

Comments
 (0)