import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

/**
 * An example of ListView breadth ScrollBar endless jitter.
 **/
public class ListViewScrollBarJitterExample extends Application {

   public static void main( final String[] args ) {
      launch( args );
   }

   final ObservableList<String> items = FXCollections.observableArrayList(
         "X0.0 Echo management message",
         "X0.1 Common Time Reference (CTR) message",
         "X0.2 Round-Trip Time Delay message",
         "X0.3 JREAP J-Series Acknowledgement (Full Stack) message",
         "X0.4 JREAP J-Series Acknowledgement (Application) message",
         "X0.5 Latency Threshold message",
         "X0.6 Latency Exceeded message",
         "X0.7 Operator-to-Operator message",
         "X0.8 Special Event message",
         "X0.9 Terminate Link message",
         "X0.10 Remote Filter message",
         "X0.11 Secondary Track Number List message",
         "X0.12 Direct Connection List message",
         "X0.13 Network Connectivity Matrix message",
         "X0.14 Connectivity Feedback message"
   );

   final ListView<String> listView = new ListView<>( items );

   private static class MyListCell extends ListCell<String> {

      private final Button button1 = new Button( "Button" );

      private final Button button2 = new Button();

      private final HBox hBox = new HBox( button1, button2 );

      @Override
      protected void updateItem( final String item, final boolean empty ) {
         super.updateItem( item, empty );
         if( !empty ) {
            setText( null );
            button2.setText( item );
            setGraphic( hBox );
         } else {
            setText( null );
            setGraphic( null );
         }
      }
   }

   @Override
   public void start( final Stage primaryStage ) throws Exception {
      listView.setCellFactory( listView -> new MyListCell() );
      primaryStage.setScene( new Scene( listView ) );
      primaryStage.show();
      // Set the width, height, vertical scroll position, selection and focus to trigger the bug.
      primaryStage.setWidth( 435.3333435058594d );
      primaryStage.setHeight( 357.3333435058594d );
      Platform.runLater( () -> {
         listView.lookupAll( ".scroll-bar" ).stream().filter( node ->
               node instanceof ScrollBar ).map( node -> (ScrollBar) node ).filter( scrollBar ->
               scrollBar.getOrientation() == Orientation.VERTICAL ).findFirst().ifPresent( vsb -> {
            vsb.setValue( vsb.getMax() );
            listView.getSelectionModel().select( items.size() - 1 );
            listView.requestFocus();
            listView.getFocusModel().focus( items.size() - 1 );
         } );
      } );
   }
} 