Compare commits

...
10 Commits
27 changed files with 162 additions and 265 deletions

No files matched your search

@@ -17,23 +17,19 @@
*/
package org.jackhuang.hmcl;
import static org.jackhuang.hmcl.util.Lang.thread;
import static org.jackhuang.hmcl.util.Logging.LOG;
import com.jfoenix.concurrency.JFXUtilities;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.stage.Stage;
import org.jackhuang.hmcl.setting.ConfigHolder;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.util.*;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.URISyntaxException;
import java.net.URL;
@@ -42,7 +38,6 @@ import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public final class Launcher extends Application {
@@ -58,24 +53,7 @@ public final class Launcher extends Application {
primaryStage.setResizable(false);
primaryStage.setScene(Controllers.getScene());
UpdateChecker.updateChannelProperty().addListener(observable -> {
thread(() -> {
try {
UpdateChecker.checkUpdate();
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to check for update", e);
}
});
});
UpdateChecker.updateChannelProperty().bind(Bindings.createStringBinding(() -> {
switch (ConfigHolder.config().getUpdateChannel()) {
case DEVELOPMENT:
return UpdateChecker.CHANNEL_DEV;
default:
return UpdateChecker.CHANNEL_STABLE;
}
}, ConfigHolder.config().updateChannelProperty()));
UpdateChecker.init();
primaryStage.show();
} catch (Throwable e) {
@@ -30,6 +30,7 @@ import org.hildan.fxgson.creators.ObservableSetCreator;
import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.upgrade.UpdateChannel;
import org.jackhuang.hmcl.util.EnumOrdinalDeserializer;
import org.jackhuang.hmcl.util.FileTypeAdapter;
import org.jackhuang.hmcl.util.ObservableHelper;
@@ -150,7 +151,7 @@ public final class Config implements Cloneable, Observable {
private ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList();
@SerializedName("updateChannel")
private ObjectProperty<EnumUpdateChannel> updateChannel = new SimpleObjectProperty<>(EnumUpdateChannel.STABLE);
private ObjectProperty<UpdateChannel> updateChannel = new SimpleObjectProperty<>(UpdateChannel.STABLE);
@SerializedName("_version")
private IntegerProperty configVersion = new SimpleIntegerProperty(0);
@@ -438,15 +439,15 @@ public final class Config implements Cloneable, Observable {
return authlibInjectorServers;
}
public EnumUpdateChannel getUpdateChannel() {
public UpdateChannel getUpdateChannel() {
return updateChannel.get();
}
public ObjectProperty<EnumUpdateChannel> updateChannelProperty() {
public ObjectProperty<UpdateChannel> updateChannelProperty() {
return updateChannel;
}
public void setUpdateChannel(EnumUpdateChannel updateChannel) {
public void setUpdateChannel(UpdateChannel updateChannel) {
this.updateChannel.set(updateChannel);
}
}
@@ -46,6 +46,7 @@ import org.jackhuang.hmcl.ui.construct.FontComboBox;
import org.jackhuang.hmcl.ui.construct.MultiFileItem;
import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
import org.jackhuang.hmcl.upgrade.UpdateChannel;
import org.jackhuang.hmcl.upgrade.RemoteVersion;
import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.upgrade.UpdateHandler;
@@ -242,24 +243,24 @@ public final class SettingsPage extends StackPane implements DecoratorPage {
lblUpdateNote.setWrappingWidth(470);
ObjectProperty<EnumUpdateChannel> updateChannel = new SimpleObjectProperty<EnumUpdateChannel>() {
ObjectProperty<UpdateChannel> updateChannel = new SimpleObjectProperty<UpdateChannel>() {
@Override
protected void invalidated() {
EnumUpdateChannel updateChannel = Objects.requireNonNull(get());
chkUpdateDev.setSelected(updateChannel == EnumUpdateChannel.DEVELOPMENT);
chkUpdateStable.setSelected(updateChannel == EnumUpdateChannel.STABLE);
UpdateChannel updateChannel = Objects.requireNonNull(get());
chkUpdateDev.setSelected(updateChannel == UpdateChannel.DEVELOPMENT);
chkUpdateStable.setSelected(updateChannel == UpdateChannel.STABLE);
}
};
ToggleGroup updateChannelGroup = new ToggleGroup();
chkUpdateDev.setToggleGroup(updateChannelGroup);
chkUpdateDev.setUserData(EnumUpdateChannel.DEVELOPMENT);
chkUpdateDev.setUserData(UpdateChannel.DEVELOPMENT);
chkUpdateStable.setToggleGroup(updateChannelGroup);
chkUpdateStable.setUserData(EnumUpdateChannel.STABLE);
chkUpdateStable.setUserData(UpdateChannel.STABLE);
updateChannelGroup.getToggles().forEach(
toggle -> toggle.selectedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
updateChannel.set((EnumUpdateChannel) toggle.getUserData());
updateChannel.set((UpdateChannel) toggle.getUserData());
}
}));
updateChannel.bindBidirectional(ConfigHolder.config().updateChannelProperty());
@@ -26,17 +26,17 @@ import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask;
import org.jackhuang.hmcl.setting.EnumGameDirectory;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.ui.export.ExportWizardProvider;
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
import org.jackhuang.hmcl.util.FileUtils;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import java.io.File;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class VersionPage extends StackPane implements DecoratorPage {
private final StringProperty title = new SimpleStringProperty(this, "title", null);
@@ -188,7 +188,11 @@ public final class VersionPage extends StackPane implements DecoratorPage {
public static void deleteVersion(Profile profile, String version) {
boolean isIndependent = profile.getVersionSetting(version).getGameDirType() == EnumGameDirectory.VERSION_FOLDER;
Controllers.confirmDialog(i18n(isIndependent ? "version.manage.remove.confirm.independent" : "version.manage.remove.confirm", version), i18n("message.confirm"), () -> {
boolean isMovingToTrashSupported = FileUtils.isMovingToTrashSupported();
String message = isIndependent ? i18n("version.manage.remove.confirm.independent", version) :
isMovingToTrashSupported ? i18n("version.manage.remove.confirm.trash", version, version + "_removed") :
i18n("version.manage.remove.confirm", version);
Controllers.confirmDialog(message, i18n("message.confirm"), () -> {
if (profile.getRepository().removeVersionFromDisk(version)) {
profile.getRepository().refreshVersionsAsync().start();
Controllers.navigate(null);
@@ -100,8 +100,6 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh
private List<VersionsPageItem> loadVersions() {
return versionList.getVersions(gameVersion).stream()
.filter(it -> {
if (it.getVersionType() == null)
return true;
switch (it.getVersionType()) {
case RELEASE:
return chkRelease.isSelected();
@@ -1,6 +1,6 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <[email protected]>
* Copyright (C) 2018 huangyuhui <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,9 +15,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.setting;
package org.jackhuang.hmcl.upgrade;
public enum EnumUpdateChannel {
STABLE,
DEVELOPMENT
public enum UpdateChannel {
STABLE("stable"),
DEVELOPMENT("dev");
public final String channelName;
UpdateChannel(String channelName) {
this.channelName = channelName;
}
}
@@ -17,16 +17,20 @@
*/
package org.jackhuang.hmcl.upgrade;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
import static org.jackhuang.hmcl.util.Lang.mapOf;
import static org.jackhuang.hmcl.util.Lang.thread;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.Pair.pair;
import static org.jackhuang.hmcl.util.VersionNumber.asVersion;
import java.io.IOException;
import java.util.logging.Level;
import com.jfoenix.concurrency.JFXUtilities;
import javafx.beans.property.*;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.util.ImmediateStringProperty;
import org.jackhuang.hmcl.setting.ConfigHolder;
import org.jackhuang.hmcl.util.NetworkUtils;
import javafx.application.Platform;
@@ -37,11 +41,6 @@ import javafx.beans.value.ObservableBooleanValue;
public final class UpdateChecker {
private UpdateChecker() {}
public static final String CHANNEL_STABLE = "stable";
public static final String CHANNEL_DEV = "dev";
private static StringProperty updateChannel = new ImmediateStringProperty(null, "updateChannel", CHANNEL_STABLE);
private static ObjectProperty<RemoteVersion> latestVersion = new SimpleObjectProperty<>();
private static BooleanBinding outdated = Bindings.createBooleanBinding(
() -> {
@@ -55,16 +54,9 @@ public final class UpdateChecker {
latestVersion);
private static ReadOnlyBooleanWrapper checkingUpdate = new ReadOnlyBooleanWrapper(false);
public static String getUpdateChannel() {
return updateChannel.get();
}
public static void setUpdateChannel(String updateChannel) {
UpdateChecker.updateChannel.set(updateChannel);
}
public static StringProperty updateChannelProperty() {
return updateChannel;
public static void init() {
ConfigHolder.config().updateChannelProperty().addListener(onInvalidating(UpdateChecker::requestCheckUpdate));
requestCheckUpdate();
}
public static RemoteVersion getLatestVersion() {
@@ -91,35 +83,53 @@ public final class UpdateChecker {
return checkingUpdate.getReadOnlyProperty();
}
public static void checkUpdate() throws IOException {
private static RemoteVersion checkUpdate(UpdateChannel channel) throws IOException {
if (!IntegrityChecker.isSelfVerified()) {
return;
throw new IOException("Self verification failed");
}
JFXUtilities.runInFXAndWait(() -> {
checkingUpdate.set(true);
});
String url = NetworkUtils.withQuery(Metadata.UPDATE_URL, mapOf(
pair("version", Metadata.VERSION),
pair("channel", channel.channelName)));
try {
String channel = getUpdateChannel();
String url = NetworkUtils.withQuery(Metadata.UPDATE_URL, mapOf(
pair("version", Metadata.VERSION),
pair("channel", channel)));
RemoteVersion fetched = RemoteVersion.fetch(url);
Platform.runLater(() -> {
if (channel.equals(getUpdateChannel())) {
latestVersion.set(fetched);
}
});
} finally {
Platform.runLater(() -> checkingUpdate.set(false));
}
return RemoteVersion.fetch(url);
}
private static boolean isDevelopmentVersion(String version) {
return version.contains("@") || // eg. @develop@
version.contains("SNAPSHOT"); // eg. 3.1.SNAPSHOT
}
public static void requestCheckUpdate() {
Platform.runLater(() -> {
if (isCheckingUpdate())
return;
checkingUpdate.set(true);
UpdateChannel channel = config().getUpdateChannel();
thread(() -> {
RemoteVersion result = null;
try {
result = checkUpdate(channel);
LOG.info("Latest version (" + channel + ") is " + result);
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to check for update", e);
}
RemoteVersion finalResult = result;
Platform.runLater(() -> {
checkingUpdate.set(false);
if (finalResult != null) {
if (channel.equals(config().getUpdateChannel())) {
latestVersion.set(finalResult);
} else {
// the channel has been changed during the period
// check update again
requestCheckUpdate();
}
}
});
});
});
}
}
@@ -334,7 +334,8 @@ version.launch_script.save=Save the launch script
version.launch_script.success=Finished script creation, %s.
version.manage.redownload_assets_index=Redownload Assets Index
version.manage.remove=Delete this game
version.manage.remove.confirm=Sure to remove game %s?
version.manage.remove.confirm=Sure to remove game %s? You cannot restore this game again!
version.manage.remove.confirm.trash=Sure to remove game %s? You can restore the game with the name of %s in your system trash.
version.manage.remove.confirm.independent=Since this game is in independent mode, deleting this game will result in all saved worlds belonging to this game removed simultaneously. Sure to remove game %s?
version.manage.remove_libraries=Delete library files
version.manage.rename=Rename this game
@@ -334,7 +334,8 @@ version.launch_script.save=保存啓動腳本
version.launch_script.success=啓動腳本已生成完畢:%s
version.manage.redownload_assets_index=重新下載資源配置(assets_index.json)
version.manage.remove=刪除該版本
version.manage.remove.confirm=真的要刪除版本 %s 嗎?
version.manage.remove.confirm=真的要刪除版本 %s 嗎?你將無法找回被刪除的文件!
version.manage.remove.confirm.trash=真的要刪除版本 %s 嗎?你可以在系統的回收站中恢復文件夾 %s 來找回該版本。
version.manage.remove.confirm.independent=由於該遊戲使用了版本隔離,所以刪除該版本將導致該遊戲的存檔等數據一同被刪除,真的要刪除版本 %s 嗎?
version.manage.remove_libraries=刪除所有庫文件
version.manage.rename=重命名該版本
@@ -334,7 +334,8 @@ version.launch_script.save=保存启动脚本
version.launch_script.success=启动脚本已生成完毕:%s
version.manage.redownload_assets_index=重新下载资源配置(assets_index.json)
version.manage.remove=删除该版本
version.manage.remove.confirm=真的要删除版本 %s 吗?
version.manage.remove.confirm=真的要删除版本 %s 吗?你将无法找回被删除的文件!
version.manage.remove.confirm.trash=真的要删除版本 %s 吗?你可以在系统的回收站中恢复文件夹 %s 来找回该版本。
version.manage.remove.confirm.independent=由于该游戏使用了版本隔离,所以删除该版本将导致该游戏的存档等数据一同被删除,真的要删除版本 %s 吗?
version.manage.remove_libraries=删除所有库文件
version.manage.rename=重命名该版本
@@ -94,7 +94,9 @@ public class MaintainTask extends TaskResult<Version> {
args.add("optifine.OptiFineForgeTweaker");
}
return version.setMinecraftArguments(new CommandBuilder().addAll(args).toString());
// Since $ will be escaped in linux, and our maintain of minecraftArgument will not cause escaping,
// so we regenerate the minecraftArgument without escaping.
return version.setMinecraftArguments(new CommandBuilder().addAllWithoutParsing(args).toString());
}
@Override
@@ -42,7 +42,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
* @param url the installer or universal jar URL.
*/
public RemoteVersion(String gameVersion, String selfVersion, String url) {
this(gameVersion, selfVersion, url, null);
this(gameVersion, selfVersion, url, Type.UNCATEGORIZED);
}
/**
@@ -56,7 +56,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
this.gameVersion = Objects.requireNonNull(gameVersion);
this.selfVersion = Objects.requireNonNull(selfVersion);
this.url = Objects.requireNonNull(url);
this.type = type;
this.type = Objects.requireNonNull(type);
}
public String getGameVersion() {
@@ -100,6 +100,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
}
public enum Type {
UNCATEGORIZED,
RELEASE,
SNAPSHOT,
OLD
@@ -34,7 +34,7 @@ public final class GameRemoteVersion extends RemoteVersion {
private final Date time;
public GameRemoteVersion(String gameVersion, String selfVersion, String url, ReleaseType type, Date time) {
super(gameVersion, selfVersion, url);
super(gameVersion, selfVersion, url, getReleaseType(type));
this.type = type;
this.time = time;
}
@@ -54,4 +54,18 @@ public final class GameRemoteVersion extends RemoteVersion {
return ((GameRemoteVersion) o).getTime().compareTo(getTime());
}
private static Type getReleaseType(ReleaseType type) {
if (type == null) return Type.UNCATEGORIZED;
switch (type) {
case RELEASE:
return Type.RELEASE;
case SNAPSHOT:
return Type.SNAPSHOT;
case UNKNOWN:
return Type.UNCATEGORIZED;
default:
return Type.OLD;
}
}
}
@@ -142,7 +142,7 @@ public final class LibraryDownloadTask extends Task {
JarInputStream jar = new JarInputStream(new ByteArrayInputStream(data));
JarEntry entry = jar.getNextJarEntry();
while (entry != null) {
byte[] eData = IOUtils.readFullyAsByteArray(jar);
byte[] eData = IOUtils.readFullyWithoutClosing(jar);
if (entry.getName().equals("checksums.sha1")) {
hashes = new String(eData, Charset.forName("UTF-8")).split("\n");
}
@@ -82,7 +82,7 @@ public final class Arguments {
}
public static List<String> parseStringArguments(List<String> arguments, Map<String, String> keys) {
return arguments.stream().map(str -> keys.getOrDefault(str, str)).collect(Collectors.toList());
return arguments.stream().flatMap(str -> new StringArgument(str).toString(keys, Collections.emptyMap()).stream()).collect(Collectors.toList());
}
public static List<String> parseArguments(List<Argument> arguments, Map<String, String> keys) {
@@ -160,14 +160,18 @@ public class DefaultGameRepository implements GameRepository {
if (!file.renameTo(removedFile))
return false;
versions.remove(id);
if (FileUtils.isMovingToTrashSupported()) {
return FileUtils.moveToTrash(removedFile);
}
// remove json files first to ensure HMCL will not recognize this folder as a valid version.
List<File> jsons = FileUtils.listFilesByExtension(removedFile, "json");
jsons.forEach(f -> {
if (!f.delete())
Logging.LOG.warning("Unable to delete file " + f);
});
versions.remove(id);
// remove the version from version list regardless of whether the directory was removed successfully or not.
try {
FileUtils.deleteDirectory(removedFile);
@@ -223,6 +223,7 @@ public class Library implements Comparable<Library> {
obj.addProperty("name", src.getName());
obj.addProperty("url", src.url);
obj.add("downloads", context.serialize(src.downloads));
obj.add("checksums", context.serialize(src.getChecksums()));
obj.add("extract", context.serialize(src.extract));
obj.add("natives", context.serialize(src.natives, new TypeToken<Map<OperatingSystem, String>>() {
}.getType()));
@@ -65,7 +65,7 @@ public class RuledArgument implements Argument {
@Override
public List<String> toString(Map<String, String> keys, Map<String, Boolean> features) {
if (CompatibilityRule.appliesToCurrentEnvironment(rules) && value != null)
if (CompatibilityRule.appliesToCurrentEnvironment(rules, features) && value != null)
return value.stream()
.map(StringArgument::new)
.map(str -> str.toString(keys, features).get(0))
@@ -153,14 +153,6 @@ public class DefaultLauncher extends Launcher {
res.addAll(Arguments.parseStringArguments(version.getMinecraftArguments().map(StringUtils::tokenize).orElseGet(LinkedList::new), configuration));
// Optional Minecraft arguments
if (options.getHeight() != null && options.getHeight() != 0 && options.getWidth() != null && options.getWidth() != 0) {
res.add("--height");
res.add(options.getHeight().toString());
res.add("--width");
res.add(options.getWidth().toString());
}
if (StringUtils.isNotBlank(options.getServerIp())) {
String[] args = options.getServerIp().split(":");
res.add("--server");
@@ -249,7 +241,9 @@ public class DefaultLauncher extends Launcher {
pair("${game_directory}", repository.getRunDirectory(version.getId()).getAbsolutePath()),
pair("${user_type}", "mojang"),
pair("${assets_index_name}", version.getAssetIndex().getId()),
pair("${user_properties}", authInfo.getUserProperties())
pair("${user_properties}", authInfo.getUserProperties()),
pair("${resolution_width}", options.getWidth().toString()),
pair("${resolution_height}", options.getHeight().toString())
);
}
@@ -46,7 +46,7 @@ public final class ModInfo implements Comparable<ModInfo> {
}
public ModInfo(File file, String name, String description) {
this(file, name, description, "unknown", "unknown", "unknown", "");
this(file, name, description, "", "", "", "");
}
public ModInfo(File file, String name, String description, String authors, String version, String gameVersion, String url) {
@@ -20,8 +20,10 @@ package org.jackhuang.hmcl.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@@ -95,6 +97,30 @@ public final class FileUtils {
return Lang.test(() -> deleteDirectory(directory));
}
public static boolean moveToTrash(File file) {
try {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
Method moveToTrash = desktop.getClass().getMethod("moveToTrash", File.class);
moveToTrash.invoke(desktop, file);
return true;
} catch (Exception e) {
return false;
}
}
/**
* Check if {@code java.awt.Desktop.moveToTrash} exists.
* @return true if the method exists.
*/
public static boolean isMovingToTrashSupported() {
try {
java.awt.Desktop.class.getMethod("moveToTrash", File.class);
return true;
} catch (ReflectiveOperationException e) {
return false;
}
}
public static void cleanDirectory(File directory)
throws IOException {
if (!directory.exists()) {
@@ -31,6 +31,12 @@ public final class IOUtils {
public static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
public static byte[] readFullyWithoutClosing(InputStream stream) throws IOException {
ByteArrayOutputStream result = new ByteArrayOutputStream();
copyTo(stream, result);
return result.toByteArray();
}
public static ByteArrayOutputStream readFully(InputStream stream) throws IOException {
try (InputStream is = stream) {
ByteArrayOutputStream result = new ByteArrayOutputStream();
@@ -21,13 +21,11 @@ import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.util.Objects;
import java.util.function.Consumer;
/**
*
* @author huangyuhui
* @deprecated Use SimpleBooleanProperty instead
*/
@Deprecated
public class ImmediateBooleanProperty extends SimpleBooleanProperty {
@Override
@@ -48,31 +46,9 @@ public class ImmediateBooleanProperty extends SimpleBooleanProperty {
super.unbind();
}
private Consumer<Boolean> consumer = null;
private ChangeListener<Boolean> listener = null;
public void setChangedListener(Consumer<Boolean> consumer) {
this.consumer = Objects.requireNonNull(consumer);
this.listener = null;
}
public void setChangedListener(ChangeListener<Boolean> listener) {
this.consumer = null;
this.listener = Objects.requireNonNull(listener);
}
public void setChangedListenerAndOperate(Consumer<Boolean> listener) {
setChangedListener(listener);
listener.accept(get());
}
public ImmediateBooleanProperty(Object bean, String name, boolean initialValue) {
super(bean, name, initialValue);
ChangeListener<Boolean> changeListener = (a, b, newValue) -> {
if (consumer != null)
consumer.accept(newValue);
if (listener != null)
listener.changed(a, b, newValue);
};
addListener(changeListener);
}
@@ -1,81 +0,0 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2018 huangyuhui <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.util.Objects;
import java.util.function.Consumer;
/**
*
* @author huangyuhui
*/
public class ImmediateDoubleProperty extends SimpleDoubleProperty {
@Override
public void set(double newValue) {
super.get();
super.set(newValue);
}
@Override
public void bind(ObservableValue<? extends Number> newObservable) {
super.get();
super.bind(newObservable);
}
@Override
public void unbind() {
super.get();
super.unbind();
}
private Consumer<Double> consumer = null;
private ChangeListener<Number> listener = null;
public void setChangedListener(Consumer<Double> consumer) {
this.consumer = Objects.requireNonNull(consumer);
this.listener = null;
}
public void setChangedListener(ChangeListener<Number> listener) {
this.consumer = null;
this.listener = Objects.requireNonNull(listener);
}
public void setChangedListenerAndOperate(Consumer<Double> listener) {
setChangedListener(listener);
listener.accept(get());
}
public ImmediateDoubleProperty(Object bean, String name, double initialValue) {
super(bean, name, initialValue);
ChangeListener<Number> changeListener = (a, b, newValue) -> {
if (consumer != null)
consumer.accept(newValue.doubleValue());
if (listener != null)
listener.changed(a, b, newValue);
};
addListener(changeListener);
}
}
@@ -21,13 +21,11 @@ import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.util.Objects;
import java.util.function.Consumer;
/**
*
* @author huangyuhui
* @deprecated Use SimpleIntegerProperty instead
*/
@Deprecated
public class ImmediateIntegerProperty extends SimpleIntegerProperty {
@Override
@@ -48,31 +46,9 @@ public class ImmediateIntegerProperty extends SimpleIntegerProperty {
super.unbind();
}
private Consumer<Integer> consumer = null;
private ChangeListener<Number> listener = null;
public void setChangedListener(Consumer<Integer> consumer) {
this.consumer = Objects.requireNonNull(consumer);
this.listener = null;
}
public void setChangedListener(ChangeListener<Number> listener) {
this.consumer = null;
this.listener = Objects.requireNonNull(listener);
}
public void setChangedListenerAndOperate(Consumer<Integer> listener) {
setChangedListener(listener);
listener.accept(get());
}
public ImmediateIntegerProperty(Object bean, String name, int initialValue) {
super(bean, name, initialValue);
ChangeListener<Number> changeListener = (a, b, newValue) -> {
if (consumer != null)
consumer.accept(newValue.intValue());
if (listener != null)
listener.changed(a, b, newValue);
};
addListener(changeListener);
}
@@ -21,13 +21,11 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import java.util.Objects;
import java.util.function.Consumer;
/**
*
* @author huangyuhui
* @deprecated Use SimpleObjectProperty instead
*/
@Deprecated
public class ImmediateObjectProperty<T> extends SimpleObjectProperty<T> {
@Override
@@ -48,31 +46,9 @@ public class ImmediateObjectProperty<T> extends SimpleObjectProperty<T> {
super.unbind();
}
private Consumer<T> consumer = null;
private ChangeListener<T> listener = null;
public void setChangedListener(Consumer<T> consumer) {
this.consumer = Objects.requireNonNull(consumer);
this.listener = null;
}
public void setChangedListener(ChangeListener<T> listener) {
this.consumer = null;
this.listener = Objects.requireNonNull(listener);
}
public void setChangedListenerAndOperate(Consumer<T> listener) {
setChangedListener(listener);
listener.accept(get());
}
public ImmediateObjectProperty(Object bean, String name, T initialValue) {
super(bean, name, initialValue);
ChangeListener<T> changeListener = (a, b, newValue) -> {
if (consumer != null)
consumer.accept(newValue);
if (listener != null)
listener.changed(a, b, newValue);
};
addListener(changeListener);
}
@@ -25,9 +25,10 @@ import java.util.Objects;
import java.util.function.Consumer;
/**
*
* @author huangyuhui
* @deprecated Use SimpleStringProperty instead
*/
@Deprecated
public class ImmediateStringProperty extends SimpleStringProperty {
@Override