* Fix #2010 * Improve behaviour * Add License
This commit is contained in:
@@ -42,8 +42,14 @@ import org.jackhuang.hmcl.ui.construct.PageCloseEvent;
|
|||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
import org.jackhuang.hmcl.util.TaskCancellationAction;
|
import org.jackhuang.hmcl.util.TaskCancellationAction;
|
||||||
|
import org.jackhuang.hmcl.util.io.CSVTable;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -100,6 +106,9 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
|||||||
actions.setPadding(new Insets(8));
|
actions.setPadding(new Insets(8));
|
||||||
actions.setAlignment(Pos.CENTER_RIGHT);
|
actions.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
|
||||||
|
JFXButton exportListButton = FXUtils.newRaisedButton(i18n("button.export"));
|
||||||
|
exportListButton.setOnAction(e -> exportList());
|
||||||
|
|
||||||
JFXButton nextButton = FXUtils.newRaisedButton(i18n("mods.check_updates.update"));
|
JFXButton nextButton = FXUtils.newRaisedButton(i18n("mods.check_updates.update"));
|
||||||
nextButton.setOnAction(e -> updateMods());
|
nextButton.setOnAction(e -> updateMods());
|
||||||
|
|
||||||
@@ -107,7 +116,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
|||||||
cancelButton.setOnAction(e -> fireEvent(new PageCloseEvent()));
|
cancelButton.setOnAction(e -> fireEvent(new PageCloseEvent()));
|
||||||
onEscPressed(this, cancelButton::fire);
|
onEscPressed(this, cancelButton::fire);
|
||||||
|
|
||||||
actions.getChildren().setAll(nextButton, cancelButton);
|
actions.getChildren().setAll(exportListButton, nextButton, cancelButton);
|
||||||
setBottom(actions);
|
setBottom(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +149,36 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
|
|||||||
TaskCancellationAction.NORMAL);
|
TaskCancellationAction.NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void exportList() {
|
||||||
|
Path path = Paths.get("hmcl-mod-update-list-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".csv").toAbsolutePath();
|
||||||
|
|
||||||
|
Controllers.taskDialog(Task.runAsync(() -> {
|
||||||
|
CSVTable csvTable = CSVTable.createEmpty();
|
||||||
|
|
||||||
|
csvTable.set(0, 0, "Source File Name");
|
||||||
|
csvTable.set(1, 0, "Current Version");
|
||||||
|
csvTable.set(2, 0, "Target Version");
|
||||||
|
csvTable.set(3, 0, "Update Source");
|
||||||
|
|
||||||
|
for (int i = 0; i < objects.size(); i++) {
|
||||||
|
csvTable.set(0, i + 1, objects.get(i).fileName.get());
|
||||||
|
csvTable.set(1, i + 1, objects.get(i).currentVersion.get());
|
||||||
|
csvTable.set(2, i + 1, objects.get(i).targetVersion.get());
|
||||||
|
csvTable.set(3, i + 1, objects.get(i).source.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
csvTable.write(Files.newOutputStream(path));
|
||||||
|
|
||||||
|
FXUtils.showFileInExplorer(path);
|
||||||
|
}).whenComplete(exception -> {
|
||||||
|
if (exception == null) {
|
||||||
|
Controllers.dialog(path.toString(), i18n("message.success"));
|
||||||
|
} else {
|
||||||
|
Controllers.dialog("", i18n("message.error"), MessageDialogPane.MessageType.ERROR);
|
||||||
|
}
|
||||||
|
}), i18n("button.export"), TaskCancellationAction.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReadOnlyObjectWrapper<State> stateProperty() {
|
public ReadOnlyObjectWrapper<State> stateProperty() {
|
||||||
return state;
|
return state;
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2020 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.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public final class InfiniteSizeList<T> extends ArrayList<T> {
|
||||||
|
private int actualSize;
|
||||||
|
|
||||||
|
public InfiniteSizeList(int initialCapacity) {
|
||||||
|
super(initialCapacity);
|
||||||
|
|
||||||
|
this.actualSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InfiniteSizeList() {
|
||||||
|
this.actualSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InfiniteSizeList(@NotNull Collection<? extends T> c) {
|
||||||
|
super(c);
|
||||||
|
|
||||||
|
this.actualSize = 0;
|
||||||
|
for (int i = super.size() - 1; i >= 0; i--) {
|
||||||
|
if (super.get(i) != null) {
|
||||||
|
actualSize = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
if (index >= super.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T set(int index, T element) {
|
||||||
|
if (element == null) { // The element is null.
|
||||||
|
if (index >= super.size()) {
|
||||||
|
return null; // The element (actually null) is out of the allocated size.
|
||||||
|
}
|
||||||
|
|
||||||
|
T previous = super.get(index);
|
||||||
|
if (previous != null) { // !null -> null
|
||||||
|
super.set(index, null);
|
||||||
|
|
||||||
|
if (index == this.actualSize - 1) { // Recalculate the actualSize.
|
||||||
|
this.actualSize = 0;
|
||||||
|
|
||||||
|
for (int i = index - 1; i >= 0; i--) {
|
||||||
|
if (super.get(i) != null) {
|
||||||
|
this.actualSize = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return previous;
|
||||||
|
} else { // null -> null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The element isn't null.
|
||||||
|
|
||||||
|
if (index >= super.size()) {
|
||||||
|
allocate0(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
T previous = super.get(index);
|
||||||
|
if (previous != null) { // !null -> !null
|
||||||
|
super.set(index, element);
|
||||||
|
return previous;
|
||||||
|
} else { // null -> !null
|
||||||
|
super.set(index, element);
|
||||||
|
if (index >= this.actualSize) {
|
||||||
|
this.actualSize = index + 1;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void allocate0(int index) {
|
||||||
|
super.ensureCapacity(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return actualSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2020 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.util.io;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.util.InfiniteSizeList;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class CSVTable {
|
||||||
|
private final List<List<String>> table = new InfiniteSizeList<>();
|
||||||
|
|
||||||
|
private CSVTable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CSVTable createEmpty() {
|
||||||
|
return new CSVTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(int x, int y) {
|
||||||
|
List<String> row = table.get(y);
|
||||||
|
if (row == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return row.get(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int x, int y, String txt) {
|
||||||
|
List<String> row = table.get(y);
|
||||||
|
if (row == null) {
|
||||||
|
row = new InfiniteSizeList<>(x);
|
||||||
|
table.set(y, row);
|
||||||
|
}
|
||||||
|
row.set(x, txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(OutputStream outputStream) throws IOException {
|
||||||
|
try (PrintWriter printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
|
||||||
|
outputStream, StandardCharsets.UTF_8)), false
|
||||||
|
)) {
|
||||||
|
for (List<String> row : this.table) {
|
||||||
|
if (row != null) {
|
||||||
|
for (int j = 0; j < row.size(); j++) {
|
||||||
|
String txt = row.get(j);
|
||||||
|
if (txt != null) {
|
||||||
|
printWriter.write(this.escape(txt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j != row.size() - 1) {
|
||||||
|
printWriter.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printWriter.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String escape(String txt) {
|
||||||
|
if (!txt.contains("\"") && !txt.contains(",")) {
|
||||||
|
return txt;
|
||||||
|
} else {
|
||||||
|
return "\"" + txt.replace("\"", "\"\"") + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user