Change version selection list look

This commit is contained in:
huanghongxun
2018-09-22 22:25:53 +08:00
parent 332719f49a
commit ba67c968cf
17 changed files with 247 additions and 103 deletions

View File

@@ -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;

View File

@@ -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 -> {
StackPane pane = new StackPane();
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()); repository.getProfile().setSelectedVersion(version.getId());
popup.hide(); 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);
}); });
} }

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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(), "-"), "-"), "_"), "_");
}
}

View File

@@ -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);
}
}

View File

@@ -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(), "-"), "-"), "_"), "_");
}
} }

View File

@@ -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);
} }

View File

@@ -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)),

View File

@@ -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

View File

@@ -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)));

View File

@@ -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;
} }

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -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=遊戲目錄列表

View File

@@ -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=游戏目录列表