mirror of
https://github.com/SKCraft/Launcher.git
synced 2025-01-06 19:18:27 +01:00
Refactor controller out of mod management dialog
This commit is contained in:
parent
966205d68a
commit
badd91d2b8
@ -15,7 +15,9 @@ import com.skcraft.launcher.swing.LinedBoxPanel;
|
||||
import com.skcraft.launcher.swing.SwingHelper;
|
||||
import com.skcraft.launcher.util.SwingExecutor;
|
||||
import com.skcraft.plugin.curse.CurseApi;
|
||||
import com.skcraft.plugin.curse.model.*;
|
||||
import com.skcraft.plugin.curse.model.AddedMod;
|
||||
import com.skcraft.plugin.curse.model.CurseProject;
|
||||
import com.skcraft.plugin.curse.model.ProjectHolder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.java.Log;
|
||||
|
||||
@ -34,34 +36,28 @@ import static com.skcraft.launcher.util.HttpRequest.url;
|
||||
|
||||
@Log
|
||||
public class CurseModsDialog extends JDialog {
|
||||
private final CurseSearchResults searchResults = new CurseSearchResults();
|
||||
private final LoadedModList modList = new LoadedModList();
|
||||
private final CursePack cursePack;
|
||||
|
||||
private final JPanel panel = new JPanel(new BorderLayout(0, 5));
|
||||
private final JTextField searchBox = new JTextField();
|
||||
private final JButton searchButton = new JButton("Search");
|
||||
private final JList<CurseProject> searchPane = new JList<>(searchResults);
|
||||
private final JList<LoadedMod> selectedPane = new JList<>(modList);
|
||||
private final JList<CurseProject> searchPane = new JList<>();
|
||||
private final JList<AddedMod> selectedPane = new JList<>();
|
||||
private final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(searchPane), new JScrollPane(selectedPane));
|
||||
private final JButton addMod = new JButton("Add Mods >>");
|
||||
private final JButton removeMod = new JButton("Remove Mods");
|
||||
private final JButton removeMod = new JButton("<< Remove Mods");
|
||||
private final JButton done = new JButton("Done");
|
||||
|
||||
private final CurseProjectListRenderer projectRenderer = new CurseProjectListRenderer();
|
||||
|
||||
private final ListeningExecutorService executor;
|
||||
private final ObjectMapper mapper;
|
||||
private final Pack pack;
|
||||
private final File curseModsDir;
|
||||
|
||||
public CurseModsDialog(Window owner, ListeningExecutorService executor, ObjectMapper mapper, Pack pack, List<LoadedMod> currentMods) {
|
||||
public CurseModsDialog(Window owner, ListeningExecutorService executor, Pack pack, CursePack cursePack) {
|
||||
super(owner);
|
||||
this.executor = executor;
|
||||
this.mapper = mapper;
|
||||
this.pack = pack;
|
||||
this.curseModsDir = new File(pack.getDirectory(), "cursemods");
|
||||
|
||||
modList.addAll(currentMods);
|
||||
this.cursePack = cursePack;
|
||||
|
||||
initComponents();
|
||||
setMinimumSize(new Dimension(500, 450));
|
||||
@ -70,11 +66,13 @@ public class CurseModsDialog extends JDialog {
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
searchPane.setModel(cursePack.getSearchResults());
|
||||
searchPane.setCellRenderer(projectRenderer);
|
||||
searchPane.setLayoutOrientation(JList.VERTICAL);
|
||||
searchPane.setVisibleRowCount(0);
|
||||
searchPane.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
|
||||
selectedPane.setModel(cursePack.getModList());
|
||||
selectedPane.setCellRenderer(projectRenderer);
|
||||
selectedPane.setLayoutOrientation(JList.VERTICAL);
|
||||
selectedPane.setVisibleRowCount(0);
|
||||
@ -107,41 +105,17 @@ public class CurseModsDialog extends JDialog {
|
||||
searchButton.addActionListener(e -> search());
|
||||
|
||||
addMod.addActionListener(e -> {
|
||||
for (CurseProject project : searchPane.getSelectedValuesList()) {
|
||||
GameVersionFile forVersion = project.findFileForVersion(pack.getCachedConfig().getGameVersion());
|
||||
ListenableFuture<Object> future = executor.submit(cursePack.addMany(searchPane.getSelectedValuesList()));
|
||||
|
||||
if (forVersion == null) {
|
||||
SwingHelper.showErrorDialog(
|
||||
getOwner(),
|
||||
String.format("Mod %s isn't available for this version.", project.getName()),
|
||||
"Mod Unavailable"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadedMod loadedMod = project.toLoadedMod(forVersion);
|
||||
modList.add(loadedMod);
|
||||
|
||||
executor.submit(() -> {
|
||||
File target = loadedMod.getDiskLocation(curseModsDir);
|
||||
|
||||
log.info(String.format("Saving mod %s", target.getName()));
|
||||
mapper.writeValue(target, loadedMod.getMod());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
// TODO: Update a progress bar built in to the dialog.
|
||||
SwingHelper.addErrorDialogCallback(getOwner(), future);
|
||||
});
|
||||
|
||||
removeMod.addActionListener(e -> {
|
||||
for (LoadedMod mod : selectedPane.getSelectedValuesList()) {
|
||||
modList.remove(mod);
|
||||
ListenableFuture<Object> future = executor.submit(
|
||||
cursePack.removeMany(selectedPane.getSelectedValuesList()));
|
||||
|
||||
File target = mod.getDiskLocation(curseModsDir);
|
||||
log.info(String.format("Removing mod %s", target.getName()));
|
||||
if (!target.delete()) {
|
||||
SwingHelper.showErrorDialog(getOwner(), String.format("Failed to delete %s", target), "I/O error");
|
||||
}
|
||||
}
|
||||
SwingHelper.addErrorDialogCallback(getOwner(), future);
|
||||
});
|
||||
|
||||
done.addActionListener(e -> dispose());
|
||||
@ -163,7 +137,7 @@ public class CurseModsDialog extends JDialog {
|
||||
@Override
|
||||
public void onSuccess(List<CurseProject> result) {
|
||||
projectRenderer.clearCacheIfBig();
|
||||
searchResults.updateResults(result);
|
||||
cursePack.getSearchResults().updateResults(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -298,7 +272,10 @@ public class CurseModsDialog extends JDialog {
|
||||
SwingHelper.addErrorDialogCallback(ctx.getOwner(), future);
|
||||
|
||||
future.addListener(() -> {
|
||||
CurseModsDialog dialog = new CurseModsDialog(ctx.getOwner(), ctx.getExecutor(), mapper, pack, scanner.getResult());
|
||||
CursePack cursePack = new CursePack(mapper, pack);
|
||||
cursePack.getModList().addAll(scanner.getResult());
|
||||
|
||||
CurseModsDialog dialog = new CurseModsDialog(ctx.getOwner(), ctx.getExecutor(), pack, cursePack);
|
||||
dialog.setTitle(getTitle());
|
||||
dialog.setVisible(true);
|
||||
}, SwingExecutor.INSTANCE);
|
||||
|
@ -0,0 +1,127 @@
|
||||
package com.skcraft.plugin.curse.creator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.skcraft.concurrency.ProgressObservable;
|
||||
import com.skcraft.concurrency.SettableProgress;
|
||||
import com.skcraft.launcher.creator.model.creator.Pack;
|
||||
import com.skcraft.plugin.curse.model.*;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.java.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@Log
|
||||
public class CursePack {
|
||||
@Getter private final CurseSearchResults searchResults = new CurseSearchResults();
|
||||
@Getter private final AddedModList modList = new AddedModList();
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
private final String gameVersion;
|
||||
private final File curseModsDir;
|
||||
|
||||
public CursePack(ObjectMapper mapper, Pack pack) {
|
||||
this.mapper = mapper;
|
||||
this.gameVersion = pack.getCachedConfig().getGameVersion();
|
||||
this.curseModsDir = new File(pack.getDirectory(), "cursemods");
|
||||
}
|
||||
|
||||
public void addMod(CurseProject project) throws IOException, MissingVersionException {
|
||||
GameVersionFile forVersion = project.findFileForVersion(gameVersion);
|
||||
|
||||
if (forVersion == null) {
|
||||
throw new MissingVersionException("Mod %s isn't available for this version.");
|
||||
}
|
||||
|
||||
AddedMod loadedMod = project.toLoadedMod(forVersion);
|
||||
modList.add(loadedMod);
|
||||
|
||||
File target = loadedMod.getDiskLocation(curseModsDir);
|
||||
log.info(String.format("Saving mod %s", target.getName()));
|
||||
mapper.writeValue(target, loadedMod.getMod());
|
||||
}
|
||||
|
||||
public void removeMod(AddedMod mod) throws IOException {
|
||||
modList.remove(mod);
|
||||
|
||||
File target = mod.getDiskLocation(curseModsDir);
|
||||
log.info(String.format("Removing mod %s", target.getName()));
|
||||
if (!target.delete()) {
|
||||
throw new IOException(String.format("Failed to delete %s", target));
|
||||
}
|
||||
}
|
||||
|
||||
public AddModsCall addMany(List<CurseProject> projects) {
|
||||
return new AddModsCall(projects);
|
||||
}
|
||||
|
||||
public RemoveModsCall removeMany(List<AddedMod> mods) {
|
||||
return new RemoveModsCall(mods);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class AddModsCall implements Callable<Object>, ProgressObservable {
|
||||
private final List<CurseProject> projects;
|
||||
private final SettableProgress progress = new SettableProgress("", -1);
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
int current = 0;
|
||||
int total = projects.size();
|
||||
|
||||
for (CurseProject project : projects) {
|
||||
progress.set(String.format("Adding mod %s", project.getName()), 100 * (double) current / total);
|
||||
|
||||
addMod(project);
|
||||
current++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProgress() {
|
||||
return progress.getProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return progress.getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class RemoveModsCall implements Callable<Object>, ProgressObservable {
|
||||
private final List<AddedMod> mods;
|
||||
private final SettableProgress progress = new SettableProgress("", -1);
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
int current = 0;
|
||||
int total = mods.size();
|
||||
|
||||
for (AddedMod mod : mods) {
|
||||
progress.set(String.format("Removing mod %s", mod.getProject().getName()),
|
||||
100 * (double) current / total);
|
||||
|
||||
removeMod(mod);
|
||||
current++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getProgress() {
|
||||
return progress.getProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return progress.getStatus();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,9 +4,9 @@ import com.beust.jcommander.internal.Lists;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.skcraft.launcher.builder.DirectoryWalker;
|
||||
import com.skcraft.plugin.curse.CurseApi;
|
||||
import com.skcraft.plugin.curse.model.AddedMod;
|
||||
import com.skcraft.plugin.curse.model.CurseMod;
|
||||
import com.skcraft.plugin.curse.model.CurseProject;
|
||||
import com.skcraft.plugin.curse.model.LoadedMod;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
@ -19,7 +19,7 @@ import java.util.List;
|
||||
public class PackModScanner extends DirectoryWalker {
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
@Getter private final List<LoadedMod> result = Lists.newArrayList();
|
||||
@Getter private final List<AddedMod> result = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@ -27,6 +27,6 @@ public class PackModScanner extends DirectoryWalker {
|
||||
CurseMod mod = mapper.readValue(file, CurseMod.class);
|
||||
CurseProject project = CurseApi.getById(mod.getProjectId());
|
||||
|
||||
result.add(new LoadedMod(mod, project));
|
||||
result.add(new AddedMod(mod, project));
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import java.io.File;
|
||||
* Represents mod metadata cached in-memory for the purpose of rendering the "Add Mods" screen.
|
||||
*/
|
||||
@Data
|
||||
public class LoadedMod implements ProjectHolder {
|
||||
public class AddedMod implements ProjectHolder {
|
||||
private final CurseMod mod;
|
||||
private final CurseProject project;
|
||||
|
@ -6,8 +6,8 @@ import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class LoadedModList extends AbstractListModel<LoadedMod> {
|
||||
private List<LoadedMod> mods = Lists.newArrayList();
|
||||
public class AddedModList extends AbstractListModel<AddedMod> {
|
||||
private List<AddedMod> mods = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
@ -15,24 +15,24 @@ public class LoadedModList extends AbstractListModel<LoadedMod> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadedMod getElementAt(int index) {
|
||||
public AddedMod getElementAt(int index) {
|
||||
return mods.get(index);
|
||||
}
|
||||
|
||||
public void addAll(Collection<? extends LoadedMod> other) {
|
||||
public void addAll(Collection<? extends AddedMod> other) {
|
||||
int start = mods.size();
|
||||
mods.addAll(other);
|
||||
fireIntervalAdded(this, start, start + other.size());
|
||||
}
|
||||
|
||||
public void add(LoadedMod mod) {
|
||||
public void add(AddedMod mod) {
|
||||
mods.add(mod);
|
||||
|
||||
int idx = mods.size() - 1;
|
||||
fireIntervalAdded(this, idx, idx);
|
||||
}
|
||||
|
||||
public void remove(LoadedMod mod) {
|
||||
public void remove(AddedMod mod) {
|
||||
int index = mods.indexOf(mod);
|
||||
|
||||
if (index > -1) {
|
@ -32,9 +32,9 @@ public class CurseProject implements ProjectHolder {
|
||||
return null;
|
||||
}
|
||||
|
||||
public LoadedMod toLoadedMod(GameVersionFile versionFile) {
|
||||
public AddedMod toLoadedMod(GameVersionFile versionFile) {
|
||||
CurseMod mod = new CurseMod(id, versionFile.getProjectFileId(), null);
|
||||
return new LoadedMod(mod, this);
|
||||
return new AddedMod(mod, this);
|
||||
}
|
||||
|
||||
public Attachment getDefaultIcon() {
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.skcraft.plugin.curse.model;
|
||||
|
||||
public class MissingVersionException extends Exception {
|
||||
public MissingVersionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MissingVersionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user