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}