fix: jfxdialog

This commit is contained in:
huanghongxun 2020-04-17 23:46:20 +08:00
parent 859da37d71
commit 2701a84b94
3 changed files with 66 additions and 42 deletions

View File

@ -17,7 +17,6 @@
*/ */
package org.jackhuang.hmcl.ui.decorator; package org.jackhuang.hmcl.ui.decorator;
import com.jfoenix.controls.JFXDialog;
import javafx.beans.property.*; import javafx.beans.property.*;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -26,6 +25,7 @@ import javafx.event.EventHandler;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.Control; import javafx.scene.control.Control;
import javafx.scene.control.Skin; import javafx.scene.control.Skin;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background; import javafx.scene.layout.Background;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.stage.Stage; import javafx.stage.Stage;
@ -47,7 +47,10 @@ public class Decorator extends Control {
private final BooleanProperty canClose = new SimpleBooleanProperty(false); private final BooleanProperty canClose = new SimpleBooleanProperty(false);
private final BooleanProperty showCloseAsHome = new SimpleBooleanProperty(false); private final BooleanProperty showCloseAsHome = new SimpleBooleanProperty(false);
private final Stage primaryStage; private final Stage primaryStage;
private JFXDialog dialog; private StackPane drawerWrapper;
private final ReadOnlyBooleanWrapper allowMove = new ReadOnlyBooleanWrapper();
private final ReadOnlyBooleanWrapper dragging = new ReadOnlyBooleanWrapper();
public Decorator(Stage primaryStage) { public Decorator(Stage primaryStage) {
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
@ -59,12 +62,12 @@ public class Decorator extends Control {
return primaryStage; return primaryStage;
} }
public JFXDialog getDialog() { public StackPane getDrawerWrapper() {
return dialog; return drawerWrapper;
} }
void setDialog(JFXDialog dialog) { public void setDrawerWrapper(StackPane drawerWrapper) {
this.dialog = dialog; this.drawerWrapper = drawerWrapper;
} }
public ObservableList<Node> getDrawer() { public ObservableList<Node> getDrawer() {
@ -167,6 +170,30 @@ public class Decorator extends Control {
return showCloseAsHome; return showCloseAsHome;
} }
public boolean isAllowMove() {
return allowMove.get();
}
public ReadOnlyBooleanProperty allowMoveProperty() {
return allowMove.getReadOnlyProperty();
}
void setAllowMove(boolean allowMove) {
this.allowMove.set(allowMove);
}
public boolean isDragging() {
return dragging.get();
}
public ReadOnlyBooleanProperty draggingProperty() {
return dragging.getReadOnlyProperty();
}
void setDragging(boolean dragging) {
this.dragging.set(dragging);
}
public ObjectProperty<EventHandler<ActionEvent>> onBackNavButtonActionProperty() { public ObjectProperty<EventHandler<ActionEvent>> onBackNavButtonActionProperty() {
return onBackNavButtonAction; return onBackNavButtonAction;
} }
@ -191,4 +218,11 @@ public class Decorator extends Control {
public void close() { public void close() {
onCloseButtonAction.get().run(); onCloseButtonAction.get().run();
} }
public void capableDraggingWindow(Node node) {
node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove.set(true));
node.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
if (!isDragging()) allowMove.set(false);
});
}
} }

View File

@ -73,6 +73,7 @@ public class DecoratorController {
private final ImageView welcomeView; private final ImageView welcomeView;
private final Navigator navigator; private final Navigator navigator;
private JFXDialog dialog;
private StackContainerPane dialogPane; private StackContainerPane dialogPane;
public DecoratorController(Stage stage, Node mainPage) { public DecoratorController(Stage stage, Node mainPage) {
@ -294,21 +295,22 @@ public class DecoratorController {
public void showDialog(Node node) { public void showDialog(Node node) {
FXUtils.checkFxUserThread(); FXUtils.checkFxUserThread();
if (decorator.getDialog() == null) { if (dialog == null) {
// Sometimes showDialog will be invoked before decorator was initialized. if (decorator.getDrawerWrapper() == null) {
// Keep trying again. // Sometimes showDialog will be invoked before decorator was initialized.
Platform.runLater(() -> showDialog(node)); // Keep trying again.
return; Platform.runLater(() -> showDialog(node));
} return;
}
if (dialogPane == null) { dialog = new JFXDialog();
dialogPane = new StackContainerPane(); dialogPane = new StackContainerPane();
decorator.getDialog().setContent(dialogPane);
dialog.setContent(dialogPane);
decorator.capableDraggingWindow(dialog);
dialog.setDialogContainer(decorator.getDrawerWrapper());
dialog.setOverlayClose(false);
dialog.show();
} }
if (dialogPane.isEmpty())
decorator.getDialog().show();
dialogPane.push(node); dialogPane.push(node);
EventHandler<DialogCloseEvent> handler = event -> closeDialog(node); EventHandler<DialogCloseEvent> handler = event -> closeDialog(node);
@ -317,10 +319,10 @@ public class DecoratorController {
if (node instanceof DialogAware) { if (node instanceof DialogAware) {
DialogAware dialogAware = (DialogAware) node; DialogAware dialogAware = (DialogAware) node;
if (decorator.getDialog().isVisible()) { if (dialog.isVisible()) {
dialogAware.onDialogShown(); dialogAware.onDialogShown();
} else { } else {
decorator.getDialog().visibleProperty().addListener(new ChangeListener<Boolean>() { dialog.visibleProperty().addListener(new ChangeListener<Boolean>() {
@Override @Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) { if (newValue) {
@ -340,11 +342,13 @@ public class DecoratorController {
Optional.ofNullable(node.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER)) Optional.ofNullable(node.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER))
.ifPresent(handler -> node.removeEventHandler(DialogCloseEvent.CLOSE, (EventHandler<DialogCloseEvent>) handler)); .ifPresent(handler -> node.removeEventHandler(DialogCloseEvent.CLOSE, (EventHandler<DialogCloseEvent>) handler));
if (decorator.getDialog() != null) { if (dialog != null) {
dialogPane.pop(node); dialogPane.pop(node);
if (dialogPane.getChildren().isEmpty()) { if (dialogPane.getChildren().isEmpty()) {
decorator.getDialog().close(); dialog.close();
dialog = null;
dialogPane = null;
} }
} }
} }

View File

@ -18,7 +18,6 @@
package org.jackhuang.hmcl.ui.decorator; package org.jackhuang.hmcl.ui.decorator;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.svg.SVGGlyph; import com.jfoenix.svg.SVGGlyph;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
@ -58,7 +57,6 @@ public class DecoratorSkin extends SkinBase<Decorator> {
private final StackPane leftPane; private final StackPane leftPane;
private double xOffset, yOffset, newX, newY, initX, initY; private double xOffset, yOffset, newX, newY, initX, initY;
private boolean allowMove, isDragging;
private boolean titleBarTransparent = true; private boolean titleBarTransparent = true;
/** /**
@ -98,16 +96,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
BorderPane root = new BorderPane(); BorderPane root = new BorderPane();
root.getStyleClass().addAll("jfx-decorator"); root.getStyleClass().addAll("jfx-decorator");
wrapper.getChildren().setAll(root); wrapper.getChildren().setAll(root);
skinnable.setDrawerWrapper(wrapper);
JFXDialog dialog = new JFXDialog();
dialog.setDialogContainer(wrapper);
dialog.setOverlayClose(false);
dialog.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove = true);
dialog.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
if (!isDragging) allowMove = false;
});
skinnable.setDialog(dialog);
parent.getChildren().add(wrapper); parent.getChildren().add(wrapper);
@ -148,10 +137,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
titleContainer = new StackPane(); titleContainer = new StackPane();
titleContainer.setPickOnBounds(false); titleContainer.setPickOnBounds(false);
titleContainer.getStyleClass().addAll("jfx-tool-bar"); titleContainer.getStyleClass().addAll("jfx-tool-bar");
titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED, e -> allowMove = true); control.capableDraggingWindow(titleContainer);
titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED, e -> {
if (!isDragging) allowMove = false;
});
StackPane titleBarBackground = new StackPane(); StackPane titleBarBackground = new StackPane();
titleBarBackground.getStyleClass().add("background"); titleBarBackground.getStyleClass().add("background");
@ -400,11 +386,11 @@ public class DecoratorSkin extends SkinBase<Decorator> {
} }
protected void onMouseReleased(MouseEvent mouseEvent) { protected void onMouseReleased(MouseEvent mouseEvent) {
isDragging = false; getSkinnable().setDragging(false);
} }
protected void onMouseDragged(MouseEvent mouseEvent) { protected void onMouseDragged(MouseEvent mouseEvent) {
this.isDragging = true; getSkinnable().setDragging(true);
if (mouseEvent.isPrimaryButtonDown() && (this.xOffset != -1.0 || this.yOffset != -1.0)) { if (mouseEvent.isPrimaryButtonDown() && (this.xOffset != -1.0 || this.yOffset != -1.0)) {
if (!this.primaryStage.isFullScreen() && !mouseEvent.isStillSincePress()) { if (!this.primaryStage.isFullScreen() && !mouseEvent.isStillSincePress()) {
this.newX = mouseEvent.getScreenX(); this.newX = mouseEvent.getScreenX();
@ -458,7 +444,7 @@ public class DecoratorSkin extends SkinBase<Decorator> {
} }
mouseEvent.consume(); mouseEvent.consume();
} else if (this.allowMove) { } else if (getSkinnable().isAllowMove()) {
this.primaryStage.setX(mouseEvent.getScreenX() - this.xOffset); this.primaryStage.setX(mouseEvent.getScreenX() - this.xOffset);
this.primaryStage.setY(mouseEvent.getScreenY() - this.yOffset); this.primaryStage.setY(mouseEvent.getScreenY() - this.yOffset);
mouseEvent.consume(); mouseEvent.consume();