mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 05:46:59 -04:00
Add selectedMinecraftVersion
This commit is contained in:
parent
9c149f3529
commit
1566e069ed
@ -19,14 +19,18 @@ package org.jackhuang.hmcl.setting;
|
|||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import javafx.beans.InvalidationListener;
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.*;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.event.EventBus;
|
||||||
|
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||||
import org.jackhuang.hmcl.game.HMCLDependencyManager;
|
import org.jackhuang.hmcl.game.HMCLDependencyManager;
|
||||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||||
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.mod.ModManager;
|
import org.jackhuang.hmcl.mod.ModManager;
|
||||||
|
import org.jackhuang.hmcl.ui.WeakListenerHelper;
|
||||||
import org.jackhuang.hmcl.util.ImmediateObjectProperty;
|
import org.jackhuang.hmcl.util.ImmediateObjectProperty;
|
||||||
import org.jackhuang.hmcl.util.ImmediateStringProperty;
|
import org.jackhuang.hmcl.util.ImmediateStringProperty;
|
||||||
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.ToStringBuilder;
|
import org.jackhuang.hmcl.util.ToStringBuilder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -38,66 +42,80 @@ import java.util.Optional;
|
|||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
public final class Profile {
|
public final class Profile {
|
||||||
|
private final WeakListenerHelper helper = new WeakListenerHelper();
|
||||||
private final HMCLGameRepository repository;
|
private final HMCLGameRepository repository;
|
||||||
private final ModManager modManager;
|
private final ModManager modManager;
|
||||||
|
|
||||||
private final ImmediateObjectProperty<File> gameDirProperty;
|
private final StringProperty selectedVersion = new SimpleStringProperty();
|
||||||
|
|
||||||
public ImmediateObjectProperty<File> gameDirProperty() {
|
public StringProperty selectedVersionProperty() {
|
||||||
return gameDirProperty;
|
return selectedVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSelectedVersion() {
|
||||||
|
return selectedVersion.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedVersion(String selectedVersion) {
|
||||||
|
this.selectedVersion.set(selectedVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ObjectProperty<File> gameDir;
|
||||||
|
|
||||||
|
public ObjectProperty<File> gameDirProperty() {
|
||||||
|
return gameDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getGameDir() {
|
public File getGameDir() {
|
||||||
return gameDirProperty.get();
|
return gameDir.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGameDir(File gameDir) {
|
public void setGameDir(File gameDir) {
|
||||||
gameDirProperty.set(gameDir);
|
this.gameDir.set(gameDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmediateObjectProperty<VersionSetting> globalProperty = new ImmediateObjectProperty<>(this, "global", new VersionSetting());
|
private final ObjectProperty<VersionSetting> global = new ImmediateObjectProperty<>(this, "global", new VersionSetting());
|
||||||
|
|
||||||
public ImmediateObjectProperty<VersionSetting> globalProperty() {
|
public ObjectProperty<VersionSetting> globalProperty() {
|
||||||
return globalProperty;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VersionSetting getGlobal() {
|
public VersionSetting getGlobal() {
|
||||||
return globalProperty.get();
|
return global.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setGlobal(VersionSetting global) {
|
private void setGlobal(VersionSetting global) {
|
||||||
if (global == null)
|
if (global == null)
|
||||||
global = new VersionSetting();
|
global = new VersionSetting();
|
||||||
globalProperty.set(global);
|
this.global.set(global);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmediateStringProperty nameProperty;
|
private final ImmediateStringProperty name;
|
||||||
|
|
||||||
public ImmediateStringProperty nameProperty() {
|
public ImmediateStringProperty nameProperty() {
|
||||||
return nameProperty;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return nameProperty.get();
|
return name.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
nameProperty.set(name);
|
this.name.set(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BooleanProperty useRelativePathProperty = new SimpleBooleanProperty(this, "useRelativePath", false);
|
private BooleanProperty useRelativePath = new SimpleBooleanProperty(this, "useRelativePath", false);
|
||||||
|
|
||||||
public BooleanProperty useRelativePathProperty() {
|
public BooleanProperty useRelativePathProperty() {
|
||||||
return useRelativePathProperty();
|
return useRelativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUseRelativePath() {
|
public boolean isUseRelativePath() {
|
||||||
return useRelativePathProperty.get();
|
return useRelativePath.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseRelativePath(boolean useRelativePath) {
|
public void setUseRelativePath(boolean useRelativePath) {
|
||||||
useRelativePathProperty.set(useRelativePath);
|
this.useRelativePath.set(useRelativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Profile(String name) {
|
public Profile(String name) {
|
||||||
@ -105,12 +123,26 @@ public final class Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Profile(String name, File initialGameDir) {
|
public Profile(String name, File initialGameDir) {
|
||||||
nameProperty = new ImmediateStringProperty(this, "name", name);
|
this.name = new ImmediateStringProperty(this, "name", name);
|
||||||
gameDirProperty = new ImmediateObjectProperty<>(this, "gameDir", initialGameDir);
|
gameDir = new ImmediateObjectProperty<>(this, "gameDir", initialGameDir);
|
||||||
repository = new HMCLGameRepository(this, initialGameDir);
|
repository = new HMCLGameRepository(this, initialGameDir);
|
||||||
modManager = new ModManager(repository);
|
modManager = new ModManager(repository);
|
||||||
|
|
||||||
gameDirProperty.addListener((a, b, newValue) -> repository.changeDirectory(newValue));
|
gameDir.addListener((a, b, newValue) -> repository.changeDirectory(newValue));
|
||||||
|
selectedVersion.addListener(o -> checkSelectedVersion());
|
||||||
|
helper.add(EventBus.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerWeak(event -> checkSelectedVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSelectedVersion() {
|
||||||
|
if (!repository.isLoaded()) return;
|
||||||
|
String newValue = selectedVersion.get();
|
||||||
|
if (!repository.hasVersion(newValue)) {
|
||||||
|
Optional<String> version = repository.getVersions().stream().findFirst().map(Version::getId);
|
||||||
|
if (version.isPresent())
|
||||||
|
selectedVersion.setValue(version.get());
|
||||||
|
else if (StringUtils.isNotBlank(newValue))
|
||||||
|
selectedVersion.setValue(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HMCLGameRepository getRepository() {
|
public HMCLGameRepository getRepository() {
|
||||||
@ -171,11 +203,12 @@ public final class Profile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addPropertyChangedListener(InvalidationListener listener) {
|
public void addPropertyChangedListener(InvalidationListener listener) {
|
||||||
nameProperty.addListener(listener);
|
name.addListener(listener);
|
||||||
globalProperty.addListener(listener);
|
global.addListener(listener);
|
||||||
gameDirProperty.addListener(listener);
|
gameDir.addListener(listener);
|
||||||
useRelativePathProperty.addListener(listener);
|
useRelativePath.addListener(listener);
|
||||||
globalProperty.get().addPropertyChangedListener(listener);
|
global.get().addPropertyChangedListener(listener);
|
||||||
|
selectedVersion.addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Serializer implements JsonSerializer<Profile>, JsonDeserializer<Profile> {
|
public static final class Serializer implements JsonSerializer<Profile>, JsonDeserializer<Profile> {
|
||||||
@ -193,6 +226,7 @@ public final class Profile {
|
|||||||
jsonObject.add("global", context.serialize(src.getGlobal()));
|
jsonObject.add("global", context.serialize(src.getGlobal()));
|
||||||
jsonObject.addProperty("gameDir", src.getGameDir().getPath());
|
jsonObject.addProperty("gameDir", src.getGameDir().getPath());
|
||||||
jsonObject.addProperty("useRelativePath", src.isUseRelativePath());
|
jsonObject.addProperty("useRelativePath", src.isUseRelativePath());
|
||||||
|
jsonObject.addProperty("selectedMinecraftVersion", src.getSelectedVersion());
|
||||||
|
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
@ -205,7 +239,7 @@ public final class Profile {
|
|||||||
|
|
||||||
Profile profile = new Profile("Default", new File(gameDir));
|
Profile profile = new Profile("Default", new File(gameDir));
|
||||||
profile.setGlobal(context.deserialize(obj.get("global"), VersionSetting.class));
|
profile.setGlobal(context.deserialize(obj.get("global"), VersionSetting.class));
|
||||||
|
profile.setSelectedVersion(Optional.ofNullable(obj.get("selectedMinecraftVersion")).map(JsonElement::getAsString).orElse(""));
|
||||||
profile.setUseRelativePath(Optional.ofNullable(obj.get("useRelativePath")).map(JsonElement::getAsBoolean).orElse(false));
|
profile.setUseRelativePath(Optional.ofNullable(obj.get("useRelativePath")).map(JsonElement::getAsBoolean).orElse(false));
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* 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.ui;
|
||||||
|
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
|
import javafx.beans.WeakInvalidationListener;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.beans.value.WeakChangeListener;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.collections.WeakListChangeListener;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WeakListenerHelper {
|
||||||
|
List<Object> refs = new LinkedList<>();
|
||||||
|
|
||||||
|
public WeakListenerHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakInvalidationListener weak(InvalidationListener listener) {
|
||||||
|
refs.add(listener);
|
||||||
|
return new WeakInvalidationListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> WeakChangeListener<T> weak(ChangeListener<T> listener) {
|
||||||
|
refs.add(listener);
|
||||||
|
return new WeakChangeListener<>(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> WeakListChangeListener<T> weak(ListChangeListener<T> listener) {
|
||||||
|
refs.add(listener);
|
||||||
|
return new WeakListChangeListener<>(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Object obj) {
|
||||||
|
refs.add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object obj) {
|
||||||
|
return refs.remove(obj);
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,7 @@ public class FontComboBox extends JFXComboBox<String> {
|
|||||||
setOnMouseClicked(e -> {
|
setOnMouseClicked(e -> {
|
||||||
if (loaded) return;
|
if (loaded) return;
|
||||||
getItems().setAll(Font.getFamilies());
|
getItems().setAll(Font.getFamilies());
|
||||||
|
loaded = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package org.jackhuang.hmcl.event;
|
|||||||
|
|
||||||
import org.jackhuang.hmcl.util.SimpleMultimap;
|
import org.jackhuang.hmcl.util.SimpleMultimap;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -31,8 +32,16 @@ public final class EventManager<T extends Event> {
|
|||||||
|
|
||||||
private final SimpleMultimap<EventPriority, Consumer<T>> handlers
|
private final SimpleMultimap<EventPriority, Consumer<T>> handlers
|
||||||
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), HashSet::new);
|
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), HashSet::new);
|
||||||
private final SimpleMultimap<EventPriority, Runnable> handlers2
|
|
||||||
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), HashSet::new);
|
public Consumer<T> registerWeak(Consumer<T> consumer) {
|
||||||
|
register(new WeakListener(consumer));
|
||||||
|
return consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Consumer<T> registerWeak(Consumer<T> consumer, EventPriority priority) {
|
||||||
|
register(new WeakListener(consumer), priority);
|
||||||
|
return consumer;
|
||||||
|
}
|
||||||
|
|
||||||
public void register(Consumer<T> consumer) {
|
public void register(Consumer<T> consumer) {
|
||||||
register(consumer, EventPriority.NORMAL);
|
register(consumer, EventPriority.NORMAL);
|
||||||
@ -44,28 +53,17 @@ public final class EventManager<T extends Event> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void register(Runnable runnable) {
|
public void register(Runnable runnable) {
|
||||||
register(runnable, EventPriority.NORMAL);
|
register(t -> runnable.run());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(Runnable runnable, EventPriority priority) {
|
public void register(Runnable runnable, EventPriority priority) {
|
||||||
if (!handlers2.get(priority).contains(runnable))
|
register(t -> runnable.run(), priority);
|
||||||
handlers2.put(priority, runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregister(Consumer<T> consumer) {
|
|
||||||
handlers.removeValue(consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregister(Runnable runnable) {
|
|
||||||
handlers2.removeValue(runnable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Event.Result fireEvent(T event) {
|
public Event.Result fireEvent(T event) {
|
||||||
for (EventPriority priority : EventPriority.values()) {
|
for (EventPriority priority : EventPriority.values()) {
|
||||||
for (Consumer<T> handler : handlers.get(priority))
|
for (Consumer<T> handler : handlers.get(priority))
|
||||||
handler.accept(event);
|
handler.accept(event);
|
||||||
for (Runnable runnable : handlers2.get(priority))
|
|
||||||
runnable.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.hasResult())
|
if (event.hasResult())
|
||||||
@ -74,4 +72,21 @@ public final class EventManager<T extends Event> {
|
|||||||
return Event.Result.DEFAULT;
|
return Event.Result.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class WeakListener implements Consumer<T> {
|
||||||
|
private final WeakReference<Consumer<T>> ref;
|
||||||
|
|
||||||
|
public WeakListener(Consumer<T> listener) {
|
||||||
|
this.ref = new WeakReference<>(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(T t) {
|
||||||
|
Consumer<T> listener = ref.get();
|
||||||
|
if (listener == null) {
|
||||||
|
handlers.removeValue(this);
|
||||||
|
} else {
|
||||||
|
listener.accept(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user