mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-12 05:16:13 -04:00
Submit the modification of JFXTextField after editing (#1869)
This commit is contained in:
parent
6611774aa9
commit
a94bb407e5
@ -72,6 +72,7 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -530,20 +531,85 @@ public final class FXUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindInt(JFXTextField textField, Property<Number> property) {
|
public static <T> void bind(JFXTextField textField, Property<T> property, StringConverter<T> converter) {
|
||||||
textField.textProperty().bindBidirectional(property, SafeStringConverter.fromInteger());
|
textField.setText(converter == null ? (String) property.getValue() : converter.toString(property.getValue()));
|
||||||
|
TextFieldBindingListener<T> listener = new TextFieldBindingListener<>(textField, property, converter);
|
||||||
|
textField.focusedProperty().addListener((ChangeListener<Boolean>) listener);
|
||||||
|
property.addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unbindInt(JFXTextField textField, Property<Number> property) {
|
public static void bindInt(JFXTextField textField, Property<Number> property) {
|
||||||
textField.textProperty().unbindBidirectional(property);
|
bind(textField, property, SafeStringConverter.fromInteger());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindString(JFXTextField textField, Property<String> property) {
|
public static void bindString(JFXTextField textField, Property<String> property) {
|
||||||
textField.textProperty().bindBidirectional(property);
|
bind(textField, property, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unbindString(JFXTextField textField, Property<String> property) {
|
public static void unbind(JFXTextField textField, Property<?> property) {
|
||||||
textField.textProperty().unbindBidirectional(property);
|
TextFieldBindingListener<?> listener = new TextFieldBindingListener<>(textField, property, null);
|
||||||
|
textField.focusedProperty().removeListener((ChangeListener<Boolean>) listener);
|
||||||
|
property.removeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TextFieldBindingListener<T> implements ChangeListener<Boolean>, InvalidationListener {
|
||||||
|
private final int hashCode;
|
||||||
|
private final WeakReference<JFXTextField> textFieldRef;
|
||||||
|
private final WeakReference<Property<T>> propertyRef;
|
||||||
|
private final StringConverter<T> converter;
|
||||||
|
|
||||||
|
TextFieldBindingListener(JFXTextField textField, Property<T> property, StringConverter<T> converter) {
|
||||||
|
this.textFieldRef = new WeakReference<>(textField);
|
||||||
|
this.propertyRef = new WeakReference<>(property);
|
||||||
|
this.converter = converter;
|
||||||
|
this.hashCode = System.identityHashCode(textField) ^ System.identityHashCode(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean focused) { // On TextField changed
|
||||||
|
JFXTextField textField = textFieldRef.get();
|
||||||
|
Property<T> property = this.propertyRef.get();
|
||||||
|
|
||||||
|
if (textField != null && property != null && oldValue == Boolean.TRUE && focused == Boolean.FALSE) {
|
||||||
|
if (textField.validate()) {
|
||||||
|
String newText = textField.getText();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T newValue = converter == null ? (T) newText : converter.fromString(newText);
|
||||||
|
|
||||||
|
if (!Objects.equals(newValue, property.getValue()))
|
||||||
|
property.setValue(newValue);
|
||||||
|
} else {
|
||||||
|
// Rollback to old value
|
||||||
|
invalidated(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidated(Observable observable) { // On property change
|
||||||
|
JFXTextField textField = textFieldRef.get();
|
||||||
|
Property<T> property = this.propertyRef.get();
|
||||||
|
|
||||||
|
if (textField != null && property != null) {
|
||||||
|
T value = property.getValue();
|
||||||
|
textField.setText(converter == null ? (String) value : converter.toString(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof TextFieldBindingListener))
|
||||||
|
return false;
|
||||||
|
TextFieldBindingListener<?> other = (TextFieldBindingListener<?>) obj;
|
||||||
|
return this.hashCode == other.hashCode
|
||||||
|
&& this.textFieldRef.get() == other.textFieldRef.get()
|
||||||
|
&& this.propertyRef.get() == other.propertyRef.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindBoolean(JFXToggleButton toggleButton, Property<Boolean> property) {
|
public static void bindBoolean(JFXToggleButton toggleButton, Property<Boolean> property) {
|
||||||
|
@ -132,7 +132,7 @@ public class DownloadSettingsPage extends StackPane {
|
|||||||
|
|
||||||
JFXTextField threadsField = new JFXTextField();
|
JFXTextField threadsField = new JFXTextField();
|
||||||
FXUtils.setLimitWidth(threadsField, 60);
|
FXUtils.setLimitWidth(threadsField, 60);
|
||||||
threadsField.textProperty().bindBidirectional(config().downloadThreadsProperty(), SafeStringConverter.fromInteger());
|
FXUtils.bindInt(threadsField, config().downloadThreadsProperty());
|
||||||
|
|
||||||
AtomicBoolean changedByTextField = new AtomicBoolean(false);
|
AtomicBoolean changedByTextField = new AtomicBoolean(false);
|
||||||
FXUtils.onChangeAndOperate(config().downloadThreadsProperty(), value -> {
|
FXUtils.onChangeAndOperate(config().downloadThreadsProperty(), value -> {
|
||||||
@ -213,7 +213,7 @@ public class DownloadSettingsPage extends StackPane {
|
|||||||
GridPane.setRowIndex(txtProxyHost, 1);
|
GridPane.setRowIndex(txtProxyHost, 1);
|
||||||
GridPane.setColumnIndex(txtProxyHost, 1);
|
GridPane.setColumnIndex(txtProxyHost, 1);
|
||||||
gridPane.getChildren().add(txtProxyHost);
|
gridPane.getChildren().add(txtProxyHost);
|
||||||
txtProxyHost.textProperty().bindBidirectional(config().proxyHostProperty());
|
FXUtils.bindString(txtProxyHost, config().proxyHostProperty());
|
||||||
txtProxyHost.getValidators().setAll(new NumberValidator(i18n("input.number"), false));
|
txtProxyHost.getValidators().setAll(new NumberValidator(i18n("input.number"), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +232,7 @@ public class DownloadSettingsPage extends StackPane {
|
|||||||
FXUtils.setValidateWhileTextChanged(txtProxyPort, true);
|
FXUtils.setValidateWhileTextChanged(txtProxyPort, true);
|
||||||
gridPane.getChildren().add(txtProxyPort);
|
gridPane.getChildren().add(txtProxyPort);
|
||||||
|
|
||||||
txtProxyPort.textProperty().bindBidirectional(config().proxyPortProperty(),
|
FXUtils.bind(txtProxyPort, config().proxyPortProperty(), SafeStringConverter.fromInteger()
|
||||||
SafeStringConverter.fromInteger()
|
|
||||||
.restrict(it -> it >= 0 && it <= 0xFFFF)
|
.restrict(it -> it >= 0 && it <= 0xFFFF)
|
||||||
.fallbackTo(0)
|
.fallbackTo(0)
|
||||||
.asPredicate(Validator.addTo(txtProxyPort)));
|
.asPredicate(Validator.addTo(txtProxyPort)));
|
||||||
@ -273,7 +272,7 @@ public class DownloadSettingsPage extends StackPane {
|
|||||||
GridPane.setRowIndex(txtProxyUsername, 0);
|
GridPane.setRowIndex(txtProxyUsername, 0);
|
||||||
GridPane.setColumnIndex(txtProxyUsername, 1);
|
GridPane.setColumnIndex(txtProxyUsername, 1);
|
||||||
authPane.getChildren().add(txtProxyUsername);
|
authPane.getChildren().add(txtProxyUsername);
|
||||||
txtProxyUsername.textProperty().bindBidirectional(config().proxyUserProperty());
|
FXUtils.bindString(txtProxyUsername, config().proxyUserProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -146,13 +146,11 @@ public class PersonalizationPage extends StackPane {
|
|||||||
|
|
||||||
JFXTextField txtLogFontSize = new JFXTextField();
|
JFXTextField txtLogFontSize = new JFXTextField();
|
||||||
FXUtils.setLimitWidth(txtLogFontSize, 50);
|
FXUtils.setLimitWidth(txtLogFontSize, 50);
|
||||||
txtLogFontSize.textProperty().bindBidirectional(config().fontSizeProperty(),
|
FXUtils.bind(txtLogFontSize, config().fontSizeProperty(), SafeStringConverter.fromFiniteDouble()
|
||||||
SafeStringConverter.fromFiniteDouble()
|
|
||||||
.restrict(it -> it > 0)
|
.restrict(it -> it > 0)
|
||||||
.fallbackTo(12.0)
|
.fallbackTo(12.0)
|
||||||
.asPredicate(Validator.addTo(txtLogFontSize)));
|
.asPredicate(Validator.addTo(txtLogFontSize)));
|
||||||
|
|
||||||
|
|
||||||
hBox.getChildren().setAll(cboLogFont, txtLogFontSize);
|
hBox.getChildren().setAll(cboLogFont, txtLogFontSize);
|
||||||
|
|
||||||
borderPane.setRight(hBox);
|
borderPane.setRight(hBox);
|
||||||
|
@ -43,7 +43,6 @@ import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
|||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
||||||
import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
|
|
||||||
import org.jackhuang.hmcl.util.platform.Architecture;
|
import org.jackhuang.hmcl.util.platform.Architecture;
|
||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
@ -259,7 +258,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
JFXTextField txtMaxMemory = new JFXTextField();
|
JFXTextField txtMaxMemory = new JFXTextField();
|
||||||
FXUtils.setLimitWidth(txtMaxMemory, 60);
|
FXUtils.setLimitWidth(txtMaxMemory, 60);
|
||||||
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
|
FXUtils.setValidateWhileTextChanged(txtMaxMemory, true);
|
||||||
txtMaxMemory.textProperty().bindBidirectional(maxMemory, SafeStringConverter.fromInteger());
|
FXUtils.bindInt(txtMaxMemory, maxMemory);
|
||||||
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
|
txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false));
|
||||||
|
|
||||||
lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MB"));
|
lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MB"));
|
||||||
@ -628,19 +627,19 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
|
|
||||||
// unbind data fields
|
// unbind data fields
|
||||||
if (lastVersionSetting != null) {
|
if (lastVersionSetting != null) {
|
||||||
FXUtils.unbindInt(txtWidth, lastVersionSetting.widthProperty());
|
FXUtils.unbind(txtWidth, lastVersionSetting.widthProperty());
|
||||||
FXUtils.unbindInt(txtHeight, lastVersionSetting.heightProperty());
|
FXUtils.unbind(txtHeight, lastVersionSetting.heightProperty());
|
||||||
maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
|
maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty());
|
||||||
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
|
javaCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.javaDirProperty());
|
||||||
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
|
gameDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.gameDirProperty());
|
||||||
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
|
nativesDirCustomOption.valueProperty().unbindBidirectional(lastVersionSetting.nativesDirProperty());
|
||||||
FXUtils.unbindString(txtJVMArgs, lastVersionSetting.javaArgsProperty());
|
FXUtils.unbind(txtJVMArgs, lastVersionSetting.javaArgsProperty());
|
||||||
FXUtils.unbindString(txtGameArgs, lastVersionSetting.minecraftArgsProperty());
|
FXUtils.unbind(txtGameArgs, lastVersionSetting.minecraftArgsProperty());
|
||||||
FXUtils.unbindString(txtMetaspace, lastVersionSetting.permSizeProperty());
|
FXUtils.unbind(txtMetaspace, lastVersionSetting.permSizeProperty());
|
||||||
FXUtils.unbindString(txtWrapper, lastVersionSetting.wrapperProperty());
|
FXUtils.unbind(txtWrapper, lastVersionSetting.wrapperProperty());
|
||||||
FXUtils.unbindString(txtPreLaunchCommand, lastVersionSetting.preLaunchCommandProperty());
|
FXUtils.unbind(txtPreLaunchCommand, lastVersionSetting.preLaunchCommandProperty());
|
||||||
FXUtils.unbindString(txtPostExitCommand, lastVersionSetting.postExitCommandProperty());
|
FXUtils.unbind(txtPostExitCommand, lastVersionSetting.postExitCommandProperty());
|
||||||
FXUtils.unbindString(txtServerIP, lastVersionSetting.serverIpProperty());
|
FXUtils.unbind(txtServerIP, lastVersionSetting.serverIpProperty());
|
||||||
FXUtils.unbindBoolean(chkAutoAllocate, lastVersionSetting.autoMemoryProperty());
|
FXUtils.unbindBoolean(chkAutoAllocate, lastVersionSetting.autoMemoryProperty());
|
||||||
FXUtils.unbindBoolean(chkFullscreen, lastVersionSetting.fullscreenProperty());
|
FXUtils.unbindBoolean(chkFullscreen, lastVersionSetting.fullscreenProperty());
|
||||||
noGameCheckPane.selectedProperty().unbindBidirectional(lastVersionSetting.notCheckGameProperty());
|
noGameCheckPane.selectedProperty().unbindBidirectional(lastVersionSetting.notCheckGameProperty());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user