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.networktables.NetworkTableType; 009import edu.wpi.first.util.function.FloatSupplier; 010import edu.wpi.first.util.sendable.Sendable; 011import java.util.List; 012import java.util.NoSuchElementException; 013import java.util.function.BooleanSupplier; 014import java.util.function.DoubleSupplier; 015import java.util.function.LongSupplier; 016import java.util.function.Supplier; 017 018/** Common interface for objects that can contain shuffleboard components. */ 019public interface ShuffleboardContainer extends ShuffleboardValue { 020 /** 021 * Gets the components that are direct children of this container. 022 * 023 * @return The components that are direct children of this container. 024 */ 025 List<ShuffleboardComponent<?>> getComponents(); 026 027 /** 028 * Gets the layout with the given type and title, creating it if it does not already exist at the 029 * time this method is called. Note: this method should only be used to use a layout type that is 030 * not already built into Shuffleboard. To use a layout built into Shuffleboard, use {@link 031 * #getLayout(String, LayoutType)} and the layouts in {@link BuiltInLayouts}. 032 * 033 * @param title the title of the layout 034 * @param type the type of the layout, eg "List Layout" or "Grid Layout" 035 * @return the layout 036 * @see #getLayout(String, LayoutType) 037 */ 038 ShuffleboardLayout getLayout(String title, String type); 039 040 /** 041 * Gets the layout with the given type and title, creating it if it does not already exist at the 042 * time this method is called. 043 * 044 * @param title the title of the layout 045 * @param layoutType the type of the layout, eg "List" or "Grid" 046 * @return the layout 047 */ 048 default ShuffleboardLayout getLayout(String title, LayoutType layoutType) { 049 return getLayout(title, layoutType.getLayoutName()); 050 } 051 052 /** 053 * Gets the already-defined layout in this container with the given title. 054 * 055 * <pre>{@code 056 * Shuffleboard.getTab("Example Tab") 057 * .getLayout("My Layout", BuiltInLayouts.kList); 058 * 059 * // Later... 060 * Shuffleboard.getTab("Example Tab") 061 * .getLayout("My Layout"); 062 * }</pre> 063 * 064 * @param title the title of the layout to get 065 * @return the layout with the given title 066 * @throws NoSuchElementException if no layout has yet been defined with the given title 067 */ 068 ShuffleboardLayout getLayout(String title); 069 070 /** 071 * Adds a widget to this container to display the given sendable. 072 * 073 * @param title the title of the widget 074 * @param sendable the sendable to display 075 * @return a widget to display the sendable data 076 * @throws IllegalArgumentException if a widget already exists in this container with the given 077 * title 078 */ 079 ComplexWidget add(String title, Sendable sendable); 080 081 /** 082 * Adds a widget to this container to display the given video stream. 083 * 084 * @param title the title of the widget 085 * @param video the video stream to display 086 * @return a widget to display the sendable data 087 * @throws IllegalArgumentException if a widget already exists in this container with the given 088 * title 089 */ 090 default ComplexWidget add(String title, VideoSource video) { 091 return add(title, SendableCameraWrapper.wrap(video)); 092 } 093 094 /** 095 * Adds a widget to this container to display the given sendable. 096 * 097 * @param sendable the sendable to display 098 * @return a widget to display the sendable data 099 * @throws IllegalArgumentException if a widget already exists in this container with the given 100 * title, or if the sendable's name has not been specified 101 */ 102 ComplexWidget add(Sendable sendable); 103 104 /** 105 * Adds a widget to this container to display the given video stream. 106 * 107 * @param video the video to display 108 * @return a widget to display the sendable data 109 * @throws IllegalArgumentException if a widget already exists in this container with the same 110 * title as the video source 111 */ 112 default ComplexWidget add(VideoSource video) { 113 return add(SendableCameraWrapper.wrap(video)); 114 } 115 116 /** 117 * Adds a widget to this container to display the given data. 118 * 119 * @param title the title of the widget 120 * @param defaultValue the default value of the widget 121 * @return a widget to display the sendable data 122 * @throws IllegalArgumentException if a widget already exists in this container with the given 123 * title 124 * @see #addPersistent(String, Object) add(String title, Object defaultValue) 125 */ 126 SimpleWidget add(String title, Object defaultValue); 127 128 /** 129 * Adds a widget to this container to display the given data. 130 * 131 * @param title the title of the widget 132 * @param typeString the NT type string 133 * @param defaultValue the default value of the widget 134 * @return a widget to display the sendable data 135 * @throws IllegalArgumentException if a widget already exists in this container with the given 136 * title 137 * @see #addPersistent(String, Object) add(String title, Object defaultValue) 138 */ 139 SimpleWidget add(String title, String typeString, Object defaultValue); 140 141 /** 142 * Adds a widget to this container to display a video stream. 143 * 144 * @param title the title of the widget 145 * @param cameraName the name of the streamed camera 146 * @param cameraUrls the URLs with which the dashboard can access the camera stream 147 * @return a widget to display the camera stream 148 * @throws IllegalArgumentException if a widget already exists in this container with the given 149 * title 150 */ 151 default ComplexWidget addCamera(String title, String cameraName, String... cameraUrls) { 152 return add(title, SendableCameraWrapper.wrap(cameraName, cameraUrls)); 153 } 154 155 /** 156 * Adds a widget to this container. The widget will display the data provided by the value 157 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 158 * overridden by values from the value supplier. 159 * 160 * @param title the title of the widget 161 * @param valueSupplier the supplier for values 162 * @return a widget to display data 163 * @throws IllegalArgumentException if a widget already exists in this container with the given 164 * title 165 */ 166 SuppliedValueWidget<String> addString(String title, Supplier<String> valueSupplier); 167 168 /** 169 * Adds a widget to this container. The widget will display the data provided by the value 170 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 171 * overridden by values from the value supplier. 172 * 173 * @param title the title of the widget 174 * @param valueSupplier the supplier for values 175 * @return a widget to display data 176 * @throws IllegalArgumentException if a widget already exists in this container with the given 177 * title 178 */ 179 SuppliedValueWidget<Double> addNumber(String title, DoubleSupplier valueSupplier); 180 181 /** 182 * Adds a widget to this container. The widget will display the data provided by the value 183 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 184 * overridden by values from the value supplier. 185 * 186 * @param title the title of the widget 187 * @param valueSupplier the supplier for values 188 * @return a widget to display data 189 * @throws IllegalArgumentException if a widget already exists in this container with the given 190 * title 191 */ 192 SuppliedValueWidget<Double> addDouble(String title, DoubleSupplier valueSupplier); 193 194 /** 195 * Adds a widget to this container. The widget will display the data provided by the value 196 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 197 * overridden by values from the value supplier. 198 * 199 * @param title the title of the widget 200 * @param valueSupplier the supplier for values 201 * @return a widget to display data 202 * @throws IllegalArgumentException if a widget already exists in this container with the given 203 * title 204 */ 205 SuppliedValueWidget<Float> addFloat(String title, FloatSupplier valueSupplier); 206 207 /** 208 * Adds a widget to this container. The widget will display the data provided by the value 209 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 210 * overridden by values from the value supplier. 211 * 212 * @param title the title of the widget 213 * @param valueSupplier the supplier for values 214 * @return a widget to display data 215 * @throws IllegalArgumentException if a widget already exists in this container with the given 216 * title 217 */ 218 SuppliedValueWidget<Long> addInteger(String title, LongSupplier valueSupplier); 219 220 /** 221 * Adds a widget to this container. The widget will display the data provided by the value 222 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 223 * overridden by values from the value supplier. 224 * 225 * @param title the title of the widget 226 * @param valueSupplier the supplier for values 227 * @return a widget to display data 228 * @throws IllegalArgumentException if a widget already exists in this container with the given 229 * title 230 */ 231 SuppliedValueWidget<Boolean> addBoolean(String title, BooleanSupplier valueSupplier); 232 233 /** 234 * Adds a widget to this container. The widget will display the data provided by the value 235 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 236 * overridden by values from the value supplier. 237 * 238 * @param title the title of the widget 239 * @param valueSupplier the supplier for values 240 * @return a widget to display data 241 * @throws IllegalArgumentException if a widget already exists in this container with the given 242 * title 243 */ 244 SuppliedValueWidget<String[]> addStringArray(String title, Supplier<String[]> valueSupplier); 245 246 /** 247 * Adds a widget to this container. The widget will display the data provided by the value 248 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 249 * overridden by values from the value supplier. 250 * 251 * @param title the title of the widget 252 * @param valueSupplier the supplier for values 253 * @return a widget to display data 254 * @throws IllegalArgumentException if a widget already exists in this container with the given 255 * title 256 */ 257 SuppliedValueWidget<double[]> addDoubleArray(String title, Supplier<double[]> valueSupplier); 258 259 /** 260 * Adds a widget to this container. The widget will display the data provided by the value 261 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 262 * overridden by values from the value supplier. 263 * 264 * @param title the title of the widget 265 * @param valueSupplier the supplier for values 266 * @return a widget to display data 267 * @throws IllegalArgumentException if a widget already exists in this container with the given 268 * title 269 */ 270 SuppliedValueWidget<float[]> addFloatArray(String title, Supplier<float[]> valueSupplier); 271 272 /** 273 * Adds a widget to this container. The widget will display the data provided by the value 274 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 275 * overridden by values from the value supplier. 276 * 277 * @param title the title of the widget 278 * @param valueSupplier the supplier for values 279 * @return a widget to display data 280 * @throws IllegalArgumentException if a widget already exists in this container with the given 281 * title 282 */ 283 SuppliedValueWidget<long[]> addIntegerArray(String title, Supplier<long[]> valueSupplier); 284 285 /** 286 * Adds a widget to this container. The widget will display the data provided by the value 287 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 288 * overridden by values from the value supplier. 289 * 290 * @param title the title of the widget 291 * @param valueSupplier the supplier for values 292 * @return a widget to display data 293 * @throws IllegalArgumentException if a widget already exists in this container with the given 294 * title 295 */ 296 SuppliedValueWidget<boolean[]> addBooleanArray(String title, Supplier<boolean[]> valueSupplier); 297 298 /** 299 * Adds a widget to this container. The widget will display the data provided by the value 300 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 301 * overridden by values from the value supplier. 302 * 303 * @param title the title of the widget 304 * @param valueSupplier the supplier for values 305 * @return a widget to display data 306 * @throws IllegalArgumentException if a widget already exists in this container with the given 307 * title 308 */ 309 default SuppliedValueWidget<byte[]> addRaw(String title, Supplier<byte[]> valueSupplier) { 310 return addRaw(title, "raw", valueSupplier); 311 } 312 313 /** 314 * Adds a widget to this container. The widget will display the data provided by the value 315 * supplier. Changes made on the dashboard will not propagate to the widget object, and will be 316 * overridden by values from the value supplier. 317 * 318 * @param title the title of the widget 319 * @param typeString the NT type string for the value 320 * @param valueSupplier the supplier for values 321 * @return a widget to display data 322 * @throws IllegalArgumentException if a widget already exists in this container with the given 323 * title 324 */ 325 SuppliedValueWidget<byte[]> addRaw( 326 String title, String typeString, Supplier<byte[]> valueSupplier); 327 328 /** 329 * Adds a widget to this container to display a simple piece of data. Unlike {@link #add(String, 330 * Object)}, the value in the widget will be saved on the robot and will be used when the robot 331 * program next starts rather than {@code defaultValue}. 332 * 333 * @param title the title of the widget 334 * @param defaultValue the default value of the widget 335 * @return a widget to display the sendable data 336 * @throws IllegalArgumentException if a widget already exists in this container with the given 337 * title 338 * @see #add(String, Object) add(String title, Object defaultValue) 339 */ 340 default SimpleWidget addPersistent(String title, Object defaultValue) { 341 return addPersistent(title, NetworkTableType.getStringFromObject(defaultValue), defaultValue); 342 } 343 344 /** 345 * Adds a widget to this container to display a simple piece of data. Unlike {@link #add(String, 346 * Object)}, the value in the widget will be saved on the robot and will be used when the robot 347 * program next starts rather than {@code defaultValue}. 348 * 349 * @param title the title of the widget 350 * @param typeString the NT type string 351 * @param defaultValue the default value of the widget 352 * @return a widget to display the sendable data 353 * @throws IllegalArgumentException if a widget already exists in this container with the given 354 * title 355 * @see #add(String, Object) add(String title, Object defaultValue) 356 */ 357 default SimpleWidget addPersistent(String title, String typeString, Object defaultValue) { 358 SimpleWidget widget = add(title, defaultValue); 359 widget.getEntry(typeString).getTopic().setPersistent(true); 360 return widget; 361 } 362}