Reputation: 1764
I would like to extend this post of TabPanes implementation.
I'm interested is it somehow possible to drag TabPanes with the mouse in order to change the position of the TabPane with mouse drag. Basic explanation how this can be implemented will highly appreciated.
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class FXSplitTabs extends Application{
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("SplitTabs");
stage.setWidth(700);
stage.setHeight(500);
//Setup Center and Right
TabPaneWrapper wrapper = new TabPaneWrapper(Orientation.HORIZONTAL, .9);
TabPane centerPane = new TabPane();
centerPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
TabPane rightPane = new TabPane();
rightPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
SplitPane.setResizableWithParent(rightPane, false);
wrapper.addNodes(centerPane, rightPane);
//Add bottom
TabPane bottomPane = new TabPane();
bottomPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
TabPaneWrapper wrapperBottom = new TabPaneWrapper(Orientation.VERTICAL, .7);
wrapperBottom.addNodes(wrapper.getNode(), bottomPane);
//Add left
TabPane leftPane = new TabPane();
leftPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
TabPaneWrapper wrapperleft = new TabPaneWrapper(Orientation.HORIZONTAL, .1);
wrapperleft.addNodes(leftPane, wrapperBottom.getNode());
Scene myScene = new Scene(wrapperleft.getNode());
stage.setScene(myScene);
stage.sizeToScene();
stage.show();
}
public Tab generateTab(String name){
Tab result = new Tab(name);
BorderPane content = new BorderPane();
TextArea text = new TextArea();
content.setCenter(text);
result.setContent(content);
return result;
}
public static void main(String[] args){
FXSplitTabs.launch(args);
}
public static class TabPaneWrapper{
SplitPane split;
public TabPaneWrapper(Orientation o, double splitLocation){
split = new SplitPane();
//Change the CSS (uncomment if using an external css)
//split.getStylesheets().add("test.css");
split.setOrientation(o);
split.setDividerPosition(0, splitLocation);
}
public void addNodes(final Node node1, final Node node2){
//Add to the split pane
split.getItems().addAll(node1, node2);
}
public Parent getNode(){
return split;
}
}
}
Upvotes: 1
Views: 1538
Reputation: 6475
I'd recommend adding an onDragDetected
listener and a onMouseDragReleased
listener to all your TabPanes
.
TabPaneDrag drag = new TabPaneDrag();
...
centerPane.setOnDragDetected(drag);
centerPane.setOnMouseDragReleased(drag);
...
rightPane.setOnDragDetected(drag);
rightPane.setOnMouseDragReleased(drag);
In your listener, you can keep track of what pane started the drag and which pane ended the drag (Then switch them if necessary). Here's a quick example (mind you, there's some special cases and and kinks and such I didn't bother with - And findWrapper()
is a method that returns the TabPaneWrapper
containing the TabPane
):
public class TabPaneDrag implements EventHandler<MouseEvent>{
Node start;
Node end;
@Override
public void handle(MouseEvent arg0) {
if(arg0.getEventType().equals(MouseEvent.DRAG_DETECTED)){
start = (Node)arg0.getSource();
start.startFullDrag(); //allows events to fire on nodes besides source
} else if(arg0.getEventType().equals(MouseDragEvent.MOUSE_DRAG_RELEASED)){
end = (Node)arg0.getSource();
if(end != start){
ObservableList<Node> startWrapper = findWrapper(start).split.getItems();
ObservableList<Node> endWrapper = findWrapper(end).split.getItems();
int startIndex = startWrapper.indexOf(start);
int endIndex = endWrapper.indexOf(end);
// Remove/Add the TabbedPanes to the new order
endWrapper.remove(endIndex);
startWrapper.remove(startIndex);
startWrapper.add(startIndex, end);
endWrapper.add(endIndex, start);
}
start = null;
end = null;
}
}
}
Upvotes: 1