88import com .skeletonarmy .marrow .prompts .Prompt ;
99
1010import java .util .ArrayList ;
11+ import java .util .HashMap ;
1112import java .util .List ;
13+ import java .util .Map ;
14+ import java .util .function .Supplier ;
1215
1316public class ChoiceMenu {
17+ private final OpMode opMode ;
1418 private final Telemetry telemetry ;
1519 private final MarrowGamepad gamepad1 ;
1620 private final MarrowGamepad gamepad2 ;
1721
18- private final List <PromptResult <?>> promptResults = new ArrayList <>();
22+ private final List <KeyPromptPair <?>> prompts = new ArrayList <>();
23+ private final Map <String , Object > results = new HashMap <>();
24+
1925 private int currentIndex = 0 ;
26+ private double lastOpModeTime = -1 ;
2027
2128 public ChoiceMenu (OpMode opMode , Gamepad gamepad1 , Gamepad gamepad2 ) {
29+ this .opMode = opMode ;
2230 this .telemetry = opMode .telemetry ;
2331 this .gamepad1 = new MarrowGamepad (opMode , gamepad1 );
2432 this .gamepad2 = new MarrowGamepad (opMode , gamepad2 );
2533 }
2634
2735 public ChoiceMenu (OpMode opMode , MarrowGamepad gamepad1 , MarrowGamepad gamepad2 ) {
36+ this .opMode = opMode ;
2837 this .telemetry = opMode .telemetry ;
2938 this .gamepad1 = gamepad1 ;
3039 this .gamepad2 = gamepad2 ;
@@ -33,13 +42,44 @@ public ChoiceMenu(OpMode opMode, MarrowGamepad gamepad1, MarrowGamepad gamepad2)
3342 /**
3443 * Add a prompt to the queue.
3544 */
36- private <T > void enqueuePrompt (Prompt <T > prompt ) {
37- promptResults .add (new PromptResult <>(prompt ));
45+ public <T > void enqueuePrompt (String key , Prompt <T > prompt ) {
46+ prompts .add (new KeyPromptPair <>(key , prompt ));
47+ }
48+
49+ /**
50+ * Add a prompt to the queue.
51+ */
52+ public <T > void enqueuePrompt (String key , Supplier <Prompt <T >> promptSupplier ) {
53+ prompts .add (new KeyPromptPair <>(key , promptSupplier ));
54+ }
55+
56+
57+ /**
58+ * Gets the chosen value of a prompt from its key.
59+ *
60+ * @param key The prompt's key
61+ * @return The value of the prompt result
62+ */
63+ @ SuppressWarnings ("unchecked" )
64+ public <T > T get (String key ) {
65+ return (T ) results .get (key );
66+ }
67+
68+ /**
69+ * Gets the chosen value of a prompt from its key.
70+ *
71+ * @param key The prompt's key
72+ * @param defaultValue A default value if the value doesn't exist
73+ * @return The value of the prompt result
74+ */
75+ @ SuppressWarnings ("unchecked" )
76+ public <T > T getOrDefault (String key , T defaultValue ) {
77+ return (T ) results .getOrDefault (key , defaultValue );
3878 }
3979
4080 /**
4181 * Handles the prompts and inputs. Should be called in a loop.
42- * @return True if there are no more prompts to process
82+ * @return True if there are no more prompts to process, false otherwise
4383 */
4484 private boolean processPrompts () {
4585 // Handle back navigation
@@ -48,49 +88,64 @@ private boolean processPrompts() {
4888 }
4989
5090 // No prompts left
51- if (currentIndex >= promptResults .size ()) {
91+ if (currentIndex >= prompts .size ()) {
5292 return true ;
5393 }
5494
55- PromptResult current = promptResults .get (currentIndex );
56- Object result = current .prompt . process ( gamepad1 , gamepad2 , telemetry );
95+ KeyPromptPair <?> current = prompts .get (currentIndex );
96+ Prompt <?> prompt = current .getPrompt ( );
5797
98+ // Skip if prompt is null
99+ if (prompt == null ) {
100+ currentIndex ++;
101+ return false ;
102+ }
103+
104+ Object result = prompt .process (gamepad1 , gamepad2 , telemetry );
58105 if (result != null ) {
59- current .result = result ;
106+ results . put ( current .getKey (), result ) ;
60107 currentIndex ++;
61108 }
62109
63110 return false ;
64111 }
65112
66- /**
67- * Prompts the user and waits for a result. This will block until the result is chosen.
68- */
69- @ SuppressWarnings ("unchecked" )
70- public <T > T prompt (Prompt <T > prompt ) {
71- enqueuePrompt (prompt );
72-
73- // Process the prompts until a result is selected for the current prompt
74- while (!processPrompts ()) {
75- gamepad1 .update ();
76- gamepad2 .update ();
77- telemetry .update ();
78- telemetry .clearAll ();
79- }
113+ public void run () {
114+ boolean finished = false ;
80115
81- // Return the result of the prompt
82- return (T ) promptResults .get (promptResults .size () - 1 ).result ;
116+ while (!finished ) {
117+ if (opMode .time == lastOpModeTime ) continue ; // Skip if it was already called this frame. This is so it runs only once per loop.
118+
119+ finished = processPrompts ();
120+ lastOpModeTime = opMode .time ;
121+ }
83122 }
84123
85- /**
86- * A helper class to keep prompt and its result together.
87- */
88- private static class PromptResult <T > {
89- public final Prompt <T > prompt ;
90- public T result ;
124+ private static class KeyPromptPair <T > {
125+ private final String key ;
126+ private final Prompt <T > prompt ;
127+ private final Supplier <Prompt <T >> promptSupplier ;
91128
92- public PromptResult (Prompt <T > prompt ) {
129+ public KeyPromptPair (String key , Prompt <T > prompt ) {
130+ this .key = key ;
93131 this .prompt = prompt ;
132+ this .promptSupplier = null ;
133+ }
134+
135+ public KeyPromptPair (String key , Supplier <Prompt <T >> promptSupplier ) {
136+ this .key = key ;
137+ this .prompt = null ;
138+ this .promptSupplier = promptSupplier ;
139+ }
140+
141+ public String getKey () {
142+ return key ;
143+ }
144+
145+ public Prompt <T > getPrompt () {
146+ if (prompt != null ) return prompt ;
147+ if (promptSupplier != null ) return promptSupplier .get ();
148+ return null ;
94149 }
95150 }
96151}
0 commit comments