WIP, getting swing "stage" implemented with animations and rendering order

This commit is contained in:
nathan 2015-08-18 01:02:10 +02:00
parent 7fda42c508
commit 3707b1f4cd
3 changed files with 149 additions and 92 deletions

View File

@ -39,7 +39,7 @@ class JavaFxUtil {
.getBounds().x);
}
public static void runAndWait(Runnable runnable) {
public static void invokeAndWait(Runnable runnable) {
// run synchronously on JavaFX thread
if (Platform.isFxApplicationThread()) {
runnable.run();
@ -57,7 +57,7 @@ class JavaFxUtil {
}
}
public static <T> T runAndWait(Callable callable) {
public static <T> T invokeAndWait(Callable callable) {
// run synchronously on JavaFX thread
if (Platform.isFxApplicationThread()) {
try {
@ -79,7 +79,11 @@ class JavaFxUtil {
return null;
}
public static void runLater(Runnable runnable) {
Platform.runLater(runnable);
public static void invokeLater(Runnable runnable) {
if (Platform.isFxApplicationThread()) {
runnable.run();
} else {
Platform.runLater(runnable);
}
}
}

View File

@ -47,23 +47,29 @@ class StageAsSwingWrapper {
}
}
private Method method;
private
StageAsSwingWrapper() {
frame = new JFrame();
panel = new JFXPanel();
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setUndecorated(true);
frame.add(panel);
private static Method method;
static {
try {
method = Scene.class.getDeclaredMethod("preferredSize");
method.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private
StageAsSwingWrapper() {
frame = new JFrame() {
};
panel = new JFXPanel();
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.setUndecorated(true);
frame.add(panel);
opacityProperty = new WritableValue<Float>() {
@Override
@ -168,6 +174,7 @@ class StageAsSwingWrapper {
public
void close() {
frame.dispose();
latch.countDown();
}
public
@ -197,12 +204,10 @@ class StageAsSwingWrapper {
frame.setVisible(false);
frame.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);
frame.pack();
panel.validate();
// Figure out the size of everything. Because JFXPanel DOES NOT do this.
sizeToScene();
frame.pack();
sizeToScene();
frame.setVisible(true);
});
}
@ -221,7 +226,7 @@ class StageAsSwingWrapper {
public
void initModality(final Dialog.ModalExclusionType modal) {
// we take in the javaFX modality, and pass it on to the correct swing version
JavaFxUtil.runAndWait(() -> frame.setModalExclusionType(modal));
JavaFxUtil.invokeAndWait(() -> frame.setModalExclusionType(modal));
}
public
@ -231,9 +236,15 @@ class StageAsSwingWrapper {
public
void sizeToScene() {
SwingUtil.invokeAndWait(() -> {
frame.invalidate();
frame.validate();
}
);
// Figure out the size of everything. Because JFXPanel DOES NOT do this.
// must be on the FX app thread
JavaFxUtil.runAndWait(() -> {
JavaFxUtil.invokeAndWait(() -> {
final Scene scene = panel.getScene();
try {
@ -250,4 +261,9 @@ class StageAsSwingWrapper {
void setScene(final Scene scene) {
panel.setScene(scene);
}
public
WritableValue<Float> getOpacityProperty() {
return opacityProperty;
}
}

View File

@ -30,7 +30,9 @@
package dorkbox.util.javafx;
import dorkbox.util.JavaFxUtil;
import dorkbox.util.SwingUtil;
import impl.org.controlsfx.ImplUtils;
import javafx.animation.*;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
@ -50,6 +52,7 @@ import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.util.Duration;
import org.controlsfx.control.PopOver;
import org.controlsfx.tools.ValueExtractor;
import org.controlsfx.validation.ValidationSupport;
@ -247,7 +250,7 @@ public class Wizard {
public
void accept(final WizardPage currentPage) {
if (currentPage.autoFocusNext) {
JavaFxUtil.runLater(BUTTON_NEXT::requestFocus);
JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus);
}
}
};
@ -292,7 +295,7 @@ public class Wizard {
borderPane.setTop(region);
center = new VBox();
center.setMinSize(0, 0);
center.setMinSize(10, 10);
center.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
// center.setStyle("-fx-background-color: #2046ff;");
borderPane.setCenter(center);
@ -315,7 +318,7 @@ public class Wizard {
private
void validatePopover(final String newValue) {
if (newValue != null) {
currentPage.ifPresent(currentPage -> JavaFxUtil.runLater(() -> {
currentPage.ifPresent(currentPage -> JavaFxUtil.invokeLater(() -> {
final PopOver popOver = this.popOver;
this.popOverErrorText.setText(newValue);
@ -388,7 +391,7 @@ public class Wizard {
*/
public
void goNext() {
JavaFxUtil.runLater(() -> {
JavaFxUtil.invokeLater(() -> {
currentPage.ifPresent(pageHistory::push);
currentPage = getFlow().advance(currentPage.orElse(null));
updatePage(stage, true);
@ -400,7 +403,7 @@ public class Wizard {
private
void goPrev() {
currentPage = Optional.ofNullable(pageHistory.isEmpty() ? null : pageHistory.pop());
JavaFxUtil.runLater(() -> updatePage(stage, false));
JavaFxUtil.invokeLater(() -> updatePage(stage, false));
}
private
@ -476,7 +479,7 @@ public class Wizard {
*/
public final
void setFlow(Flow flow) {
JavaFxUtil.runAndWait(() -> this.flow.set(flow));
JavaFxUtil.invokeAndWait(() -> this.flow.set(flow));
}
@ -624,6 +627,9 @@ public class Wizard {
return;
}
SequentialTransition sequentialTransition = new SequentialTransition();
sequentialTransition.setCycleCount(1);
Optional<WizardPage> prevPage = Optional.ofNullable(pageHistory.isEmpty() ? null : pageHistory.peek());
prevPage.ifPresent(page -> {
// if we are going forward in the wizard, we read in the settings
@ -643,83 +649,114 @@ public class Wizard {
invalidProperty.set(false);
popOver.hide();
Timeline timeline = new Timeline();
timeline.setCycleCount(1);
timeline.getKeyFrames()
.addAll(new KeyFrame(Duration.millis(200),
new KeyValue(stage.getOpacityProperty(), 0F, Interpolator.EASE_OUT)));
timeline.setOnFinished(event -> {
currentPage.ifPresent(currentPage -> {
refreshCurrentPage(stage, currentPage);
SwingUtil.invokeAndWait(() -> SwingUtil.showOnSameScreenAsMouseCenter(stage.frame));
Timeline timeline2 = new Timeline();
timeline2.setCycleCount(1);
timeline2.getKeyFrames()
.addAll(new KeyFrame(Duration.millis(500),
new KeyValue(stage.getOpacityProperty(), 1F, Interpolator.EASE_OUT)));
timeline2.play();
});
}
);
sequentialTransition.getChildren().add(timeline);
});
currentPage.ifPresent(currentPage -> {
// put in default actions
if (!BUTTON_PREV_INIT) {
BUTTON_PREV_INIT = true;
BUTTON_PREVIOUS.setDisable(false);
}
if (!BUTTON_NEXT_INIT) {
BUTTON_NEXT_INIT = true;
BUTTON_NEXT.setDisable(false);
// only run this if we don't have a prev page, otherwise, we run this at the end of our animation
if (!prevPage.isPresent()) {
currentPage.ifPresent(currentPage -> {
refreshCurrentPage(stage, currentPage);
});
}
BUTTON_NEXT.addEventFilter(ActionEvent.ACTION, BUTTON_NEXT_EVENT_HANDLER);
BUTTON_NEXT.addEventFilter(KeyEvent.KEY_PRESSED, BUTTON_NEXT_EVENT_HANDLER);
}
sequentialTransition.play();
validateActionState();
}
// then give user a chance to modify the default actions
currentPage.onEnteringPage(this);
private
void refreshCurrentPage(final StageAsSwingWrapper stage, final WizardPage currentPage) {
// put in default actions
if (!BUTTON_PREV_INIT) {
BUTTON_PREV_INIT = true;
BUTTON_PREVIOUS.setDisable(false);
}
if (!BUTTON_NEXT_INIT) {
BUTTON_NEXT_INIT = true;
BUTTON_NEXT.setDisable(false);
invalidProperty.bind(currentPage.invalidProperty);
invalidPropertyStrings.bind(currentPage.invalidPropertyStrings);
BUTTON_NEXT.addEventFilter(ActionEvent.ACTION, BUTTON_NEXT_EVENT_HANDLER);
BUTTON_NEXT.addEventFilter(KeyEvent.KEY_PRESSED, BUTTON_NEXT_EVENT_HANDLER);
}
final Node firstFocusElement = currentPage.firstFocusElement;
if (firstFocusElement != null) {
JavaFxUtil.runLater(() -> {
if (isInvalid()) {
firstFocusElement.requestFocus();
}
else {
JavaFxUtil.runLater(BUTTON_NEXT::requestFocus);
}
});
}
else {
// then give user a chance to modify the default actions
currentPage.onEnteringPage(this);
invalidProperty.bind(currentPage.invalidProperty);
invalidPropertyStrings.bind(currentPage.invalidPropertyStrings);
final Node firstFocusElement = currentPage.firstFocusElement;
if (firstFocusElement != null) {
JavaFxUtil.invokeLater(() -> {
if (isInvalid()) {
JavaFxUtil.runLater(BUTTON_PREVIOUS::requestFocus);
firstFocusElement.requestFocus();
}
else {
JavaFxUtil.runLater(BUTTON_NEXT::requestFocus);
}
}
// and then switch to the new pane
if (currentPage.headerFont != null) {
headerText.setFont(currentPage.headerFont);
}
else {
headerText.setFont(defaultHeaderFont);
}
if (currentPage.headerGraphic != null) {
graphicRegion.getChildren().setAll(currentPage.headerGraphic);
} else {
graphicRegion.getChildren().clear();
}
headerText.setText(currentPage.headerText);
ObservableList<Node> children = center.getChildren();
children.clear();
children.add(currentPage.anchorPane);
if (!useSpecifiedSize) {
currentPage.anchorPane.autosize();
stage.sizeToScene();
}
JavaFxUtil.runLater(() -> {
if (isInvalid()) {
validatePopover(currentPage.invalidPropertyStrings.get());
} else {
popOver.hide();
JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus);
}
});
});
}
else {
if (isInvalid()) {
JavaFxUtil.invokeLater(BUTTON_PREVIOUS::requestFocus);
}
else {
JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus);
}
}
validateActionState();
// and then switch to the new pane
if (currentPage.headerFont != null) {
headerText.setFont(currentPage.headerFont);
}
else {
headerText.setFont(defaultHeaderFont);
}
if (currentPage.headerGraphic != null) {
graphicRegion.getChildren().setAll(currentPage.headerGraphic);
} else {
graphicRegion.getChildren().clear();
}
headerText.setText(currentPage.headerText);
ObservableList<Node> children = center.getChildren();
children.clear();
children.add(currentPage.anchorPane);
if (!useSpecifiedSize) {
currentPage.anchorPane.autosize();
stage.sizeToScene();
}
JavaFxUtil.invokeAndWait(() -> {
if (isInvalid()) {
validatePopover(currentPage.invalidPropertyStrings.get());
} else {
popOver.hide();
}
});
}
private