diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index c7a99881db..13a67943c1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -62,6 +62,7 @@ public enum SVG { EXTENSION_FILL("M8.8 21H5q-.825 0-1.4125-.5875T3 19V15.2q1.2 0 2.1-.7625T6 12.5q0-1.175-.9-1.9375T3 9.8V6q0-.825.5875-1.4125T5 4H9q0-1.05.725-1.775T11.5 1.5q1.05 0 1.775.725T14 4h4q.825 0 1.4125.5875T20 6v4q1.05 0 1.775.725T22.5 12.5q0 1.05-.725 1.775T20 15v4q0 .825-.5875 1.4125T18 21H14.2q0-1.25-.7875-2.125T11.5 18q-1.125 0-1.9125.875T8.8 21Z"), FEEDBACK("M12 15Q12.425 15 12.7125 14.7125T13 14Q13 13.575 12.7125 13.2875T12 13Q11.575 13 11.2875 13.2875T11 14Q11 14.425 11.2875 14.7125T12 15ZM11 11H13V5H11V11ZM2 22V4Q2 3.175 2.5875 2.5875T4 2H20Q20.825 2 21.4125 2.5875T22 4V16Q22 16.825 21.4125 17.4125T20 18H6L2 22ZM5.15 16H20V4H4V17.125L5.15 16ZM4 16V4 16Z"), FEEDBACK_FILL("M2 22V4q0-.825.5875-1.4125T4 2H20q.825 0 1.4125.5875T22 4V16q0 .825-.5875 1.4125T20 18H6L2 22Zm10-7q.425 0 .7125-.2875T13 14t-.2875-.7125T12 13t-.7125.2875T11 14t.2875.7125T12 15Zm-1-4h2V5H11v6Z"), + FILE_OPEN("M6 22q-0.825 0-1.4125-0.5875T4 20v-16q0-0.825 0.5875-1.4125T6 2h8l6 6v6h-2v-5H13v-5H6v16h9v2H6Zm15.95 0.375L19 19.425v2.225h-2v-5.65h5.65v2h-2.25l2.95 2.95-1.4 1.425Zm-15.95-2.375v-16 16Z"), FOLDER("M4 20Q3.175 20 2.5875 19.4125T2 18V6Q2 5.175 2.5875 4.5875T4 4H10L12 6H20Q20.825 6 21.4125 6.5875T22 8V18Q22 18.825 21.4125 19.4125T20 20H4ZM4 18H20V8H11.175L9.175 6H4V18ZM4 18V6 18Z"), FOLDER_COPY("M3 21Q2.175 21 1.5875 20.4125T1 19V6H3V19H20V21H3ZM7 17Q6.175 17 5.5875 16.4125T5 15V4Q5 3.175 5.5875 2.5875T7 2H12L14 4H21Q21.825 4 22.4125 4.5875T23 6V15Q23 15.825 22.4125 16.4125T21 17H7ZM7 15H21V6H13.175L11.175 4H7V15ZM7 15V4 15Z"), FOLDER_OPEN("M4 20Q3.175 20 2.5875 19.4125T2 18V6Q2 5.175 2.5875 4.5875T4 4H10L12 6H20Q20.825 6 21.4125 6.5875T22 8H11.175L9.175 6H4V18L6.4 10H23.5L20.925 18.575Q20.725 19.225 20.1875 19.6125T19 20H4ZM6.1 18H19L20.8 12H7.9L6.1 18ZM6.1 18 7.9 12 6.1 18ZM4 8V6 8Z"), diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileSelector.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileSelector.java index 14100ebe10..1c40375526 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileSelector.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileSelector.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXPopup; import com.jfoenix.controls.JFXTextField; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; @@ -30,6 +31,7 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.FileUtils; import java.nio.file.Path; @@ -38,10 +40,18 @@ public class FileSelector extends HBox { private final StringProperty value = new SimpleStringProperty(); - private String chooserTitle = i18n("selector.choose_file"); - private boolean directory = false; + private String chooserTitle = ""; + private SelectionMode selectionMode = SelectionMode.FILE; private final ObservableList extensionFilters = FXCollections.observableArrayList(); + JFXButton selectButton = FXUtils.newToggleButton4(SVG.FOLDER_OPEN, 15); + + public enum SelectionMode { + FILE, + DIRECTORY, + FILE_OR_DIRECTORY + } + public String getValue() { return value.get(); } @@ -63,12 +73,12 @@ public FileSelector setChooserTitle(String chooserTitle) { return this; } - public boolean isDirectory() { - return directory; + public SelectionMode getSelectionMode() { + return selectionMode; } - public FileSelector setDirectory(boolean directory) { - this.directory = directory; + public FileSelector setSelectionMode(SelectionMode selectionMode) { + this.selectionMode = selectionMode; return this; } @@ -80,26 +90,20 @@ public FileSelector() { JFXTextField customField = new JFXTextField(); FXUtils.bindString(customField, valueProperty()); - JFXButton selectButton = FXUtils.newToggleButton4(SVG.FOLDER_OPEN, 15); selectButton.setOnAction(e -> { - if (directory) { - DirectoryChooser chooser = new DirectoryChooser(); - chooser.setTitle(chooserTitle); - Path dir = FileUtils.toPath(chooser.showDialog(Controllers.getStage())); - if (dir != null) { - String path = FileUtils.getAbsolutePath(dir); - customField.setText(path); - value.setValue(path); - } - } else { - FileChooser chooser = new FileChooser(); - chooser.getExtensionFilters().addAll(getExtensionFilters()); - chooser.setTitle(chooserTitle); - Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage())); - if (file != null) { - String path = FileUtils.getAbsolutePath(file); - customField.setText(path); - value.setValue(path); + switch (selectionMode) { + case FILE -> openFileChooser(customField); + case DIRECTORY -> openDirectoryChooser(customField); + case FILE_OR_DIRECTORY -> { + PopupMenu selectPopupMenu = new PopupMenu(); + JFXPopup selectModePopup = new JFXPopup(selectPopupMenu); + + selectPopupMenu.getContent().addAll( + new IconedMenuItem(SVG.FILE_OPEN, i18n("selector.choose_file"), () -> openFileChooser(customField), selectModePopup), + new IconedMenuItem(SVG.FOLDER_OPEN, i18n("selector.choose_directory"), () -> openDirectoryChooser(customField), selectModePopup) + ); + + selectModePopup.show(selectButton, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.LEFT, selectButton.getWidth(), 0); } } }); @@ -108,4 +112,27 @@ public FileSelector() { setSpacing(3); getChildren().addAll(customField, selectButton); } + + private void openFileChooser(JFXTextField customField) { + FileChooser chooser = new FileChooser(); + chooser.getExtensionFilters().addAll(getExtensionFilters()); + chooser.setTitle(StringUtils.isBlank(chooserTitle) ? i18n("selector.choose_file") : chooserTitle); + Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage())); + if (file != null) { + String path = FileUtils.getAbsolutePath(file); + customField.setText(path); + value.setValue(path); + } + } + + private void openDirectoryChooser(JFXTextField customField) { + DirectoryChooser chooser = new DirectoryChooser(); + chooser.setTitle(StringUtils.isBlank(chooserTitle) ? i18n("selector.choose_directory") : chooserTitle); + Path dir = FileUtils.toPath(chooser.showDialog(Controllers.getStage())); + if (dir != null) { + String path = FileUtils.getAbsolutePath(dir); + customField.setText(path); + value.setValue(path); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java index 5f89da798b..b26dcc0f57 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MultiFileItem.java @@ -266,8 +266,8 @@ public void setValue(String value) { selector.setValue(value); } - public FileOption setDirectory(boolean directory) { - selector.setDirectory(directory); + public FileOption setSelectionMode(FileSelector.SelectionMode selectionMode) { + selector.setSelectionMode(selectionMode); return this; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java index 6f19448095..40f241121d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java @@ -135,6 +135,7 @@ public PersonalizationPage() { new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumBackgroundImage.CUSTOM) .setChooserTitle(i18n("launcher.background.choose")) .addExtensionFilter(FXUtils.getImageExtensionFilter()) + .setSelectionMode(FileSelector.SelectionMode.FILE_OR_DIRECTORY) .bindBidirectional(config().backgroundImageProperty()), new MultiFileItem.StringOption<>(i18n("launcher.background.network"), EnumBackgroundImage.NETWORK) .setValidators(new URLValidator(true)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java index db12d37bb0..defbe443ca 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/SettingsPage.java @@ -230,7 +230,7 @@ public SettingsPage() { new MultiFileItem.Option<>(i18n("launcher.cache_directory.default"), EnumCommonDirectory.DEFAULT), new MultiFileItem.FileOption<>(i18n("settings.custom"), EnumCommonDirectory.CUSTOM) .setChooserTitle(i18n("launcher.cache_directory.choose")) - .setDirectory(true) + .setSelectionMode(FileSelector.SelectionMode.DIRECTORY) .bindBidirectional(config().commonDirectoryProperty()) )); fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java index efb154997e..b134b14f0c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java @@ -159,7 +159,7 @@ public AdvancedVersionSettingPage(Profile profile, @Nullable String versionId, V nativesDirSublist.setHasSubtitle(true); nativesDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.advanced.natives_directory.custom"), NativesDirectoryType.CUSTOM) .setChooserTitle(i18n("settings.advanced.natives_directory.choose")) - .setDirectory(true); + .setSelectionMode(FileSelector.SelectionMode.DIRECTORY); nativesDirItem.loadChildren(Arrays.asList( new MultiFileItem.Option<>(i18n("settings.advanced.natives_directory.default"), NativesDirectoryType.VERSION_FOLDER), nativesDirCustomOption diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index ad6ab14187..f011841382 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -242,7 +242,7 @@ public VersionSettingsPage(boolean globalSetting) { gameDirItem.disableProperty().bind(modpack); gameDirCustomOption = new MultiFileItem.FileOption<>(i18n("settings.custom"), GameDirectoryType.CUSTOM) .setChooserTitle(i18n("settings.game.working_directory.choose")) - .setDirectory(true); + .setSelectionMode(FileSelector.SelectionMode.DIRECTORY); gameDirItem.loadChildren(Arrays.asList( new MultiFileItem.Option<>(i18n("settings.advanced.game_dir.default"), GameDirectoryType.ROOT_FOLDER), diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 174b7a1f41..bdea0e16f6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1299,6 +1299,7 @@ search.page_n=%1$d / %2$s selector.choose=Choose selector.choose_file=Choose file +selector.choose_directory=Choose directory selector.custom=Custom settings=Settings diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 96f7df20b1..605b960ee5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1089,6 +1089,7 @@ search.page_n=%d / %s selector.choose=選取 selector.choose_file=選取檔案 +selector.choose_directory=選取資料夾 selector.custom=自訂 settings=設定 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 2d306511af..fc810f4261 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1094,6 +1094,7 @@ search.page_n=%d / %s selector.choose=选择 selector.choose_file=选择文件 +selector.choose_directory=选择文件夹 selector.custom=自定义 settings=设置