Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
palexdev committed Apr 8, 2023
2 parents 3961ca2 + 24674cf commit a27d7e6
Showing 1 changed file with 84 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

package io.github.palexdev.materialfx.dialogs;

import io.github.palexdev.materialfx.beans.SizeBean;
import io.github.palexdev.materialfx.effects.MFXScrimEffect;
import io.github.palexdev.materialfx.enums.ScrimPriority;
import io.github.palexdev.materialfx.utils.AnimationUtils.KeyFrames;
Expand All @@ -34,9 +33,11 @@
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;

import java.io.IOException;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.WindowEvent;

/**
* Dialog implementation that simply extends {@link Stage}.
Expand Down Expand Up @@ -71,6 +72,7 @@ public class MFXStageDialog extends Stage {
private final ObjectProperty<AbstractMFXDialog> content = new SimpleObjectProperty<>();

private boolean draggable = false;

private double xPos;
private double yPos;
private EventHandler<MouseEvent> mousePressed = event -> {
Expand All @@ -92,6 +94,46 @@ public class MFXStageDialog extends Stage {
private MFXScrimEffect scrimEffect = new MFXScrimEffect();
private ScrimPriority scrimPriority = ScrimPriority.NODE;

// =====================================================================

//
// NOTE ON CENTERING THE DIALOG WITHIN THE OWNER
//
// When centerInownerNode is true, we want to show the dialog
// centered in the owner. However JavaFX calculates the actual
// width and height of the dialog only when it has to be shown,
// therefore there is no way to calculate its position relative
// to the owner in advance.
//
// The workaround is to detect when the dialog with and height
// change, so that as soon as there is a value the position of
// the dialog can be calculated and the dialog moved. This is
// done withe the two listener below, which are set in buildScene()
//
// Finally, we need anyway to center the dialog any time it is
// shown even if the dialog height and with have not changed.
// This is done during initialization adding a listener for
// WindowEvent.WINDOW_SHOWING
//

private final ChangeListener<Number> widthChangeListener = new ChangeListener<>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (centerInOwnerNode.getValue()) {
centerXInOwner(newValue.doubleValue());
}
}
};

private final ChangeListener<Number> heightChangeListener = new ChangeListener<>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (centerInOwnerNode.getValue()) {
centerYInOwner(newValue.doubleValue());
}
}
};

//================================================================================
// Constructors
//================================================================================
Expand Down Expand Up @@ -124,20 +166,33 @@ private void initialize() {
if (oldValue != null) {
oldValue.removeEventHandler(MouseEvent.MOUSE_PRESSED, mousePressed);
oldValue.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDragged);
oldValue.widthProperty().removeListener(widthChangeListener);
oldValue.heightProperty().removeListener(heightChangeListener);
}

setScene(buildScene(getContent()));
initDraggable();
});

addEventHandler(WindowEvent.WINDOW_SHOWN, event -> centerInOwner());
addEventHandler(WindowEvent.WINDOW_SHOWING, event -> {
if (getWidth() == 0) {
return;
}
if (centerInOwnerNode.getValue()) {
centerXInOwner(getWidth());
centerYInOwner(getHeight());
}
});
}

/**
* Builds the dialog's scene
* for the given content.
*/
protected Scene buildScene(AbstractMFXDialog content) {
widthProperty().addListener(widthChangeListener);
heightProperty().addListener(heightChangeListener);

Scene scene = new Scene(content);
scene.setFill(Color.TRANSPARENT);
return scene;
Expand Down Expand Up @@ -234,22 +289,32 @@ protected void unScrimOwner() {
.play();
}

/**
* This is responsible for centering the dialog on the {@link #getOwnerNode()} (if enabled).
*/
protected void centerInOwner() {
if (!isCenterInOwnerNode() || ownerNode == null) return;

Bounds screenBounds = ownerNode.localToScreen(ownerNode.getBoundsInLocal());
double startX = screenBounds.getMinX();
double startY = screenBounds.getMinY();
SizeBean dialogSize = SizeBean.of(getWidth(), getHeight());
SizeBean nodeSize = SizeBean.of(ownerNode.getWidth(), ownerNode.getHeight());
double x = startX + (nodeSize.getWidth() / 2 - dialogSize.getWidth() / 2);
double y = startY + (nodeSize.getHeight() / 2 - dialogSize.getHeight() / 2);
setX(x);
setY(y);
}
/**
* This is responsible for centering the dialog on the X axis in the
* {@link #getOwnerNode()} (if enabled).
*/
protected void centerXInOwner(double dialogWidth) {
Bounds screenBounds = ownerNode.localToScreen(ownerNode.getBoundsInLocal());

double startX = screenBounds.getMinX();
double nodeWidth = ownerNode.getWidth();
double x = startX + (nodeWidth / 2 - dialogWidth / 2);

setX(x);
}

/**
* This is responsible for centering the dialog on the Y axis in the
* {@link #getOwnerNode()} (if enabled).
*/
protected void centerYInOwner(double dialogHeight) {
Bounds screenBounds = ownerNode.localToScreen(ownerNode.getBoundsInLocal());

double startY = screenBounds.getMinY();
double nodeHeight = ownerNode.getHeight();
double y = startY + (nodeHeight / 2 - dialogHeight / 2);
setY(y);
}

/**
* Disposes the dialog, making it not reusable anymore!
Expand Down

0 comments on commit a27d7e6

Please sign in to comment.