mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-01-12 14:14:52 +08:00
parent
d54d9ae5cb
commit
1a6dffab74
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2019 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.construct;
|
||||
|
||||
import com.jfoenix.controls.JFXCheckBox;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.TreeTableCell;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
public class JFXCheckBoxTreeTableCell<S, T> extends TreeTableCell<S, T> {
|
||||
|
||||
private final CheckBox checkBox;
|
||||
private boolean showLabel;
|
||||
private ObservableValue<Boolean> booleanProperty;
|
||||
|
||||
public JFXCheckBoxTreeTableCell() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public JFXCheckBoxTreeTableCell(
|
||||
final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty) {
|
||||
this(getSelectedProperty, null);
|
||||
}
|
||||
|
||||
public JFXCheckBoxTreeTableCell(
|
||||
final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty,
|
||||
final StringConverter<T> converter) {
|
||||
this.getStyleClass().add("check-box-tree-table-cell");
|
||||
this.checkBox = new JFXCheckBox();
|
||||
setGraphic(null);
|
||||
setSelectedStateCallback(getSelectedProperty);
|
||||
setConverter(converter);
|
||||
}
|
||||
|
||||
private ObjectProperty<StringConverter<T>> converter = new SimpleObjectProperty<StringConverter<T>>(this, "converter") {
|
||||
protected void invalidated() {
|
||||
updateShowLabel();
|
||||
}
|
||||
};
|
||||
|
||||
public final ObjectProperty<StringConverter<T>> converterProperty() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
public final void setConverter(StringConverter<T> value) {
|
||||
converterProperty().set(value);
|
||||
}
|
||||
|
||||
public final StringConverter<T> getConverter() {
|
||||
return converterProperty().get();
|
||||
}
|
||||
|
||||
private ObjectProperty<Callback<Integer, ObservableValue<Boolean>>>
|
||||
selectedStateCallback =
|
||||
new SimpleObjectProperty<Callback<Integer, ObservableValue<Boolean>>>(
|
||||
this, "selectedStateCallback");
|
||||
|
||||
public final ObjectProperty<Callback<Integer, ObservableValue<Boolean>>> selectedStateCallbackProperty() {
|
||||
return selectedStateCallback;
|
||||
}
|
||||
|
||||
public final void setSelectedStateCallback(Callback<Integer, ObservableValue<Boolean>> value) {
|
||||
selectedStateCallbackProperty().set(value);
|
||||
}
|
||||
|
||||
public final Callback<Integer, ObservableValue<Boolean>> getSelectedStateCallback() {
|
||||
return selectedStateCallbackProperty().get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void updateItem(T item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (empty) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
StringConverter<T> c = getConverter();
|
||||
|
||||
if (showLabel) {
|
||||
setText(c.toString(item));
|
||||
}
|
||||
setGraphic(checkBox);
|
||||
|
||||
if (booleanProperty instanceof BooleanProperty) {
|
||||
checkBox.selectedProperty().unbindBidirectional((BooleanProperty) booleanProperty);
|
||||
}
|
||||
ObservableValue<?> obsValue = getSelectedProperty();
|
||||
if (obsValue instanceof BooleanProperty) {
|
||||
booleanProperty = (ObservableValue<Boolean>) obsValue;
|
||||
checkBox.selectedProperty().bindBidirectional((BooleanProperty) booleanProperty);
|
||||
}
|
||||
|
||||
checkBox.disableProperty().bind(Bindings.not(
|
||||
getTreeTableView().editableProperty().and(
|
||||
getTableColumn().editableProperty()).and(
|
||||
editableProperty())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShowLabel() {
|
||||
this.showLabel = converter != null;
|
||||
this.checkBox.setAlignment(showLabel ? Pos.CENTER_LEFT : Pos.CENTER);
|
||||
}
|
||||
|
||||
private ObservableValue<?> getSelectedProperty() {
|
||||
return getSelectedStateCallback() != null ?
|
||||
getSelectedStateCallback().call(getIndex()) :
|
||||
getTableColumn().getCellObservableValue(getIndex());
|
||||
}
|
||||
}
|
@ -179,7 +179,7 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
|
||||
}
|
||||
|
||||
public void checkUpdates() {
|
||||
Controllers.taskDialog(Task
|
||||
Runnable action = () -> Controllers.taskDialog(Task
|
||||
.composeAsync(() -> {
|
||||
Optional<String> gameVersion = profile.getRepository().getGameVersion(versionId);
|
||||
if (gameVersion.isPresent()) {
|
||||
@ -193,11 +193,20 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
|
||||
} else if (result.isEmpty()) {
|
||||
Controllers.dialog(i18n("mods.check_updates.empty"));
|
||||
} else {
|
||||
Controllers.navigate(new ModUpdatesPage(modManager, result, profile.getRepository().isModpack(versionId)));
|
||||
Controllers.navigate(new ModUpdatesPage(modManager, result));
|
||||
}
|
||||
})
|
||||
.withStagesHint(Collections.singletonList("mods.check_updates")),
|
||||
i18n("update.checking"), TaskCancellationAction.NORMAL);
|
||||
|
||||
if (profile.getRepository().isModpack(versionId)) {
|
||||
Controllers.confirm(
|
||||
i18n("mods.update_modpack_mod.warning"), null,
|
||||
MessageDialogPane.MessageType.WARNING,
|
||||
action, null);
|
||||
} else {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void download() {
|
||||
|
@ -17,20 +17,19 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import com.jfoenix.controls.*;
|
||||
import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXListView;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.CheckBoxTableCell;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.jackhuang.hmcl.mod.LocalModFile;
|
||||
import org.jackhuang.hmcl.mod.ModManager;
|
||||
@ -41,8 +40,10 @@ import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
import org.jackhuang.hmcl.ui.construct.*;
|
||||
import org.jackhuang.hmcl.ui.construct.MDListCell;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.PageCloseEvent;
|
||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||
import org.jackhuang.hmcl.util.Pair;
|
||||
import org.jackhuang.hmcl.util.TaskCancellationAction;
|
||||
@ -67,38 +68,36 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
||||
private final ObservableList<ModUpdateObject> objects;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ModUpdatesPage(ModManager modManager, List<LocalModFile.ModUpdate> updates, Boolean isModpack) {
|
||||
public ModUpdatesPage(ModManager modManager, List<LocalModFile.ModUpdate> updates) {
|
||||
this.modManager = modManager;
|
||||
|
||||
getStyleClass().add("gray-background");
|
||||
|
||||
JFXTreeTableColumn<ModUpdateObject, Boolean> enabledColumn = new JFXTreeTableColumn<>();
|
||||
enabledColumn.setCellFactory(column -> new JFXCheckBoxTreeTableCell<>());
|
||||
TableColumn<ModUpdateObject, Boolean> enabledColumn = new TableColumn<>();
|
||||
enabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(enabledColumn));
|
||||
setupCellValueFactory(enabledColumn, ModUpdateObject::enabledProperty);
|
||||
enabledColumn.setEditable(true);
|
||||
enabledColumn.setMaxWidth(40);
|
||||
enabledColumn.setMinWidth(40);
|
||||
|
||||
JFXTreeTableColumn<ModUpdateObject, String> fileNameColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.file"));
|
||||
TableColumn<ModUpdateObject, String> fileNameColumn = new TableColumn<>(i18n("mods.check_updates.file"));
|
||||
fileNameColumn.setPrefWidth(200);
|
||||
setupCellValueFactory(fileNameColumn, ModUpdateObject::fileNameProperty);
|
||||
|
||||
JFXTreeTableColumn<ModUpdateObject, String> currentVersionColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.current_version"));
|
||||
TableColumn<ModUpdateObject, String> currentVersionColumn = new TableColumn<>(i18n("mods.check_updates.current_version"));
|
||||
currentVersionColumn.setPrefWidth(200);
|
||||
setupCellValueFactory(currentVersionColumn, ModUpdateObject::currentVersionProperty);
|
||||
|
||||
JFXTreeTableColumn<ModUpdateObject, String> targetVersionColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.target_version"));
|
||||
TableColumn<ModUpdateObject, String> targetVersionColumn = new TableColumn<>(i18n("mods.check_updates.target_version"));
|
||||
targetVersionColumn.setPrefWidth(200);
|
||||
setupCellValueFactory(targetVersionColumn, ModUpdateObject::targetVersionProperty);
|
||||
|
||||
JFXTreeTableColumn<ModUpdateObject, String> sourceColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.source"));
|
||||
TableColumn<ModUpdateObject, String> sourceColumn = new TableColumn<>(i18n("mods.check_updates.source"));
|
||||
setupCellValueFactory(sourceColumn, ModUpdateObject::sourceProperty);
|
||||
|
||||
objects = FXCollections.observableList(updates.stream().map(ModUpdateObject::new).collect(Collectors.toList()));
|
||||
|
||||
RecursiveTreeItem<ModUpdateObject> root = new RecursiveTreeItem<>(
|
||||
objects,
|
||||
RecursiveTreeObject::getChildren);
|
||||
|
||||
JFXTreeTableView<ModUpdateObject> table = new JFXTreeTableView<>(root);
|
||||
table.setShowRoot(false);
|
||||
TableView<ModUpdateObject> table = new TableView<>(objects);
|
||||
table.setEditable(true);
|
||||
table.getColumns().setAll(enabledColumn, fileNameColumn, currentVersionColumn, targetVersionColumn, sourceColumn);
|
||||
|
||||
@ -111,9 +110,6 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
||||
JFXButton nextButton = new JFXButton(i18n("mods.check_updates.update"));
|
||||
nextButton.getStyleClass().add("jfx-button-raised");
|
||||
nextButton.setButtonType(JFXButton.ButtonType.RAISED);
|
||||
nextButton.setOnAction(e -> {
|
||||
if (isModpack) updateModpackModWarningDialog();
|
||||
});
|
||||
|
||||
JFXButton cancelButton = new JFXButton(i18n("button.cancel"));
|
||||
cancelButton.getStyleClass().add("jfx-button-raised");
|
||||
@ -125,38 +121,8 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
||||
setBottom(actions);
|
||||
}
|
||||
|
||||
private <T> void setupCellValueFactory(JFXTreeTableColumn<ModUpdateObject, T> column, Function<ModUpdateObject, ObservableValue<T>> mapper) {
|
||||
column.setCellValueFactory(param -> {
|
||||
if (column.validateValue(param))
|
||||
return mapper.apply(param.getValue().getValue());
|
||||
else
|
||||
return column.getComputedValue(param);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateModpackModWarningDialog() {
|
||||
JFXDialogLayout warningPane = new JFXDialogLayout();
|
||||
warningPane.setHeading(new Label(i18n("message.warning"), SVG.alert(new ObjectBinding<Paint>() {
|
||||
@Override
|
||||
protected Paint computeValue() {
|
||||
return Color.ORANGERED;
|
||||
}
|
||||
}, -1, -1)));
|
||||
warningPane.setBody(new Label(i18n("mods.update_modpack_mod.warning")));
|
||||
JFXButton yesButton = new JFXButton(i18n("button.yes"));
|
||||
yesButton.getStyleClass().add("dialog-accept");
|
||||
yesButton.setOnAction(event -> {
|
||||
warningPane.fireEvent(new DialogCloseEvent());
|
||||
updateMods();
|
||||
});
|
||||
JFXButton noButton = new JFXButton(i18n("button.cancel"));
|
||||
noButton.getStyleClass().add("dialog-cancel");
|
||||
noButton.setOnAction(event -> {
|
||||
// Do nothing.
|
||||
warningPane.fireEvent(new DialogCloseEvent());
|
||||
});
|
||||
warningPane.setActions(yesButton, noButton);
|
||||
Controllers.dialog(warningPane);
|
||||
private <T> void setupCellValueFactory(TableColumn<ModUpdateObject, T> column, Function<ModUpdateObject, ObservableValue<T>> mapper) {
|
||||
column.setCellValueFactory(param -> mapper.apply(param.getValue()));
|
||||
}
|
||||
|
||||
private void updateMods() {
|
||||
@ -189,7 +155,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
||||
return state;
|
||||
}
|
||||
|
||||
public static class ModUpdateCell extends MDListCell<LocalModFile.ModUpdate> {
|
||||
public static final class ModUpdateCell extends MDListCell<LocalModFile.ModUpdate> {
|
||||
TwoLineListItem content = new TwoLineListItem();
|
||||
|
||||
public ModUpdateCell(JFXListView<LocalModFile.ModUpdate> listView, MutableObject<Object> lastCell) {
|
||||
@ -214,7 +180,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ModUpdateObject extends RecursiveTreeObject<ModUpdateObject> {
|
||||
private static final class ModUpdateObject {
|
||||
final LocalModFile.ModUpdate data;
|
||||
final BooleanProperty enabled = new SimpleBooleanProperty();
|
||||
final StringProperty fileName = new SimpleStringProperty();
|
||||
|
@ -705,7 +705,7 @@ mods.name=名稱
|
||||
mods.not_modded=你需要先在自動安裝頁面安裝 Fabric、Forge 或 LiteLoader 才能進行模組管理。
|
||||
mods.restore=回退
|
||||
mods.url=官方頁面
|
||||
mods.update_modpack_mod.warning=更新整合包中的Mod可能導致整合包損壞,使整合包無法正常啟動。該操作不可逆,確定要更新嗎?
|
||||
mods.update_modpack_mod.warning=更新模組包中的 Mod 可能導致綜合包損壞,使模組包無法正常啟動。該操作不可逆,確定要更新嗎?
|
||||
|
||||
multiplayer=多人聯機
|
||||
multiplayer.agreement.prompt=多人聯機功能由 速聚 提供。使用前,你需要先同意多人聯機服務提供方 速聚 的用戶協議與免責聲明。\n你需要了解,HMCL 僅為 速聚 提供多人聯機服務入口,使用中遇到的任何問題由 速聚 負責處理。您在使用多人聯機服務過程中所遇到的任何問題與糾紛(包括其付費業務)均與 HMCL 無關,應與 速聚 協商解決。
|
||||
|
@ -707,7 +707,7 @@ mods.name=名称
|
||||
mods.not_modded=你需要先在自动安装页面安装 Fabric、Forge 或 LiteLoader 才能进行模组管理!
|
||||
mods.restore=回退
|
||||
mods.url=官方页面
|
||||
mods.update_modpack_mod.warning=更新整合包中的Mod可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗?
|
||||
mods.update_modpack_mod.warning=更新整合包中的 Mod 可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗?
|
||||
|
||||
multiplayer=多人联机
|
||||
multiplayer.agreement.prompt=多人联机功能由 速聚 提供。使用前,你需要先同意多人联机服务提供方 速聚 的用户协议与免责声明。\n你需要了解,HMCL 仅为 速聚 提供多人联机服务入口,使用中遇到的任何问题由 速聚 负责处理。\n您在使用多人联机服务过程中所遇到的任何问题与纠纷(包括其付费业务)均与 HMCL 无关,请与 速聚 协商解决。
|
||||
|
Loading…
Reference in New Issue
Block a user