JavaFX - Glisser déposer d'onglet vers un autre TabPane

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage stage) {

    // L'objet contenant l'onglet à déplacer
    TabToMove tabToMove = new TabToMove();

    // Le premier onglet
    Tab tab0 = new Tab();
    // Avec un label en tant que titre
    Label labelTab0 = new Label("Onglet 0");
    tab0.setGraphic(labelTab0);
    tab0.setContent(new Label("Contenu de l'onglet 0"));

    // Les autres onglets
    Tab tab1 = new Tab();
    Label labelTab1 = new Label("Onglet 1");
    tab1.setGraphic(labelTab1);
    tab1.setContent(new Label("Contenu de l'onglet 1"));

    Tab tab2 = new Tab();
    Label labelTab2 = new Label("Onglet 2");
    tab2.setGraphic(labelTab2);
    tab2.setContent(new Label("Contenu de l'onglet 2"));

    Tab tab3 = new Tab();
    Label labelTab3 = new Label("Onglet 3");
    tab3.setGraphic(labelTab3);
    tab3.setContent(new Label("Contenu de l'onglet 3"));

    // Les deux panneaux contenant les onglets
    TabPane tabpane = new TabPane(tab0, tab1);
    TabPane tabpane2 = new TabPane(tab2, tab3);

    // Lorsque l'onglet est déplacé (drag)
    labelTab0.setOnDragDetected(new DragDetectedEventHandler(tabToMove, tab0));
    labelTab1.setOnDragDetected(new DragDetectedEventHandler(tabToMove, tab1));
    labelTab2.setOnDragDetected(new DragDetectedEventHandler(tabToMove, tab2));
    labelTab3.setOnDragDetected(new DragDetectedEventHandler(tabToMove, tab3));

    // Accepte le drag
    tabpane.setOnDragOver(new DragDropOverEventHandler());
    tabpane2.setOnDragOver(new DragDropOverEventHandler());

    // Ajoute l'onglet vers son nouveau panneau et supprime l'onglet de l'ancien panneau
    tabpane.setOnDragDropped(new DragDropDroppedEventHandler(tabToMove, tabpane));
    tabpane2.setOnDragDropped(new DragDropDroppedEventHandler(tabToMove, tabpane2));

    // Affichage des éléments
    HBox root = new HBox(tabpane, tabpane2);
    HBox.setHgrow(tabpane, Priority.ALWAYS);
    HBox.setHgrow(tabpane2, Priority.ALWAYS);
    Scene scene = new Scene(root, 640, 480);
    stage.setScene(scene);
    stage.show();
  }

  public static void main(String[] args) {
    launch();
  }

}

class DragDetectedEventHandler implements EventHandler < MouseEvent > {

  private TabToMove movingTab;
  private Tab tab;

  public DragDetectedEventHandler(TabToMove movingTab, Tab tab) {
    this.movingTab = movingTab;
    this.tab = tab;
  }

  @Override
  public void handle(MouseEvent event) {
    // L'élément source
    Node node = (Node) event.getSource();

    // Commence le transfert
    Dragboard dragboard = node.startDragAndDrop(TransferMode.MOVE);

    // Ajoute un contenu arbitraire dans le presse-papier
    ClipboardContent clipboardContent = new ClipboardContent();
    clipboardContent.putString("");
    dragboard.setContent(clipboardContent);

    // Met à jour l'onglet en mouvement courant
    movingTab.setMovingTab(tab);
  }
}

class DragDropOverEventHandler implements EventHandler < DragEvent > {

  @Override
  public void handle(DragEvent event) {
    // Accepte le transfert
    event.acceptTransferModes(TransferMode.MOVE);
  }

}

class DragDropDroppedEventHandler implements EventHandler < DragEvent > {

  private TabToMove movingTab;
  private TabPane tabpane;

  public DragDropDroppedEventHandler(TabToMove movingTab, TabPane tabpane) {
    this.movingTab = movingTab;
    this.tabpane = tabpane;
  }

  @Override
  public void handle(DragEvent event) {
    // Supprime l'onglet de l'ancien panneau
    movingTab.getMovingTab().getTabPane().getTabs().remove(movingTab.getMovingTab());
    // Ajoute l'onglet vers son nouveau panneau
    tabpane.getTabs().add(movingTab.getMovingTab());
  }

}

/** Object contenant l'onglet à déplacer */
class TabToMove {
  private Tab movingTab;

  public Tab getMovingTab() {
    return movingTab;
  }

  public void setMovingTab(Tab movingTab) {
    this.movingTab = movingTab;
  }

}

Commentaires