2424import java .util .Optional ;
2525import java .util .function .Consumer ;
2626import java .util .function .Predicate ;
27-
2827import javafx .application .Platform ;
28+ import javafx .event .ActionEvent ;
2929import javafx .event .EventHandler ;
3030import javafx .scene .Parent ;
3131import javafx .scene .control .Button ;
3232import javafx .scene .control .ButtonBar ;
3333import javafx .scene .control .ButtonType ;
34- import javafx .scene .control .ContentDisplay ;
3534import javafx .scene .control .Control ;
3635import javafx .scene .control .Dialog ;
36+ import javafx .scene .control .MenuButton ;
37+ import javafx .scene .control .MenuItem ;
3738import javafx .scene .control .Spinner ;
3839import javafx .scene .control .TextField ;
3940import javafx .scene .image .ImageView ;
40- import javafx .scene .input .MouseEvent ;
4141import javafx .scene .layout .GridPane ;
42- import javafx .scene .layout .HBox ;
4342import javafx .scene .layout .Priority ;
4443import javafx .scene .text .Text ;
45- import javafx .scene .text .TextAlignment ;
4644import javafx .stage .FileChooser ;
4745import javafx .stage .FileChooser .ExtensionFilter ;
4846
5250 * construct that source. As an example, the image file source results in a file picker that the
5351 * user can use to browse for an image.
5452 */
55- public class AddSourceView extends HBox {
53+ public class AddSourceButton extends MenuButton {
5654
5755 @ VisibleForTesting
5856 static final String SOURCE_DIALOG_STYLE_CLASS = "source-dialog" ;
5957 private final EventBus eventBus ;
6058
61- private final Button webcamButton ;
62- private final Button ipcamButton ;
59+ private final MenuItem webcamButton ;
60+ private final MenuItem ipcamButton ;
61+ private final MenuItem httpButton ;
6362 private Optional <Dialog > activeDialog = Optional .empty ();
6463
6564 @ Inject
66- AddSourceView (EventBus eventBus ,
65+ AddSourceButton (EventBus eventBus ,
6766 MultiImageFileSource .Factory multiImageSourceFactory ,
6867 ImageFileSource .Factory imageSourceFactory ,
6968 CameraSource .Factory cameraSourceFactory ,
7069 HttpSource .Factory httpSourceFactory ) {
70+ super ("Add Source" );
7171 this .eventBus = eventBus ;
72-
73- this .setFillHeight (true );
74-
75- addButton ("Add\n Image(s)" ,
76- getClass ().getResource ("/edu/wpi/grip/ui/icons/add-image.png" ),
77- mouseEvent -> {
72+
73+ addMenuItem ("Image(s)" ,
74+ getClass ().getResource ("/edu/wpi/grip/ui/icons/add-image.png" ), mouseEvent -> {
7875 // Show a file picker so the user can open one or more images from disk
7976 final FileChooser fileChooser = new FileChooser ();
8077 fileChooser .setTitle ("Open an image" );
@@ -120,14 +117,12 @@ public class AddSourceView extends HBox {
120117 }
121118 });
122119
123- webcamButton = addButton (
124- "Add\n Webcam" ,
125- getClass ().getResource ("/edu/wpi/grip/ui/icons/add-webcam.png" ),
126- mouseEvent -> {
120+ webcamButton = addMenuItem ("Webcam" ,
121+ getClass ().getResource ("/edu/wpi/grip/ui/icons/add-webcam.png" ), mouseEvent -> {
127122 final Parent root = this .getScene ().getRoot ();
128123
129124 // Show a dialog for the user to pick a camera index
130- final Spinner <Integer > cameraIndex = new Spinner <Integer >(0 , Integer .MAX_VALUE , 0 );
125+ final Spinner <Integer > cameraIndex = new Spinner <>(0 , Integer .MAX_VALUE , 0 );
131126 final SourceDialog dialog = new SourceDialog (root , cameraIndex );
132127
133128 dialog .setTitle ("Add Webcam" );
@@ -144,15 +139,11 @@ public class AddSourceView extends HBox {
144139 cameraSource .initialize ();
145140 return cameraSource ;
146141 },
147- e -> {
148- dialog .errorText .setText (e .getMessage ());
149- });
142+ e -> dialog .errorText .setText (e .getMessage ()));
150143 });
151144
152- ipcamButton = addButton (
153- "Add IP\n Camera" ,
154- getClass ().getResource ("/edu/wpi/grip/ui/icons/add-webcam.png" ),
155- mouseEvent -> {
145+ ipcamButton = addMenuItem ("IP Camera" ,
146+ getClass ().getResource ("/edu/wpi/grip/ui/icons/add-webcam.png" ), mouseEvent -> {
156147 final Parent root = this .getScene ().getRoot ();
157148
158149 // Show a dialog for the user to pick a camera URL
@@ -197,8 +188,8 @@ public class AddSourceView extends HBox {
197188 e -> dialog .errorText .setText (e .getMessage ()));
198189 });
199190
200- addButton ( "Add \n HTTP source" , getClass (). getResource ( "/edu/wpi/grip/ui/icons/publish.png" ) ,
201- mouseEvent -> {
191+ httpButton = addMenuItem ( "HTTP" ,
192+ getClass (). getResource ( "/edu/wpi/grip/ui/icons/publish.png" ), mouseEvent -> {
202193 final Parent root = this .getScene ().getRoot ();
203194 // Show a dialog to pick the server path images will be uploaded on
204195 final String imageRoot = GripServer .IMAGE_UPLOAD_PATH + "/" ;
@@ -252,31 +243,34 @@ private void loadCamera(Dialog<ButtonType> dialog, SupplierWithIO<CameraSource>
252243 /**
253244 * Add a new button for adding a source. This method takes care of setting the event handler.
254245 */
255- private Button addButton (String text , URL graphicURL , EventHandler <? super MouseEvent >
256- onMouseClicked ) {
246+ private MenuItem addMenuItem (String text , URL graphicURL , EventHandler <ActionEvent >
247+ onActionEvent ) {
257248 final ImageView graphic = new ImageView (graphicURL .toString ());
258249 graphic .setFitWidth (DPIUtility .SMALL_ICON_SIZE );
259250 graphic .setFitHeight (DPIUtility .SMALL_ICON_SIZE );
260251
261- final Button button = new Button (text , graphic );
262- button .setTextAlignment (TextAlignment .CENTER );
263- button .setContentDisplay (ContentDisplay .TOP );
264- button .setOnMouseClicked (onMouseClicked );
252+ final MenuItem menuItem = new MenuItem (" " + text , graphic );
253+ menuItem .setOnAction (onActionEvent );
265254
266- this . getChildren ().add (button );
267- return button ;
255+ getItems ().add (menuItem );
256+ return menuItem ;
268257 }
269258
270259 @ VisibleForTesting
271- Button getWebcamButton () {
260+ MenuItem getWebcamButton () {
272261 return webcamButton ;
273262 }
274263
275264 @ VisibleForTesting
276- Button getIpcamButton () {
265+ MenuItem getIpcamButton () {
277266 return ipcamButton ;
278267 }
279268
269+ @ VisibleForTesting
270+ MenuItem getHttpButton () {
271+ return httpButton ;
272+ }
273+
280274 @ VisibleForTesting
281275 void closeDialogs () {
282276 activeDialog .ifPresent (dialog -> {
@@ -291,7 +285,7 @@ void closeDialogs() {
291285 }
292286
293287 public interface Factory {
294- AddSourceView create ();
288+ AddSourceButton create ();
295289 }
296290
297291 private static class SourceDialog extends Dialog <ButtonType > {
0 commit comments