show dialogs on the same screen as the currently focussed window

This commit is contained in:
Craig Raw 2021-04-27 12:22:39 +02:00
parent 8865f4946a
commit 93f9539f7b
21 changed files with 52 additions and 1 deletions

View file

@ -891,9 +891,11 @@ public class AppController implements Initializable {
File walletFile = Storage.getExistingWallet(wallet.getName()); File walletFile = Storage.getExistingWallet(wallet.getName());
if(walletFile != null) { if(walletFile != null) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION); Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
AppServices.setStageIcon(alert.getDialogPane().getScene().getWindow());
alert.setTitle("Existing wallet found"); alert.setTitle("Existing wallet found");
alert.setHeaderText("Replace existing wallet?"); alert.setHeaderText("Replace existing wallet?");
alert.setContentText("Wallet file " + walletFile.getName() + " already exists.\n"); alert.setContentText("Wallet file " + walletFile.getName() + " already exists.\n");
AppServices.moveToActiveWindowScreen(alert);
Optional<ButtonType> result = alert.showAndWait(); Optional<ButtonType> result = alert.showAndWait();
if(result.isPresent() && result.get() == ButtonType.CANCEL) { if(result.isPresent() && result.get() == ButtonType.CANCEL) {
return; return;

View file

@ -29,8 +29,11 @@ import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import javafx.stage.Screen;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.util.Duration; import javafx.util.Duration;
@ -508,6 +511,7 @@ public class AppServices {
alert.getDialogPane().getScene().getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); alert.getDialogPane().getScene().getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
alert.setTitle(title); alert.setTitle(title);
alert.setHeaderText(title); alert.setHeaderText(title);
moveToActiveWindowScreen(alert);
return alert.showAndWait(); return alert.showAndWait();
} }
@ -520,6 +524,31 @@ public class AppServices {
} }
} }
public static void moveToActiveWindowScreen(Dialog<?> dialog) {
Window activeWindow = Stage.getWindows().stream().filter(Window::isFocused).findFirst().orElse(get().walletWindows.keySet().iterator().hasNext() ? get().walletWindows.keySet().iterator().next() : null);
if(activeWindow != null) {
moveToWindowScreen(activeWindow, dialog);
}
}
public void moveToWalletWindowScreen(Storage storage, Dialog<?> dialog) {
moveToWindowScreen(getWindowForWallet(storage), dialog);
}
public static void moveToWindowScreen(Window currentWindow, Dialog<?> dialog) {
Window newWindow = dialog.getDialogPane().getScene().getWindow();
DialogPane dialogPane = dialog.getDialogPane();
Screen currentScreen = Screen.getScreens().stream().filter(screen -> screen.getVisualBounds().contains(currentWindow.getX(), currentWindow.getY())).findFirst().orElse(null);
if(currentScreen != null && !Screen.getPrimary().getVisualBounds().contains(currentWindow.getX(), currentWindow.getY()) && !currentScreen.getVisualBounds().contains(newWindow.getX(), newWindow.getY())) {
double dialogWidth = dialogPane.getPrefWidth() > 0.0 ? dialogPane.getPrefWidth() : (dialogPane.getWidth() > 0.0 ? dialogPane.getWidth() : 360);
double dialogHeight = dialogPane.getPrefHeight() > 0.0 ? dialogPane.getPrefHeight() : (dialogPane.getHeight() > 0.0 ? dialogPane.getHeight() : 200);
double x = currentWindow.getX() + (currentWindow.getWidth() / 2) - (dialogWidth / 2);
double y = currentWindow.getY() + (currentWindow.getHeight() / 2.2) - (dialogHeight / 2);
newWindow.setX(x);
newWindow.setY(y);
}
}
public static Font getMonospaceFont() { public static Font getMonospaceFont() {
return Font.font("Roboto Mono", 13); return Font.font("Roboto Mono", 13);
} }

View file

@ -21,6 +21,7 @@ public class WelcomeDialog extends Dialog<Mode> {
dialogPane.setPrefWidth(600); dialogPane.setPrefWidth(600);
dialogPane.setPrefHeight(520); dialogPane.setPrefHeight(520);
AppServices.moveToActiveWindowScreen(this);
dialogPane.getStylesheets().add(AppServices.class.getResource("welcome.css").toExternalForm()); dialogPane.getStylesheets().add(AppServices.class.getResource("welcome.css").toExternalForm());

View file

@ -89,6 +89,7 @@ public abstract class DeviceDialog<R> extends Dialog<R> {
dialogPane.setPrefWidth(500); dialogPane.setPrefWidth(500);
dialogPane.setPrefHeight(360); dialogPane.setPrefHeight(360);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton == cancelButtonType ? null : getResult()); setResultConverter(dialogButton -> dialogButton == cancelButtonType ? null : getResult());
} }

View file

@ -30,6 +30,7 @@ public class KeystorePassphraseDialog extends Dialog<String> {
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);
dialogPane.setPrefWidth(380); dialogPane.setPrefWidth(380);
dialogPane.setPrefHeight(200); dialogPane.setPrefHeight(200);
AppServices.moveToActiveWindowScreen(this);
Glyph key = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.KEY); Glyph key = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.KEY);
key.setFontSize(50); key.setFontSize(50);

View file

@ -41,6 +41,7 @@ public class MasterKeyDisplayDialog extends Dialog<Void> {
dialogPane.setPrefWidth(500); dialogPane.setPrefWidth(500);
dialogPane.setPrefHeight(260); dialogPane.setPrefHeight(260);
AppServices.moveToActiveWindowScreen(this);
Platform.runLater(() -> keystoreAccordion.setExpandedPane(keystorePane)); Platform.runLater(() -> keystoreAccordion.setExpandedPane(keystorePane));
} }

View file

@ -185,6 +185,7 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
EventManager.get().unregister(this); EventManager.get().unregister(this);
}); });
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton == signButtonType || dialogButton == verifyButtonType ? ButtonBar.ButtonData.APPLY : ButtonBar.ButtonData.OK_DONE); setResultConverter(dialogButton -> dialogButton == signButtonType || dialogButton == verifyButtonType ? ButtonBar.ButtonData.APPLY : ButtonBar.ButtonData.OK_DONE);
} }
@ -275,6 +276,7 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
alert.setTitle("Verification Succeeded"); alert.setTitle("Verification Succeeded");
alert.setHeaderText("Verification Succeeded"); alert.setHeaderText("Verification Succeeded");
alert.setContentText("The signature verified against the message."); alert.setContentText("The signature verified against the message.");
AppServices.moveToActiveWindowScreen(alert);
alert.showAndWait(); alert.showAndWait();
} else { } else {
AppServices.showErrorDialog("Verification failed", "The provided signature did not match the message for this address."); AppServices.showErrorDialog("Verification failed", "The provided signature did not match the message for this address.");

View file

@ -96,6 +96,7 @@ public class QRDisplayDialog extends Dialog<UR> {
dialogPane.setPrefWidth(40 + QR_WIDTH + 40); dialogPane.setPrefWidth(40 + QR_WIDTH + 40);
dialogPane.setPrefHeight(40 + QR_HEIGHT + 85); dialogPane.setPrefHeight(40 + QR_HEIGHT + 85);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? ur : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? ur : null);
} }
@ -118,6 +119,7 @@ public class QRDisplayDialog extends Dialog<UR> {
dialogPane.getButtonTypes().addAll(cancelButtonType); dialogPane.getButtonTypes().addAll(cancelButtonType);
dialogPane.setPrefWidth(40 + QR_WIDTH + 40); dialogPane.setPrefWidth(40 + QR_WIDTH + 40);
dialogPane.setPrefHeight(40 + QR_HEIGHT + 85); dialogPane.setPrefHeight(40 + QR_HEIGHT + 85);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? ur : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? ur : null);
} }

View file

@ -137,6 +137,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> {
dialogPane.getButtonTypes().addAll(hdButtonType, cancelButtonType); dialogPane.getButtonTypes().addAll(hdButtonType, cancelButtonType);
dialogPane.setPrefWidth(646); dialogPane.setPrefWidth(646);
dialogPane.setPrefHeight(webcamResolutionProperty.get() == WebcamResolution.HD ? 490 : 590); dialogPane.setPrefHeight(webcamResolutionProperty.get() == WebcamResolution.HD ? 490 : 590);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? result : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? result : null);
} }

View file

@ -44,6 +44,7 @@ public class SeedDisplayDialog extends Dialog<Void> {
dialogPane.setPrefWidth(500); dialogPane.setPrefWidth(500);
dialogPane.setPrefHeight(150 + height); dialogPane.setPrefHeight(150 + height);
AppServices.moveToActiveWindowScreen(this);
Platform.runLater(() -> keystoreAccordion.setExpandedPane(keystorePane)); Platform.runLater(() -> keystoreAccordion.setExpandedPane(keystorePane));
} }

View file

@ -59,6 +59,7 @@ public class TextAreaDialog extends Dialog<String> {
dialogPane.setPrefWidth(700); dialogPane.setPrefWidth(700);
dialogPane.setPrefHeight(400); dialogPane.setPrefHeight(400);
AppServices.moveToActiveWindowScreen(this);
} }
public final TextArea getEditor() { public final TextArea getEditor() {

View file

@ -63,5 +63,6 @@ public class TransactionIdDialog extends Dialog<Sha256Hash> {
txid.setPromptText("f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16"); txid.setPromptText("f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16");
Platform.runLater(txid::requestFocus); Platform.runLater(txid::requestFocus);
setResultConverter(dialogButton -> dialogButton == okButtonType ? Sha256Hash.wrap(txid.getText()) : null); setResultConverter(dialogButton -> dialogButton == okButtonType ? Sha256Hash.wrap(txid.getText()) : null);
AppServices.moveToActiveWindowScreen(this);
} }
} }

View file

@ -31,6 +31,7 @@ public class WalletBirthDateDialog extends Dialog<Date> {
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL);
dialogPane.setPrefWidth(420); dialogPane.setPrefWidth(420);
dialogPane.setPrefHeight(200); dialogPane.setPrefHeight(200);
AppServices.moveToActiveWindowScreen(this);
Glyph wallet = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.HISTORY); Glyph wallet = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.HISTORY);
wallet.setFontSize(50); wallet.setFontSize(50);

View file

@ -59,6 +59,7 @@ public class WalletExportDialog extends Dialog<Wallet> {
dialogPane.getButtonTypes().addAll(cancelButtonType); dialogPane.getButtonTypes().addAll(cancelButtonType);
dialogPane.setPrefWidth(500); dialogPane.setPrefWidth(500);
dialogPane.setPrefHeight(480); dialogPane.setPrefHeight(480);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
} }

View file

@ -73,6 +73,7 @@ public class WalletImportDialog extends Dialog<Wallet> {
dialogPane.setPrefWidth(500); dialogPane.setPrefWidth(500);
dialogPane.setPrefHeight(500); dialogPane.setPrefHeight(500);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
} }

View file

@ -44,6 +44,7 @@ public class WalletNameDialog extends Dialog<WalletNameDialog.NameAndBirthDate>
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL);
dialogPane.setPrefWidth(460); dialogPane.setPrefWidth(460);
dialogPane.setPrefHeight(requestBirthDate ? 250 : 200); dialogPane.setPrefHeight(requestBirthDate ? 250 : 200);
AppServices.moveToActiveWindowScreen(this);
Glyph wallet = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.WALLET); Glyph wallet = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.WALLET);
wallet.setFontSize(50); wallet.setFontSize(50);

View file

@ -45,6 +45,7 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL);
dialogPane.setPrefWidth(380); dialogPane.setPrefWidth(380);
dialogPane.setPrefHeight(260); dialogPane.setPrefHeight(260);
AppServices.moveToActiveWindowScreen(this);
Glyph lock = new Glyph("FontAwesome", FontAwesome.Glyph.LOCK); Glyph lock = new Glyph("FontAwesome", FontAwesome.Glyph.LOCK);
lock.setFontSize(50); lock.setFontSize(50);

View file

@ -46,6 +46,7 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
dialogPane.getButtonTypes().addAll(watchOnlyButtonType, cancelButtonType); dialogPane.getButtonTypes().addAll(watchOnlyButtonType, cancelButtonType);
dialogPane.setPrefWidth(650); dialogPane.setPrefWidth(650);
dialogPane.setPrefHeight(620); dialogPane.setPrefHeight(620);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? getWatchOnlyKeystore() : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? getWatchOnlyKeystore() : null);
} catch(IOException e) { } catch(IOException e) {

View file

@ -48,6 +48,7 @@ public class PreferencesDialog extends Dialog<Boolean> {
dialogPane.setPrefWidth(750); dialogPane.setPrefWidth(750);
dialogPane.setPrefHeight(630); dialogPane.setPrefHeight(630);
AppServices.moveToActiveWindowScreen(this);
preferencesController.reconnectOnClosingProperty().set(AppServices.isConnecting() || AppServices.isConnected()); preferencesController.reconnectOnClosingProperty().set(AppServices.isConnecting() || AppServices.isConnected());
setOnCloseRequest(event -> { setOnCloseRequest(event -> {

View file

@ -34,6 +34,7 @@ public class AdvancedDialog extends Dialog<Boolean> {
dialogPane.setPrefWidth(400); dialogPane.setPrefWidth(400);
dialogPane.setPrefHeight(300); dialogPane.setPrefHeight(300);
AppServices.moveToActiveWindowScreen(this);
setResultConverter(dialogButton -> dialogButton == passwordButtonType); setResultConverter(dialogButton -> dialogButton == passwordButtonType);
} }

View file

@ -738,7 +738,7 @@ public class SendController extends WalletFormController implements Initializabl
long thisFee = walletTransaction.getFee(); long thisFee = walletTransaction.getFee();
double thisSize = walletTransaction.getTransaction().getVirtualSize(); double thisSize = walletTransaction.getTransaction().getVirtualSize();
double effectiveRate = (utxoTxFee + thisFee) / (utxoTxSize + thisSize); double effectiveRate = (utxoTxFee + thisFee) / (utxoTxSize + thisSize);
Tooltip tooltip = new Tooltip(String.format("%.2f", effectiveRate) + " sats/vB effective rate"); Tooltip tooltip = new Tooltip("Child Pays For Parent\n" + String.format("%.2f", effectiveRate) + " sats/vB effective rate");
cpfpFeeRate.setTooltip(tooltip); cpfpFeeRate.setTooltip(tooltip);
cpfpFeeRate.setVisible(true); cpfpFeeRate.setVisible(true);
} else { } else {