add drag sort
This commit is contained in:
@@ -10,16 +10,22 @@ import com.imyeyu.lang.multi.ResourcesMultilingual;
|
|||||||
import javafx.beans.binding.DoubleBinding;
|
import javafx.beans.binding.DoubleBinding;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.TableCell;
|
import javafx.scene.control.TableCell;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
|
import javafx.scene.control.TableRow;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
|
import javafx.scene.input.ClipboardContent;
|
||||||
|
import javafx.scene.input.Dragboard;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.input.ScrollEvent;
|
import javafx.scene.input.ScrollEvent;
|
||||||
|
import javafx.scene.input.TransferMode;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,7 +37,10 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class HostTable extends TableView<Host> implements TimiFXUI {
|
public class HostTable extends TableView<Host> implements TimiFXUI {
|
||||||
|
|
||||||
|
private static final String DRAG_INDEX_KEY = "host-table-row-index";
|
||||||
|
|
||||||
private final ResourcesMultilingual multilingual;
|
private final ResourcesMultilingual multilingual;
|
||||||
|
private int dragSourceIndex = -1;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void postConstruct() {
|
private void postConstruct() {
|
||||||
@@ -78,6 +87,10 @@ public class HostTable extends TableView<Host> implements TimiFXUI {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
getColumns().add(activated);
|
getColumns().add(activated);
|
||||||
|
|
||||||
|
TableColumn<Host, Void> drag = createDragColumn();
|
||||||
|
getColumns().add(drag);
|
||||||
|
|
||||||
// IP
|
// IP
|
||||||
TableColumn<Host, String> ip = new TableColumn<>("IP");
|
TableColumn<Host, String> ip = new TableColumn<>("IP");
|
||||||
ip.setCellValueFactory(new PropertyValueFactory<>("ip"));
|
ip.setCellValueFactory(new PropertyValueFactory<>("ip"));
|
||||||
@@ -245,6 +258,7 @@ public class HostTable extends TableView<Host> implements TimiFXUI {
|
|||||||
|
|
||||||
DoubleBinding db = widthProperty().subtract(8);
|
DoubleBinding db = widthProperty().subtract(8);
|
||||||
db = db.subtract(activated.widthProperty());
|
db = db.subtract(activated.widthProperty());
|
||||||
|
db = db.subtract(drag.widthProperty());
|
||||||
db = db.subtract(ip.widthProperty());
|
db = db.subtract(ip.widthProperty());
|
||||||
db = db.subtract(description.widthProperty());
|
db = db.subtract(description.widthProperty());
|
||||||
db = db.subtract(delete.widthProperty());
|
db = db.subtract(delete.widthProperty());
|
||||||
@@ -256,5 +270,117 @@ public class HostTable extends TableView<Host> implements TimiFXUI {
|
|||||||
|
|
||||||
// 滚动时编辑区主动失去焦点
|
// 滚动时编辑区主动失去焦点
|
||||||
addEventFilter(ScrollEvent.ANY, e -> requestFocus());
|
addEventFilter(ScrollEvent.ANY, e -> requestFocus());
|
||||||
|
setRowFactory(table -> createDraggableRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建拖动排序列。
|
||||||
|
*
|
||||||
|
* @return 拖动排序列
|
||||||
|
*/
|
||||||
|
private TableColumn<Host, Void> createDragColumn() {
|
||||||
|
TableColumn<Host, Void> drag = new TableColumn<>("");
|
||||||
|
drag.setPrefWidth(40);
|
||||||
|
drag.setSortable(false);
|
||||||
|
drag.setResizable(false);
|
||||||
|
drag.setReorderable(false);
|
||||||
|
drag.setCellFactory(cell -> new TableCell<>() {
|
||||||
|
|
||||||
|
private final Button dragButton = new Button("::");
|
||||||
|
|
||||||
|
{
|
||||||
|
dragButton.getStyleClass().add(CSS.BORDER_N);
|
||||||
|
dragButton.setFocusTraversable(false);
|
||||||
|
dragButton.setOnDragDetected(this::startRowDrag);
|
||||||
|
setAlignment(Pos.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Void item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
if (empty || getTableRow() == null || getTableRow().getItem() == null) {
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
setGraphic(dragButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从拖动按钮发起行拖拽。
|
||||||
|
*
|
||||||
|
* @param event 鼠标事件
|
||||||
|
*/
|
||||||
|
private void startRowDrag(MouseEvent event) {
|
||||||
|
TableRow<Host> row = getTableRow();
|
||||||
|
if (row == null || row.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dragSourceIndex = row.getIndex();
|
||||||
|
Dragboard dragboard = row.startDragAndDrop(TransferMode.MOVE);
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(DRAG_INDEX_KEY.formatted());
|
||||||
|
dragboard.setContent(content);
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建支持拖动排序的表格行。
|
||||||
|
*
|
||||||
|
* @return 表格行
|
||||||
|
*/
|
||||||
|
private TableRow<Host> createDraggableRow() {
|
||||||
|
TableRow<Host> row = new TableRow<>();
|
||||||
|
row.setOnDragOver(event -> {
|
||||||
|
if (dragSourceIndex < 0 || row.getIndex() == dragSourceIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.getDragboard().hasString()) {
|
||||||
|
event.acceptTransferModes(TransferMode.MOVE);
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
row.setOnDragDropped(event -> {
|
||||||
|
if (dragSourceIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int targetIndex = row.isEmpty() ? getItems().size() : row.getIndex();
|
||||||
|
moveItem(dragSourceIndex, targetIndex);
|
||||||
|
event.setDropCompleted(true);
|
||||||
|
event.consume();
|
||||||
|
});
|
||||||
|
row.setOnDragDone(event -> dragSourceIndex = -1);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整条目顺序。
|
||||||
|
*
|
||||||
|
* @param fromIndex 原索引
|
||||||
|
* @param toIndex 目标索引
|
||||||
|
*/
|
||||||
|
private void moveItem(int fromIndex, int toIndex) {
|
||||||
|
ObservableList<Host> items = getItems();
|
||||||
|
if (fromIndex < 0 || items.size() <= fromIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (toIndex < 0) {
|
||||||
|
toIndex = 0;
|
||||||
|
}
|
||||||
|
if (items.size() < toIndex) {
|
||||||
|
toIndex = items.size();
|
||||||
|
}
|
||||||
|
if (fromIndex == toIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Host movedItem = items.remove(fromIndex);
|
||||||
|
if (fromIndex < toIndex) {
|
||||||
|
toIndex--;
|
||||||
|
}
|
||||||
|
items.add(toIndex, movedItem);
|
||||||
|
getSelectionModel().clearAndSelect(toIndex);
|
||||||
|
scrollTo(toIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user