001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.wpilibj.shuffleboard;
006
007import edu.wpi.first.cscore.VideoSource;
008import edu.wpi.first.util.sendable.Sendable;
009import java.util.List;
010import java.util.NoSuchElementException;
011import java.util.function.BooleanSupplier;
012import java.util.function.DoubleSupplier;
013import java.util.function.Supplier;
014
015/** Common interface for objects that can contain shuffleboard components. */
016public interface ShuffleboardContainer extends ShuffleboardValue {
017  /**
018   * Gets the components that are direct children of this container.
019   *
020   * @return The components that are direct children of this container.
021   */
022  List<ShuffleboardComponent<?>> getComponents();
023
024  /**
025   * Gets the layout with the given type and title, creating it if it does not already exist at the
026   * time this method is called. Note: this method should only be used to use a layout type that is
027   * not already built into Shuffleboard. To use a layout built into Shuffleboard, use {@link
028   * #getLayout(String, LayoutType)} and the layouts in {@link BuiltInLayouts}.
029   *
030   * @param title the title of the layout
031   * @param type the type of the layout, eg "List Layout" or "Grid Layout"
032   * @return the layout
033   * @see #getLayout(String, LayoutType)
034   */
035  ShuffleboardLayout getLayout(String title, String type);
036
037  /**
038   * Gets the layout with the given type and title, creating it if it does not already exist at the
039   * time this method is called.
040   *
041   * @param title the title of the layout
042   * @param layoutType the type of the layout, eg "List" or "Grid"
043   * @return the layout
044   */
045  default ShuffleboardLayout getLayout(String title, LayoutType layoutType) {
046    return getLayout(title, layoutType.getLayoutName());
047  }
048
049  /**
050   * Gets the already-defined layout in this container with the given title.
051   *
052   * <pre>{@code
053   * Shuffleboard.getTab("Example Tab")
054   *   .getLayout("My Layout", BuiltInLayouts.kList);
055   *
056   * // Later...
057   * Shuffleboard.getTab("Example Tab")
058   *   .getLayout("My Layout");
059   * }</pre>
060   *
061   * @param title the title of the layout to get
062   * @return the layout with the given title
063   * @throws NoSuchElementException if no layout has yet been defined with the given title
064   */
065  ShuffleboardLayout getLayout(String title);
066
067  /**
068   * Adds a widget to this container to display the given sendable.
069   *
070   * @param title the title of the widget
071   * @param sendable the sendable to display
072   * @return a widget to display the sendable data
073   * @throws IllegalArgumentException if a widget already exists in this container with the given
074   *     title
075   */
076  ComplexWidget add(String title, Sendable sendable);
077
078  /**
079   * Adds a widget to this container to display the given video stream.
080   *
081   * @param title the title of the widget
082   * @param video the video stream to display
083   * @return a widget to display the sendable data
084   * @throws IllegalArgumentException if a widget already exists in this container with the given
085   *     title
086   */
087  default ComplexWidget add(String title, VideoSource video) {
088    return add(title, SendableCameraWrapper.wrap(video));
089  }
090
091  /**
092   * Adds a widget to this container to display the given sendable.
093   *
094   * @param sendable the sendable to display
095   * @return a widget to display the sendable data
096   * @throws IllegalArgumentException if a widget already exists in this container with the given
097   *     title, or if the sendable's name has not been specified
098   */
099  ComplexWidget add(Sendable sendable);
100
101  /**
102   * Adds a widget to this container to display the given video stream.
103   *
104   * @param video the video to display
105   * @return a widget to display the sendable data
106   * @throws IllegalArgumentException if a widget already exists in this container with the same
107   *     title as the video source
108   */
109  default ComplexWidget add(VideoSource video) {
110    return add(SendableCameraWrapper.wrap(video));
111  }
112
113  /**
114   * Adds a widget to this container to display the given data.
115   *
116   * @param title the title of the widget
117   * @param defaultValue the default value of the widget
118   * @return a widget to display the sendable data
119   * @throws IllegalArgumentException if a widget already exists in this container with the given
120   *     title
121   * @see #addPersistent(String, Object) add(String title, Object defaultValue)
122   */
123  SimpleWidget add(String title, Object defaultValue);
124
125  /**
126   * Adds a widget to this container to display a video stream.
127   *
128   * @param title the title of the widget
129   * @param cameraName the name of the streamed camera
130   * @param cameraUrls the URLs with which the dashboard can access the camera stream
131   * @return a widget to display the camera stream
132   * @throws IllegalArgumentException if a widget already exists in this container with the given
133   *     title
134   */
135  default ComplexWidget addCamera(String title, String cameraName, String... cameraUrls) {
136    return add(title, SendableCameraWrapper.wrap(cameraName, cameraUrls));
137  }
138
139  /**
140   * Adds a widget to this container. The widget will display the data provided by the value
141   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
142   * overridden by values from the value supplier.
143   *
144   * @param title the title of the widget
145   * @param valueSupplier the supplier for values
146   * @return a widget to display data
147   * @throws IllegalArgumentException if a widget already exists in this container with the given
148   *     title
149   */
150  SuppliedValueWidget<String> addString(String title, Supplier<String> valueSupplier);
151
152  /**
153   * Adds a widget to this container. The widget will display the data provided by the value
154   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
155   * overridden by values from the value supplier.
156   *
157   * @param title the title of the widget
158   * @param valueSupplier the supplier for values
159   * @return a widget to display data
160   * @throws IllegalArgumentException if a widget already exists in this container with the given
161   *     title
162   */
163  SuppliedValueWidget<Double> addNumber(String title, DoubleSupplier valueSupplier);
164
165  /**
166   * Adds a widget to this container. The widget will display the data provided by the value
167   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
168   * overridden by values from the value supplier.
169   *
170   * @param title the title of the widget
171   * @param valueSupplier the supplier for values
172   * @return a widget to display data
173   * @throws IllegalArgumentException if a widget already exists in this container with the given
174   *     title
175   */
176  SuppliedValueWidget<Boolean> addBoolean(String title, BooleanSupplier valueSupplier);
177
178  /**
179   * Adds a widget to this container. The widget will display the data provided by the value
180   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
181   * overridden by values from the value supplier.
182   *
183   * @param title the title of the widget
184   * @param valueSupplier the supplier for values
185   * @return a widget to display data
186   * @throws IllegalArgumentException if a widget already exists in this container with the given
187   *     title
188   */
189  SuppliedValueWidget<String[]> addStringArray(String title, Supplier<String[]> valueSupplier);
190
191  /**
192   * Adds a widget to this container. The widget will display the data provided by the value
193   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
194   * overridden by values from the value supplier.
195   *
196   * @param title the title of the widget
197   * @param valueSupplier the supplier for values
198   * @return a widget to display data
199   * @throws IllegalArgumentException if a widget already exists in this container with the given
200   *     title
201   */
202  SuppliedValueWidget<double[]> addDoubleArray(String title, Supplier<double[]> valueSupplier);
203
204  /**
205   * Adds a widget to this container. The widget will display the data provided by the value
206   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
207   * overridden by values from the value supplier.
208   *
209   * @param title the title of the widget
210   * @param valueSupplier the supplier for values
211   * @return a widget to display data
212   * @throws IllegalArgumentException if a widget already exists in this container with the given
213   *     title
214   */
215  SuppliedValueWidget<boolean[]> addBooleanArray(String title, Supplier<boolean[]> valueSupplier);
216
217  /**
218   * Adds a widget to this container. The widget will display the data provided by the value
219   * supplier. Changes made on the dashboard will not propagate to the widget object, and will be
220   * overridden by values from the value supplier.
221   *
222   * @param title the title of the widget
223   * @param valueSupplier the supplier for values
224   * @return a widget to display data
225   * @throws IllegalArgumentException if a widget already exists in this container with the given
226   *     title
227   */
228  SuppliedValueWidget<byte[]> addRaw(String title, Supplier<byte[]> valueSupplier);
229
230  /**
231   * Adds a widget to this container to display a simple piece of data. Unlike {@link #add(String,
232   * Object)}, the value in the widget will be saved on the robot and will be used when the robot
233   * program next starts rather than {@code defaultValue}.
234   *
235   * @param title the title of the widget
236   * @param defaultValue the default value of the widget
237   * @return a widget to display the sendable data
238   * @throws IllegalArgumentException if a widget already exists in this container with the given
239   *     title
240   * @see #add(String, Object) add(String title, Object defaultValue)
241   */
242  default SimpleWidget addPersistent(String title, Object defaultValue) {
243    SimpleWidget widget = add(title, defaultValue);
244    widget.getEntry().setPersistent();
245    return widget;
246  }
247}