Change version selection list look
This commit is contained in:
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.game;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
import org.jackhuang.hmcl.event.EventBus;
|
import org.jackhuang.hmcl.event.EventBus;
|
||||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||||
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshingVersionsEvent;
|
||||||
@@ -144,10 +145,24 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
|||||||
return setting;
|
return setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getVersionIcon(String id) {
|
public File getVersionIconFile(String id) {
|
||||||
return new File(getVersionRoot(id), "icon.png");
|
return new File(getVersionRoot(id), "icon.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Image getVersionIconImage(String id) {
|
||||||
|
if (id == null)
|
||||||
|
return new Image("/assets/img/grass.png");
|
||||||
|
|
||||||
|
Version version = getVersion(id);
|
||||||
|
File iconFile = getVersionIconFile(id);
|
||||||
|
if (iconFile.exists())
|
||||||
|
return new Image("file:" + iconFile.getAbsolutePath());
|
||||||
|
else if ("net.minecraft.launchwrapper.Launch".equals(version.getMainClass()))
|
||||||
|
return new Image("/assets/img/furnace.png");
|
||||||
|
else
|
||||||
|
return new Image("/assets/img/grass.png");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean saveVersionSetting(String id) {
|
public boolean saveVersionSetting(String id) {
|
||||||
if (!versionSettings.containsKey(id))
|
if (!versionSettings.containsKey(id))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -32,12 +32,13 @@ import javafx.scene.shape.Rectangle;
|
|||||||
import org.jackhuang.hmcl.event.EventBus;
|
import org.jackhuang.hmcl.event.EventBus;
|
||||||
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||||
import org.jackhuang.hmcl.setting.ConfigHolder;
|
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.setting.Profiles;
|
import org.jackhuang.hmcl.setting.Profiles;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
import org.jackhuang.hmcl.ui.construct.PopupMenu;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.RipplerContainer;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
|
import org.jackhuang.hmcl.ui.versions.GameItem;
|
||||||
import org.jackhuang.hmcl.ui.versions.Versions;
|
import org.jackhuang.hmcl.ui.versions.Versions;
|
||||||
import org.jackhuang.hmcl.util.VersionNumber;
|
import org.jackhuang.hmcl.util.VersionNumber;
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|||||||
public final class MainPage extends StackPane implements DecoratorPage {
|
public final class MainPage extends StackPane implements DecoratorPage {
|
||||||
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("main_page"));
|
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(this, "title", i18n("main_page"));
|
||||||
|
|
||||||
private final VBox menu = new VBox();
|
private final PopupMenu menu = new PopupMenu();
|
||||||
private final JFXPopup popup = new JFXPopup(menu);
|
private final JFXPopup popup = new JFXPopup(menu);
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -69,7 +70,7 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
|||||||
|
|
||||||
btnLaunch.setClip(new Rectangle(-100, -100, 310, 200));
|
btnLaunch.setClip(new Rectangle(-100, -100, 310, 200));
|
||||||
btnMenu.setClip(new Rectangle(211, -100, 100, 200));
|
btnMenu.setClip(new Rectangle(211, -100, 100, 200));
|
||||||
menu.getStyleClass().setAll("menu");
|
menu.setMaxHeight(400);
|
||||||
|
|
||||||
StackPane graphic = new StackPane();
|
StackPane graphic = new StackPane();
|
||||||
Node svg = SVG.triangle(Theme.whiteFillBinding(), 10, 10);
|
Node svg = SVG.triangle(Theme.whiteFillBinding(), 10, 10);
|
||||||
@@ -102,17 +103,26 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadVersions(HMCLGameRepository repository) {
|
private void loadVersions(HMCLGameRepository repository) {
|
||||||
List<IconedMenuItem> children = repository.getVersions().parallelStream()
|
List<Node> children = repository.getVersions().parallelStream()
|
||||||
.filter(version -> !version.isHidden())
|
.filter(version -> !version.isHidden())
|
||||||
.sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId())))
|
.sorted((a, b) -> VersionNumber.COMPARATOR.compare(VersionNumber.asVersion(a.getId()), VersionNumber.asVersion(b.getId())))
|
||||||
.map(version -> new IconedMenuItem(null, version.getId(), () -> {
|
.map(version -> {
|
||||||
repository.getProfile().setSelectedVersion(version.getId());
|
StackPane pane = new StackPane();
|
||||||
popup.hide();
|
GameItem item = new GameItem(repository.getProfile(), version.getId());
|
||||||
}))
|
pane.getChildren().setAll(item);
|
||||||
|
pane.getStyleClass().setAll("menu-container");
|
||||||
|
item.setMouseTransparent(true);
|
||||||
|
RipplerContainer container = new RipplerContainer(pane);
|
||||||
|
container.setOnMouseClicked(e -> {
|
||||||
|
repository.getProfile().setSelectedVersion(version.getId());
|
||||||
|
popup.hide();
|
||||||
|
});
|
||||||
|
return container;
|
||||||
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
JFXUtilities.runInFX(() -> {
|
JFXUtilities.runInFX(() -> {
|
||||||
if (profile == repository.getProfile())
|
if (profile == repository.getProfile())
|
||||||
menu.getChildren().setAll(children);
|
menu.getContent().setAll(children);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class AdvancedListItemSkin extends SkinBase<AdvancedListItem> {
|
|||||||
JFXButton settings = new JFXButton();
|
JFXButton settings = new JFXButton();
|
||||||
FXUtils.setLimitWidth(settings, 40);
|
FXUtils.setLimitWidth(settings, 40);
|
||||||
settings.getStyleClass().setAll("toggle-icon4");
|
settings.getStyleClass().setAll("toggle-icon4");
|
||||||
settings.setGraphic(SVG.dotsVertical(Theme.blackFillBinding(), -1, -1));
|
settings.setGraphic(SVG.gear(Theme.blackFillBinding(), -1, -1));
|
||||||
right.getChildren().setAll(settings);
|
right.getChildren().setAll(settings);
|
||||||
root.setRight(right);
|
root.setRight(right);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.construct;
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Control;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.Skin;
|
||||||
|
import javafx.scene.control.SkinBase;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
|
||||||
|
public class PopupMenu extends Control {
|
||||||
|
|
||||||
|
private final ObservableList<Node> content = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
public PopupMenu() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableList<Node> getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Skin<?> createDefaultSkin() {
|
||||||
|
return new PopupMenuSkin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PopupMenuSkin extends SkinBase<PopupMenu> {
|
||||||
|
|
||||||
|
protected PopupMenuSkin() {
|
||||||
|
super(PopupMenu.this);
|
||||||
|
|
||||||
|
ScrollPane scrollPane = new ScrollPane();
|
||||||
|
scrollPane.setFitToHeight(true);
|
||||||
|
scrollPane.setFitToWidth(true);
|
||||||
|
|
||||||
|
VBox content = new VBox();
|
||||||
|
content.getStyleClass().add("menu");
|
||||||
|
Bindings.bindContent(content.getChildren(), PopupMenu.this.getContent());
|
||||||
|
scrollPane.setContent(content);
|
||||||
|
|
||||||
|
FXUtils.smoothScrolling(scrollPane);
|
||||||
|
|
||||||
|
getChildren().setAll(scrollPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,11 +38,7 @@ public class GameAdvancedListItem extends AdvancedListItem {
|
|||||||
public GameAdvancedListItem() {
|
public GameAdvancedListItem() {
|
||||||
FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), version -> {
|
FXUtils.onChangeAndOperate(Profiles.selectedVersionProperty(), version -> {
|
||||||
FXUtils.runLaterIf(() -> !Objects.nonNull(Profiles.getSelectedProfile()), () -> {
|
FXUtils.runLaterIf(() -> !Objects.nonNull(Profiles.getSelectedProfile()), () -> {
|
||||||
File iconFile = Profiles.getSelectedProfile().getRepository().getVersionIcon(version);
|
imageProperty().set(Profiles.getSelectedProfile().getRepository().getVersionIconImage(version));
|
||||||
if (iconFile.exists())
|
|
||||||
imageProperty().set(new Image("file:" + iconFile.getAbsolutePath()));
|
|
||||||
else
|
|
||||||
imageProperty().set(new Image("/assets/img/grass.png"));
|
|
||||||
|
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
titleProperty().set(version);
|
titleProperty().set(version);
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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.versions;
|
||||||
|
|
||||||
|
import javafx.beans.property.*;
|
||||||
|
import javafx.scene.control.Control;
|
||||||
|
import javafx.scene.control.Skin;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
|
import org.jackhuang.hmcl.game.GameVersion;
|
||||||
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.StringUtils.removePrefix;
|
||||||
|
import static org.jackhuang.hmcl.util.StringUtils.removeSuffix;
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class GameItem extends Control {
|
||||||
|
private final Profile profile;
|
||||||
|
private final String version;
|
||||||
|
private final StringProperty title = new SimpleStringProperty();
|
||||||
|
private final StringProperty subtitle = new SimpleStringProperty();
|
||||||
|
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
|
public GameItem(Profile profile, String id) {
|
||||||
|
this.profile = profile;
|
||||||
|
this.version = id;
|
||||||
|
|
||||||
|
String game = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(id)).orElse("Unknown");
|
||||||
|
|
||||||
|
StringBuilder libraries = new StringBuilder(game);
|
||||||
|
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(profile.getRepository().getVersion(id));
|
||||||
|
analyzer.getForge().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.forge")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)forge", ""))));
|
||||||
|
analyzer.getLiteLoader().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.liteloader")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)liteloader", ""))));
|
||||||
|
analyzer.getOptiFine().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.optifine")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)optifine", ""))));
|
||||||
|
|
||||||
|
title.set(id);
|
||||||
|
subtitle.set(libraries.toString());
|
||||||
|
image.set(profile.getRepository().getVersionIconImage(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Skin<?> createDefaultSkin() {
|
||||||
|
return new GameItemSkin(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Profile getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty subtitleProperty() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Image> imageProperty() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String modifyVersion(String gameVersion, String version) {
|
||||||
|
return removeSuffix(removePrefix(removeSuffix(removePrefix(version.replace(gameVersion, "").trim(), "-"), "-"), "_"), "_");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.jackhuang.hmcl.ui.versions;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.SkinBase;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
|
|
||||||
|
public class GameItemSkin extends SkinBase<GameItem> {
|
||||||
|
public GameItemSkin(GameItem skinnable) {
|
||||||
|
super(skinnable);
|
||||||
|
|
||||||
|
HBox center = new HBox();
|
||||||
|
center.setSpacing(8);
|
||||||
|
center.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
StackPane imageViewContainer = new StackPane();
|
||||||
|
FXUtils.setLimitWidth(imageViewContainer, 32);
|
||||||
|
FXUtils.setLimitHeight(imageViewContainer, 32);
|
||||||
|
|
||||||
|
ImageView imageView = new ImageView();
|
||||||
|
FXUtils.limitSize(imageView, 32, 32);
|
||||||
|
imageView.imageProperty().bind(skinnable.imageProperty());
|
||||||
|
imageViewContainer.getChildren().setAll(imageView);
|
||||||
|
|
||||||
|
TwoLineListItem item = new TwoLineListItem();
|
||||||
|
item.titleProperty().bind(skinnable.titleProperty());
|
||||||
|
item.subtitleProperty().bind(skinnable.subtitleProperty());
|
||||||
|
BorderPane.setAlignment(item, Pos.CENTER);
|
||||||
|
center.getChildren().setAll(imageView, item);
|
||||||
|
getChildren().setAll(center);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,27 +21,16 @@ import javafx.beans.property.*;
|
|||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
import javafx.scene.control.Skin;
|
import javafx.scene.control.Skin;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
|
||||||
import org.jackhuang.hmcl.game.GameVersion;
|
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.StringUtils.removePrefix;
|
|
||||||
import static org.jackhuang.hmcl.util.StringUtils.removeSuffix;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
|
||||||
|
|
||||||
public class GameListItem extends Control {
|
public class GameListItem extends Control {
|
||||||
private final Profile profile;
|
private final Profile profile;
|
||||||
private final String version;
|
private final String version;
|
||||||
private final boolean isModpack;
|
private final boolean isModpack;
|
||||||
private final ToggleGroup toggleGroup;
|
private final ToggleGroup toggleGroup;
|
||||||
private final StringProperty title = new SimpleStringProperty();
|
|
||||||
private final StringProperty subtitle = new SimpleStringProperty();
|
|
||||||
private final BooleanProperty selected = new SimpleBooleanProperty();
|
private final BooleanProperty selected = new SimpleBooleanProperty();
|
||||||
private final ObjectProperty<Image> image = new SimpleObjectProperty<>();
|
|
||||||
|
|
||||||
public GameListItem(ToggleGroup toggleGroup, Profile profile, String id) {
|
public GameListItem(ToggleGroup toggleGroup, Profile profile, String id) {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
@@ -49,23 +38,7 @@ public class GameListItem extends Control {
|
|||||||
this.toggleGroup = toggleGroup;
|
this.toggleGroup = toggleGroup;
|
||||||
this.isModpack = profile.getRepository().isModpack(id);
|
this.isModpack = profile.getRepository().isModpack(id);
|
||||||
|
|
||||||
String game = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(id)).orElse("Unknown");
|
|
||||||
|
|
||||||
StringBuilder libraries = new StringBuilder(game);
|
|
||||||
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(profile.getRepository().getVersion(id));
|
|
||||||
analyzer.getForge().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.forge")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)forge", ""))));
|
|
||||||
analyzer.getLiteLoader().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.liteloader")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)liteloader", ""))));
|
|
||||||
analyzer.getOptiFine().ifPresent(library -> libraries.append(", ").append(i18n("install.installer.optifine")).append(": ").append(modifyVersion(game, library.getVersion().replaceAll("(?i)optifine", ""))));
|
|
||||||
|
|
||||||
title.set(id);
|
|
||||||
subtitle.set(libraries.toString());
|
|
||||||
selected.set(id.equals(profile.getSelectedVersion()));
|
selected.set(id.equals(profile.getSelectedVersion()));
|
||||||
|
|
||||||
File iconFile = profile.getRepository().getVersionIcon(version);
|
|
||||||
if (iconFile.exists())
|
|
||||||
image.set(new Image("file:" + iconFile.getAbsolutePath()));
|
|
||||||
else
|
|
||||||
image.set(new Image("/assets/img/grass.png"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,22 +58,10 @@ public class GameListItem extends Control {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty titleProperty() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringProperty subtitleProperty() {
|
|
||||||
return subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BooleanProperty selectedProperty() {
|
public BooleanProperty selectedProperty() {
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<Image> imageProperty() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkSelection() {
|
public void checkSelection() {
|
||||||
selected.set(version.equals(profile.getSelectedVersion()));
|
selected.set(version.equals(profile.getSelectedVersion()));
|
||||||
}
|
}
|
||||||
@@ -141,8 +102,4 @@ public class GameListItem extends Control {
|
|||||||
public void update() {
|
public void update() {
|
||||||
Versions.updateVersion(profile, version);
|
Versions.updateVersion(profile, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String modifyVersion(String gameVersion, String version) {
|
|
||||||
return removeSuffix(removePrefix(removeSuffix(removePrefix(version.replace(gameVersion, "").trim(), "-"), "-"), "_"), "_");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,17 +24,14 @@ import com.jfoenix.controls.JFXRadioButton;
|
|||||||
import com.jfoenix.effects.JFXDepthManager;
|
import com.jfoenix.effects.JFXDepthManager;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
import javafx.scene.image.ImageView;
|
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.SVG;
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
||||||
import org.jackhuang.hmcl.ui.construct.MenuSeparator;
|
import org.jackhuang.hmcl.ui.construct.MenuSeparator;
|
||||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
import org.jackhuang.hmcl.ui.construct.PopupMenu;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
@@ -52,29 +49,12 @@ public class GameListItemSkin extends SkinBase<GameListItem> {
|
|||||||
chkSelected.setToggleGroup(skinnable.getToggleGroup());
|
chkSelected.setToggleGroup(skinnable.getToggleGroup());
|
||||||
root.setLeft(chkSelected);
|
root.setLeft(chkSelected);
|
||||||
|
|
||||||
HBox center = new HBox();
|
root.setCenter(new GameItem(skinnable.getProfile(), skinnable.getVersion()));
|
||||||
center.setSpacing(8);
|
|
||||||
center.setAlignment(Pos.CENTER_LEFT);
|
|
||||||
|
|
||||||
StackPane imageViewContainer = new StackPane();
|
PopupMenu menu = new PopupMenu();
|
||||||
FXUtils.setLimitWidth(imageViewContainer, 32);
|
|
||||||
FXUtils.setLimitHeight(imageViewContainer, 32);
|
|
||||||
|
|
||||||
ImageView imageView = new ImageView();
|
|
||||||
FXUtils.limitSize(imageView, 32, 32);
|
|
||||||
imageView.imageProperty().bind(skinnable.imageProperty());
|
|
||||||
imageViewContainer.getChildren().setAll(imageView);
|
|
||||||
|
|
||||||
TwoLineListItem item = new TwoLineListItem();
|
|
||||||
BorderPane.setAlignment(item, Pos.CENTER);
|
|
||||||
center.getChildren().setAll(imageView, item);
|
|
||||||
root.setCenter(center);
|
|
||||||
|
|
||||||
VBox menu = new VBox();
|
|
||||||
menu.getStyleClass().setAll("menu");
|
|
||||||
JFXPopup popup = new JFXPopup(menu);
|
JFXPopup popup = new JFXPopup(menu);
|
||||||
|
|
||||||
menu.getChildren().setAll(
|
menu.getContent().setAll(
|
||||||
new IconedMenuItem(FXUtils.limitingSize(SVG.gear(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.manage.manage"), FXUtils.withJFXPopupClosing(skinnable::modifyGameSettings, popup)),
|
new IconedMenuItem(FXUtils.limitingSize(SVG.gear(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.manage.manage"), FXUtils.withJFXPopupClosing(skinnable::modifyGameSettings, popup)),
|
||||||
new MenuSeparator(),
|
new MenuSeparator(),
|
||||||
new IconedMenuItem(FXUtils.limitingSize(SVG.pencil(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.manage.rename"), FXUtils.withJFXPopupClosing(skinnable::rename, popup)),
|
new IconedMenuItem(FXUtils.limitingSize(SVG.pencil(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("version.manage.rename"), FXUtils.withJFXPopupClosing(skinnable::rename, popup)),
|
||||||
@@ -109,8 +89,6 @@ public class GameListItemSkin extends SkinBase<GameListItem> {
|
|||||||
|
|
||||||
root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;");
|
root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;");
|
||||||
JFXDepthManager.setDepth(root, 1);
|
JFXDepthManager.setDepth(root, 1);
|
||||||
item.titleProperty().bind(skinnable.titleProperty());
|
|
||||||
item.subtitleProperty().bind(skinnable.subtitleProperty());
|
|
||||||
|
|
||||||
getChildren().setAll(root);
|
getChildren().setAll(root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask;
|
|||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.PopupMenu;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.FileUtils;
|
import org.jackhuang.hmcl.util.FileUtils;
|
||||||
|
|
||||||
@@ -74,10 +75,9 @@ public final class VersionPage extends StackPane implements DecoratorPage {
|
|||||||
{
|
{
|
||||||
FXUtils.loadFXML(this, "/assets/fxml/version/version.fxml");
|
FXUtils.loadFXML(this, "/assets/fxml/version/version.fxml");
|
||||||
|
|
||||||
VBox browseList = new VBox();
|
PopupMenu browseList = new PopupMenu();
|
||||||
browseList.getStyleClass().setAll("menu");
|
|
||||||
browsePopup = new JFXPopup(browseList);
|
browsePopup = new JFXPopup(browseList);
|
||||||
browseList.getChildren().setAll(
|
browseList.getContent().setAll(
|
||||||
new IconedMenuItem(null, i18n("folder.game"), FXUtils.withJFXPopupClosing(() -> onBrowse(""), browsePopup)),
|
new IconedMenuItem(null, i18n("folder.game"), FXUtils.withJFXPopupClosing(() -> onBrowse(""), browsePopup)),
|
||||||
new IconedMenuItem(null, i18n("folder.mod"), FXUtils.withJFXPopupClosing(() -> onBrowse("mods"), browsePopup)),
|
new IconedMenuItem(null, i18n("folder.mod"), FXUtils.withJFXPopupClosing(() -> onBrowse("mods"), browsePopup)),
|
||||||
new IconedMenuItem(null, i18n("folder.config"), FXUtils.withJFXPopupClosing(() -> onBrowse("config"), browsePopup)),
|
new IconedMenuItem(null, i18n("folder.config"), FXUtils.withJFXPopupClosing(() -> onBrowse("config"), browsePopup)),
|
||||||
@@ -86,10 +86,9 @@ public final class VersionPage extends StackPane implements DecoratorPage {
|
|||||||
new IconedMenuItem(null, i18n("folder.saves"), FXUtils.withJFXPopupClosing(() -> onBrowse("resourcepacks"), browsePopup))
|
new IconedMenuItem(null, i18n("folder.saves"), FXUtils.withJFXPopupClosing(() -> onBrowse("resourcepacks"), browsePopup))
|
||||||
);
|
);
|
||||||
|
|
||||||
VBox managementList = new VBox();
|
PopupMenu managementList = new PopupMenu();
|
||||||
managementList.getStyleClass().setAll("menu");
|
|
||||||
managementPopup = new JFXPopup(managementList);
|
managementPopup = new JFXPopup(managementList);
|
||||||
managementList.getChildren().setAll(
|
managementList.getContent().setAll(
|
||||||
new IconedMenuItem(null, i18n("version.manage.rename"), FXUtils.withJFXPopupClosing(() -> Versions.renameVersion(profile, version), managementPopup)),
|
new IconedMenuItem(null, i18n("version.manage.rename"), FXUtils.withJFXPopupClosing(() -> Versions.renameVersion(profile, version), managementPopup)),
|
||||||
new IconedMenuItem(null, i18n("version.manage.remove"), FXUtils.withJFXPopupClosing(() -> Versions.deleteVersion(profile, version), managementPopup)),
|
new IconedMenuItem(null, i18n("version.manage.remove"), FXUtils.withJFXPopupClosing(() -> Versions.deleteVersion(profile, version), managementPopup)),
|
||||||
new IconedMenuItem(null, i18n("version.manage.redownload_assets_index"), FXUtils.withJFXPopupClosing(() -> new GameAssetIndexDownloadTask(profile.getDependency(), profile.getRepository().getResolvedVersion(version)).start(), managementPopup)),
|
new IconedMenuItem(null, i18n("version.manage.redownload_assets_index"), FXUtils.withJFXPopupClosing(() -> new GameAssetIndexDownloadTask(profile.getDependency(), profile.getRepository().getResolvedVersion(version)).start(), managementPopup)),
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("extension.png"), "*.png"));
|
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("extension.png"), "*.png"));
|
||||||
File selectedFile = chooser.showOpenDialog(Controllers.getStage());
|
File selectedFile = chooser.showOpenDialog(Controllers.getStage());
|
||||||
if (selectedFile != null) {
|
if (selectedFile != null) {
|
||||||
File iconFile = profile.getRepository().getVersionIcon(versionId);
|
File iconFile = profile.getRepository().getVersionIconFile(versionId);
|
||||||
try {
|
try {
|
||||||
FileUtils.copyFile(selectedFile, iconFile);
|
FileUtils.copyFile(selectedFile, iconFile);
|
||||||
loadIcon();
|
loadIcon();
|
||||||
@@ -291,7 +291,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
if (versionId == null)
|
if (versionId == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
File iconFile = profile.getRepository().getVersionIcon(versionId);
|
File iconFile = profile.getRepository().getVersionIconFile(versionId);
|
||||||
if (iconFile.exists())
|
if (iconFile.exists())
|
||||||
iconFile.delete();
|
iconFile.delete();
|
||||||
loadIcon();
|
loadIcon();
|
||||||
@@ -303,7 +303,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File iconFile = profile.getRepository().getVersionIcon(versionId);
|
File iconFile = profile.getRepository().getVersionIconFile(versionId);
|
||||||
if (iconFile.exists())
|
if (iconFile.exists())
|
||||||
iconPickerItem.setImage(new Image("file:" + iconFile.getAbsolutePath()));
|
iconPickerItem.setImage(new Image("file:" + iconFile.getAbsolutePath()));
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import javafx.scene.image.ImageView;
|
|||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.SVG;
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
import org.jackhuang.hmcl.ui.construct.IconedMenuItem;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.PopupMenu;
|
||||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
@@ -43,11 +43,10 @@ public class WorldListItemSkin extends SkinBase<WorldListItem> {
|
|||||||
center.getChildren().setAll(imageView, item);
|
center.getChildren().setAll(imageView, item);
|
||||||
root.setCenter(center);
|
root.setCenter(center);
|
||||||
|
|
||||||
VBox menu = new VBox();
|
PopupMenu menu = new PopupMenu();
|
||||||
menu.getStyleClass().setAll("menu");
|
|
||||||
JFXPopup popup = new JFXPopup(menu);
|
JFXPopup popup = new JFXPopup(menu);
|
||||||
|
|
||||||
menu.getChildren().setAll(
|
menu.getContent().setAll(
|
||||||
new IconedMenuItem(FXUtils.limitingSize(SVG.gear(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("world.datapack"), FXUtils.withJFXPopupClosing(skinnable::manageDatapacks, popup)),
|
new IconedMenuItem(FXUtils.limitingSize(SVG.gear(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("world.datapack"), FXUtils.withJFXPopupClosing(skinnable::manageDatapacks, popup)),
|
||||||
new IconedMenuItem(FXUtils.limitingSize(SVG.export(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("world.export"), FXUtils.withJFXPopupClosing(skinnable::export, popup)));
|
new IconedMenuItem(FXUtils.limitingSize(SVG.export(Theme.blackFillBinding(), 14, 14), 14, 14), i18n("world.export"), FXUtils.withJFXPopupClosing(skinnable::export, popup)));
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,10 @@
|
|||||||
-fx-alignment: CENTER_LEFT;
|
-fx-alignment: CENTER_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-container {
|
||||||
|
-fx-padding: 8 16 8 16;
|
||||||
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
-fx-padding: 4 0 4 0;
|
-fx-padding: 4 0 4 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<graphic>
|
<graphic>
|
||||||
<VBox alignment="CENTER" translateX="-7" maxWidth="200">
|
<VBox alignment="CENTER" translateX="-7" maxWidth="200">
|
||||||
<Label style="-fx-font-size: 16;" text="%version.launch"/>
|
<Label style="-fx-font-size: 16;" text="%version.launch"/>
|
||||||
<Label style="-fx-font-size: 12px;" fx:id="lblCurrentGame"/>
|
<Label style="-fx-font-size: 13px;" fx:id="lblCurrentGame"/>
|
||||||
</VBox>
|
</VBox>
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
|
|||||||
BIN
HMCL/src/main/resources/assets/img/furnace.png
Normal file
BIN
HMCL/src/main/resources/assets/img/furnace.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
@@ -269,7 +269,7 @@ world.time=yyyy 年 MM 月 dd 日 HH:mm:ss
|
|||||||
|
|
||||||
profile=遊戲目錄
|
profile=遊戲目錄
|
||||||
profile.default=目前目錄
|
profile.default=目前目錄
|
||||||
profile.home=官方啟動器目錄
|
profile.home=官方啟動器
|
||||||
profile.instance_directory=遊戲路徑
|
profile.instance_directory=遊戲路徑
|
||||||
profile.instance_directory.choose=選擇遊戲路徑
|
profile.instance_directory.choose=選擇遊戲路徑
|
||||||
profile.manage=遊戲目錄列表
|
profile.manage=遊戲目錄列表
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ world.time=yyyy 年 MM 月 dd 日 HH:mm:ss
|
|||||||
|
|
||||||
profile=游戏目录
|
profile=游戏目录
|
||||||
profile.default=当前目录
|
profile.default=当前目录
|
||||||
profile.home=官方启动器目录
|
profile.home=官方启动器
|
||||||
profile.instance_directory=游戏路径
|
profile.instance_directory=游戏路径
|
||||||
profile.instance_directory.choose=选择游戏路径
|
profile.instance_directory.choose=选择游戏路径
|
||||||
profile.manage=游戏目录列表
|
profile.manage=游戏目录列表
|
||||||
|
|||||||
Reference in New Issue
Block a user