added PerMainWindowInjector
parent
0e9e935fca
commit
0968c20de4
|
@ -7,6 +7,7 @@ import amidst.documentation.CalledOnlyBy;
|
|||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.license.LicenseWindow;
|
||||
import amidst.gui.main.MainWindow;
|
||||
import amidst.gui.main.MainWindowDialogs;
|
||||
import amidst.gui.main.UpdatePrompt;
|
||||
import amidst.gui.profileselect.ProfileSelectWindow;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
|
@ -14,7 +15,7 @@ import amidst.mojangapi.MojangApi;
|
|||
@NotThreadSafe
|
||||
public class Application {
|
||||
private final MojangApi mojangApi;
|
||||
private final Factory1<MainWindow, UpdatePrompt> noisyUpdatePromptFactory;
|
||||
private final Factory1<MainWindowDialogs, UpdatePrompt> noisyUpdatePromptFactory;
|
||||
private final Factory0<UpdatePrompt> silentUpdatePromptFactory;
|
||||
private final Factory0<MainWindow> mainWindowFactory;
|
||||
private final Factory0<ProfileSelectWindow> profileSelectWindowFactory;
|
||||
|
@ -26,7 +27,7 @@ public class Application {
|
|||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public Application(
|
||||
MojangApi mojangApi,
|
||||
Factory1<MainWindow, UpdatePrompt> noisyUpdatePromptFactory,
|
||||
Factory1<MainWindowDialogs, UpdatePrompt> noisyUpdatePromptFactory,
|
||||
Factory0<UpdatePrompt> silentUpdatePromptFactory,
|
||||
Factory0<MainWindow> mainWindowFactory,
|
||||
Factory0<ProfileSelectWindow> profileSelectWindowFactory,
|
||||
|
@ -50,8 +51,8 @@ public class Application {
|
|||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void checkForUpdates(MainWindow mainWindow) {
|
||||
noisyUpdatePromptFactory.create(mainWindow).check();
|
||||
public void checkForUpdates(MainWindowDialogs dialogs) {
|
||||
noisyUpdatePromptFactory.create(dialogs).check();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
|
|
|
@ -12,6 +12,7 @@ import amidst.fragment.layer.LayerBuilder;
|
|||
import amidst.gui.license.LicenseWindow;
|
||||
import amidst.gui.main.Actions;
|
||||
import amidst.gui.main.MainWindow;
|
||||
import amidst.gui.main.MainWindowDialogs;
|
||||
import amidst.gui.main.UpdatePrompt;
|
||||
import amidst.gui.main.viewer.BiomeSelection;
|
||||
import amidst.gui.main.viewer.ViewerFacade;
|
||||
|
@ -71,8 +72,8 @@ public class PerApplicationInjector {
|
|||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private UpdatePrompt createNoisyUpdatePrompt(MainWindow mainWindow) {
|
||||
return UpdatePrompt.from(metadata.getVersion(), threadMaster.getWorkerExecutor(), mainWindow, false);
|
||||
private UpdatePrompt createNoisyUpdatePrompt(MainWindowDialogs dialogs) {
|
||||
return UpdatePrompt.from(metadata.getVersion(), threadMaster.getWorkerExecutor(), dialogs, false);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
|
@ -82,14 +83,14 @@ public class PerApplicationInjector {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private MainWindow createMainWindow() {
|
||||
return new MainWindow(
|
||||
return new PerMainWindowInjector(
|
||||
application,
|
||||
metadata,
|
||||
settings,
|
||||
mojangApi,
|
||||
biomeProfileDirectory,
|
||||
this::createViewerFacade,
|
||||
threadMaster);
|
||||
threadMaster).getMainWindow();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package amidst.dependency.injection;
|
||||
|
||||
import java.awt.Container;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import amidst.AmidstMetaData;
|
||||
import amidst.AmidstSettings;
|
||||
import amidst.Application;
|
||||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.main.Actions;
|
||||
import amidst.gui.main.MainWindow;
|
||||
import amidst.gui.main.MainWindowDialogs;
|
||||
import amidst.gui.main.WorldSwitcher;
|
||||
import amidst.gui.main.menu.AmidstMenu;
|
||||
import amidst.gui.main.menu.AmidstMenuBuilder;
|
||||
import amidst.gui.main.viewer.ViewerFacade;
|
||||
import amidst.gui.seedsearcher.SeedSearcher;
|
||||
import amidst.gui.seedsearcher.SeedSearcherWindow;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
import amidst.mojangapi.world.World;
|
||||
import amidst.settings.biomeprofile.BiomeProfileDirectory;
|
||||
import amidst.threading.ThreadMaster;
|
||||
|
||||
@NotThreadSafe
|
||||
public class PerMainWindowInjector {
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private static String createVersionString(AmidstMetaData metadata, MojangApi mojangApi) {
|
||||
return metadata.getVersion().createLongVersionString() + " - Selected Profile: " + mojangApi.getProfileName()
|
||||
+ " - Minecraft Version " + mojangApi.getVersionId() + " (recognised: "
|
||||
+ mojangApi.getRecognisedVersionName() + ")";
|
||||
}
|
||||
|
||||
private final Factory2<World, Actions, ViewerFacade> viewerFacadeFactory;
|
||||
private final String versionString;
|
||||
private final JFrame frame;
|
||||
private final Container contentPane;
|
||||
private final AtomicReference<ViewerFacade> viewerFacadeReference;
|
||||
private final MainWindowDialogs dialogs;
|
||||
private final WorldSwitcher worldSwitcher;
|
||||
private final SeedSearcher seedSearcher;
|
||||
private final SeedSearcherWindow seedSearcherWindow;
|
||||
private final Actions actions;
|
||||
private final AmidstMenu menuBar;
|
||||
private final MainWindow mainWindow;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public PerMainWindowInjector(
|
||||
Application application,
|
||||
AmidstMetaData metadata,
|
||||
AmidstSettings settings,
|
||||
MojangApi mojangApi,
|
||||
BiomeProfileDirectory biomeProfileDirectory,
|
||||
Factory2<World, Actions, ViewerFacade> viewerFacadeFactory,
|
||||
ThreadMaster threadMaster) {
|
||||
this.viewerFacadeFactory = viewerFacadeFactory;
|
||||
this.versionString = createVersionString(metadata, mojangApi);
|
||||
this.frame = new JFrame();
|
||||
this.contentPane = frame.getContentPane();
|
||||
this.viewerFacadeReference = new AtomicReference<>();
|
||||
this.dialogs = new MainWindowDialogs(settings, mojangApi, frame);
|
||||
this.worldSwitcher = new WorldSwitcher(
|
||||
mojangApi,
|
||||
this::createViewerFacade,
|
||||
threadMaster,
|
||||
frame,
|
||||
contentPane,
|
||||
viewerFacadeReference,
|
||||
dialogs,
|
||||
this::getMenuBar);
|
||||
this.seedSearcher = new SeedSearcher(dialogs, mojangApi, threadMaster.getWorkerExecutor());
|
||||
this.seedSearcherWindow = new SeedSearcherWindow(metadata, dialogs, worldSwitcher, seedSearcher);
|
||||
this.actions = new Actions(
|
||||
application,
|
||||
dialogs,
|
||||
worldSwitcher,
|
||||
seedSearcherWindow,
|
||||
viewerFacadeReference::get,
|
||||
settings.biomeProfileSelection);
|
||||
this.menuBar = new AmidstMenuBuilder(settings, actions, biomeProfileDirectory).construct();
|
||||
this.mainWindow = new MainWindow(frame, worldSwitcher, seedSearcherWindow);
|
||||
this.mainWindow.initializeFrame(metadata, versionString, actions, menuBar);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private ViewerFacade createViewerFacade(World world) {
|
||||
return viewerFacadeFactory.create(world, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* This only exists to break the cyclic dependency between {@link #menuBar},
|
||||
* {@link #actions} and {@link #worldSwitcher}.
|
||||
*/
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private AmidstMenu getMenuBar() {
|
||||
return this.menuBar;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public MainWindow getMainWindow() {
|
||||
return mainWindow;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
@ -19,6 +19,7 @@ import amidst.documentation.NotThreadSafe;
|
|||
import amidst.gui.crash.CrashWindow;
|
||||
import amidst.gui.main.menu.MovePlayerPopupMenu;
|
||||
import amidst.gui.main.viewer.ViewerFacade;
|
||||
import amidst.gui.seedsearcher.SeedSearcherWindow;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.mojangapi.world.WorldSeed;
|
||||
import amidst.mojangapi.world.WorldType;
|
||||
|
@ -33,25 +34,31 @@ import amidst.util.FileExtensionChecker;
|
|||
@NotThreadSafe
|
||||
public class Actions {
|
||||
private final Application application;
|
||||
private final MainWindow mainWindow;
|
||||
private final AtomicReference<ViewerFacade> viewerFacade;
|
||||
private final MainWindowDialogs dialogs;
|
||||
private final WorldSwitcher worldSwitcher;
|
||||
private final SeedSearcherWindow seedSearcherWindow;
|
||||
private final Supplier<ViewerFacade> viewerFacadeSupplier;
|
||||
private final BiomeProfileSelection biomeProfileSelection;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public Actions(
|
||||
Application application,
|
||||
MainWindow mainWindow,
|
||||
AtomicReference<ViewerFacade> viewerFacade,
|
||||
MainWindowDialogs dialogs,
|
||||
WorldSwitcher worldSwitcher,
|
||||
SeedSearcherWindow seedSearcherWindow,
|
||||
Supplier<ViewerFacade> viewerFacadeSupplier,
|
||||
BiomeProfileSelection biomeProfileSelection) {
|
||||
this.application = application;
|
||||
this.mainWindow = mainWindow;
|
||||
this.viewerFacade = viewerFacade;
|
||||
this.dialogs = dialogs;
|
||||
this.worldSwitcher = worldSwitcher;
|
||||
this.seedSearcherWindow = seedSearcherWindow;
|
||||
this.viewerFacadeSupplier = viewerFacadeSupplier;
|
||||
this.biomeProfileSelection = biomeProfileSelection;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void newFromSeed() {
|
||||
WorldSeed seed = mainWindow.askForSeed();
|
||||
WorldSeed seed = dialogs.askForSeed();
|
||||
if (seed != null) {
|
||||
newFromSeed(seed);
|
||||
}
|
||||
|
@ -64,30 +71,30 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void newFromSeed(WorldSeed worldSeed) {
|
||||
WorldType worldType = mainWindow.askForWorldType();
|
||||
WorldType worldType = dialogs.askForWorldType();
|
||||
if (worldType != null) {
|
||||
mainWindow.displayWorld(worldSeed, worldType);
|
||||
worldSwitcher.displayWorld(worldSeed, worldType);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void searchForRandom() {
|
||||
mainWindow.displaySeedSearcherWindow();
|
||||
seedSearcherWindow.show();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void openSaveGame() {
|
||||
File file = mainWindow.askForSaveGame();
|
||||
File file = dialogs.askForSaveGame();
|
||||
if (file != null) {
|
||||
mainWindow.displayWorld(file);
|
||||
worldSwitcher.displayWorld(file);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void export() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.export(mainWindow.askForExportConfiguration());
|
||||
viewerFacade.export(dialogs.askForExportConfiguration());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,16 +110,16 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void goToCoordinate() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
String input = mainWindow.askForCoordinates();
|
||||
String input = dialogs.askForCoordinates();
|
||||
if (input != null) {
|
||||
CoordinatesInWorld coordinates = CoordinatesInWorld.tryParse(input);
|
||||
if (coordinates != null) {
|
||||
viewerFacade.centerOn(coordinates);
|
||||
} else {
|
||||
AmidstLogger.warn("Invalid location entered, ignoring.");
|
||||
mainWindow.displayError("You entered an invalid location.");
|
||||
dialogs.displayError("You entered an invalid location.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +127,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void goToSpawn() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.centerOn(viewerFacade.getSpawnWorldIcon());
|
||||
}
|
||||
|
@ -128,9 +135,9 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void goToStronghold() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
WorldIcon stronghold = mainWindow
|
||||
WorldIcon stronghold = dialogs
|
||||
.askForOptions("Go to", "Select Stronghold:", viewerFacade.getStrongholdWorldIcons());
|
||||
if (stronghold != null) {
|
||||
viewerFacade.centerOn(stronghold);
|
||||
|
@ -140,17 +147,17 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void goToPlayer() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
List<WorldIcon> playerWorldIcons = viewerFacade.getPlayerWorldIcons();
|
||||
if (!playerWorldIcons.isEmpty()) {
|
||||
WorldIcon player = mainWindow.askForOptions("Go to", "Select player:", playerWorldIcons);
|
||||
WorldIcon player = dialogs.askForOptions("Go to", "Select player:", playerWorldIcons);
|
||||
if (player != null) {
|
||||
viewerFacade.centerOn(player);
|
||||
}
|
||||
} else {
|
||||
AmidstLogger.warn("There are no players in this world.");
|
||||
mainWindow.displayError("There are no players in this world.");
|
||||
dialogs.displayError("There are no players in this world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,9 +174,9 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void savePlayerLocations() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
if (mainWindow.askToConfirmSaveGameManipulation()) {
|
||||
if (dialogs.askToConfirmSaveGameManipulation()) {
|
||||
viewerFacade.savePlayerLocations();
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +184,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void reloadPlayerLocations() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.loadPlayers();
|
||||
}
|
||||
|
@ -185,7 +192,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void howCanIMoveAPlayer() {
|
||||
mainWindow.displayInfo(
|
||||
dialogs.displayInfo(
|
||||
"How can I move a player?",
|
||||
"If you load the world from a save game, you can change the player locations.\n"
|
||||
+ "1. Scroll the map to and right-click on the new player location, this opens a popup menu.\n"
|
||||
|
@ -195,7 +202,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void copySeedToClipboard() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
String seed = "" + viewerFacade.getWorldSeed().getLong();
|
||||
StringSelection selection = new StringSelection(seed);
|
||||
|
@ -205,25 +212,25 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void saveCaptureImage() {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
BufferedImage image = viewerFacade.createCaptureImage();
|
||||
String suggestedFilename = "screenshot_" + viewerFacade.getWorldType().getFilenameText() + "_"
|
||||
+ viewerFacade.getWorldSeed().getLong() + ".png";
|
||||
File file = mainWindow.askForCaptureImageSaveFile(suggestedFilename);
|
||||
File file = dialogs.askForCaptureImageSaveFile(suggestedFilename);
|
||||
if (file != null) {
|
||||
file = appendPNGFileExtensionIfNecessary(file);
|
||||
if (file.exists() && !file.isFile()) {
|
||||
String message = "Unable to write capture image, because the target exists but is not a file: "
|
||||
+ file.getAbsolutePath();
|
||||
AmidstLogger.warn(message);
|
||||
mainWindow.displayError(message);
|
||||
dialogs.displayError(message);
|
||||
} else if (!canWriteToFile(file)) {
|
||||
String message = "Unable to write capture image, because you have no writing permissions: "
|
||||
+ file.getAbsolutePath();
|
||||
AmidstLogger.warn(message);
|
||||
mainWindow.displayError(message);
|
||||
} else if (!file.exists() || mainWindow.askToConfirmYesNo(
|
||||
dialogs.displayError(message);
|
||||
} else if (!file.exists() || dialogs.askToConfirmYesNo(
|
||||
"Replace file?",
|
||||
"File already exists. Do you want to replace it?\n" + file.getAbsolutePath() + "")) {
|
||||
saveImageToFile(image, file);
|
||||
|
@ -236,7 +243,7 @@ public class Actions {
|
|||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void selectBiomeProfile(BiomeProfile profile) {
|
||||
biomeProfileSelection.set(profile);
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.reloadBackgroundLayer();
|
||||
}
|
||||
|
@ -249,7 +256,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void checkForUpdates() {
|
||||
application.checkForUpdates(mainWindow);
|
||||
application.checkForUpdates(dialogs);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
|
@ -259,7 +266,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void about() {
|
||||
mainWindow.displayInfo(
|
||||
dialogs.displayInfo(
|
||||
"About",
|
||||
"Amidst - Advanced Minecraft Interfacing and Data/Structure Tracking\n\n"
|
||||
+ "Author: Skidoodle aka skiphs\n" + "Mail: toolbox4minecraft+amidst@gmail.com\n"
|
||||
|
@ -268,7 +275,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void adjustZoom(int notches) {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.adjustZoom(notches);
|
||||
}
|
||||
|
@ -276,7 +283,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void adjustZoom(Point mousePosition, int notches) {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.adjustZoom(mousePosition, notches);
|
||||
}
|
||||
|
@ -284,7 +291,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void selectWorldIcon(WorldIcon worldIcon) {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
viewerFacade.selectWorldIcon(worldIcon);
|
||||
}
|
||||
|
@ -292,7 +299,7 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void showPlayerPopupMenu(CoordinatesInWorld targetCoordinates, Component component, int x, int y) {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
if (viewerFacade.canSavePlayerLocations()) {
|
||||
new MovePlayerPopupMenu(this, viewerFacade.getMovablePlayerList(), targetCoordinates)
|
||||
|
@ -303,17 +310,16 @@ public class Actions {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void movePlayer(Player player, CoordinatesInWorld targetCoordinates) {
|
||||
ViewerFacade viewerFacade = this.viewerFacade.get();
|
||||
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
|
||||
if (viewerFacade != null) {
|
||||
PlayerCoordinates currentCoordinates = player.getPlayerCoordinates();
|
||||
long currentHeight = currentCoordinates.getY();
|
||||
String input = mainWindow.askForPlayerHeight(currentHeight);
|
||||
String input = dialogs.askForPlayerHeight(currentHeight);
|
||||
if (input != null) {
|
||||
player.moveTo(targetCoordinates, tryParseLong(input, currentHeight), currentCoordinates.getDimension());
|
||||
viewerFacade.reloadPlayerLayer();
|
||||
if (mainWindow
|
||||
.askToConfirmYesNo("Save Player Locations", "Do you want to save the player locations?")) {
|
||||
if (mainWindow.askToConfirmSaveGameManipulation()) {
|
||||
if (dialogs.askToConfirmYesNo("Save Player Locations", "Do you want to save the player locations?")) {
|
||||
if (dialogs.askToConfirmSaveGameManipulation()) {
|
||||
viewerFacade.savePlayerLocations();
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +348,7 @@ public class Actions {
|
|||
ImageIO.write(image, "png", file);
|
||||
} catch (IOException e) {
|
||||
AmidstLogger.warn(e);
|
||||
mainWindow.displayError(e);
|
||||
dialogs.displayError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,372 +1,52 @@
|
|||
package amidst.gui.main;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import amidst.AmidstMetaData;
|
||||
import amidst.AmidstSettings;
|
||||
import amidst.Application;
|
||||
import amidst.dependency.injection.Factory2;
|
||||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.main.menu.AmidstMenu;
|
||||
import amidst.gui.main.menu.AmidstMenuBuilder;
|
||||
import amidst.gui.main.viewer.ViewerFacade;
|
||||
import amidst.gui.seedsearcher.SeedSearcher;
|
||||
import amidst.gui.seedsearcher.SeedSearcherWindow;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.logging.AmidstMessageBox;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
import amidst.mojangapi.file.MojangApiParsingException;
|
||||
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
|
||||
import amidst.mojangapi.world.World;
|
||||
import amidst.mojangapi.world.WorldSeed;
|
||||
import amidst.mojangapi.world.WorldType;
|
||||
import amidst.mojangapi.world.export.WorldExporterConfiguration;
|
||||
import amidst.mojangapi.world.player.MovablePlayerList;
|
||||
import amidst.mojangapi.world.player.WorldPlayerType;
|
||||
import amidst.settings.biomeprofile.BiomeProfileDirectory;
|
||||
import amidst.threading.ThreadMaster;
|
||||
|
||||
@NotThreadSafe
|
||||
public class MainWindow {
|
||||
private final Application application;
|
||||
private final AmidstMetaData metadata;
|
||||
private final AmidstSettings settings;
|
||||
private final MojangApi mojangApi;
|
||||
private final BiomeProfileDirectory biomeProfileDirectory;
|
||||
private final Factory2<World, Actions, ViewerFacade> viewerFacadeFactory;
|
||||
private final ThreadMaster threadMaster;
|
||||
|
||||
private final JFrame frame;
|
||||
private final Container contentPane;
|
||||
private final Actions actions;
|
||||
private final AmidstMenu menuBar;
|
||||
private final WorldSwitcher worldSwitcher;
|
||||
private final SeedSearcherWindow seedSearcherWindow;
|
||||
|
||||
private final AtomicReference<ViewerFacade> viewerFacade = new AtomicReference<>();
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public MainWindow(
|
||||
Application application,
|
||||
AmidstMetaData metadata,
|
||||
AmidstSettings settings,
|
||||
MojangApi mojangApi,
|
||||
BiomeProfileDirectory biomeProfileDirectory,
|
||||
Factory2<World, Actions, ViewerFacade> viewerFacadeFactory,
|
||||
ThreadMaster threadMaster) {
|
||||
this.application = application;
|
||||
this.metadata = metadata;
|
||||
this.settings = settings;
|
||||
this.mojangApi = mojangApi;
|
||||
this.biomeProfileDirectory = biomeProfileDirectory;
|
||||
this.viewerFacadeFactory = viewerFacadeFactory;
|
||||
this.threadMaster = threadMaster;
|
||||
this.frame = createFrame();
|
||||
this.contentPane = createContentPane();
|
||||
this.actions = createActions();
|
||||
this.menuBar = createMenuBar();
|
||||
this.seedSearcherWindow = createSeedSearcherWindow();
|
||||
initCloseListener();
|
||||
showFrame();
|
||||
clearViewerFacade();
|
||||
public MainWindow(JFrame frame, WorldSwitcher worldSwitcher, SeedSearcherWindow seedSearcherWindow) {
|
||||
this.frame = frame;
|
||||
this.worldSwitcher = worldSwitcher;
|
||||
this.seedSearcherWindow = seedSearcherWindow;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private JFrame createFrame() {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setTitle(
|
||||
createVersionString(
|
||||
mojangApi.getVersionId(),
|
||||
mojangApi.getRecognisedVersionName(),
|
||||
mojangApi.getProfileName()));
|
||||
public void initializeFrame(AmidstMetaData metadata, String versionString, Actions actions, AmidstMenu menuBar) {
|
||||
frame.setSize(1000, 800);
|
||||
frame.setIconImages(metadata.getIcons());
|
||||
return frame;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private String createVersionString(String versionId, String recognisedVersionName, String profileName) {
|
||||
return metadata.getVersion().createLongVersionString() + " - Selected Profile: " + profileName
|
||||
+ " - Minecraft Version " + versionId + " (recognised: " + recognisedVersionName + ")";
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private Container createContentPane() {
|
||||
Container contentPane = frame.getContentPane();
|
||||
contentPane.setLayout(new BorderLayout());
|
||||
return contentPane;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private Actions createActions() {
|
||||
return new Actions(application, this, viewerFacade, settings.biomeProfileSelection);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private AmidstMenu createMenuBar() {
|
||||
AmidstMenu menuBar = new AmidstMenuBuilder(settings, actions, biomeProfileDirectory).construct();
|
||||
frame.setTitle(versionString);
|
||||
frame.setJMenuBar(menuBar.getMenuBar());
|
||||
return menuBar;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private SeedSearcherWindow createSeedSearcherWindow() {
|
||||
return new SeedSearcherWindow(
|
||||
metadata,
|
||||
this,
|
||||
new SeedSearcher(this, mojangApi, threadMaster.getWorkerExecutor()));
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void initCloseListener() {
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
actions.exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void showFrame() {
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayWorld(WorldSeed worldSeed, WorldType worldType) {
|
||||
try {
|
||||
setWorld(mojangApi.createWorldFromSeed(worldSeed, worldType));
|
||||
} catch (IllegalStateException | MinecraftInterfaceException e) {
|
||||
AmidstLogger.warn(e);
|
||||
displayError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayWorld(File file) {
|
||||
try {
|
||||
setWorld(mojangApi.createWorldFromSaveGame(file));
|
||||
} catch (IllegalStateException | MinecraftInterfaceException | IOException | MojangApiParsingException e) {
|
||||
AmidstLogger.warn(e);
|
||||
displayError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void setWorld(World world) {
|
||||
clearViewerFacade();
|
||||
if (decideWorldPlayerType(world.getMovablePlayerList())) {
|
||||
setViewerFacade(viewerFacadeFactory.create(world, actions));
|
||||
} else {
|
||||
frame.revalidate();
|
||||
frame.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private boolean decideWorldPlayerType(MovablePlayerList movablePlayerList) {
|
||||
if (movablePlayerList.getWorldPlayerType().equals(WorldPlayerType.BOTH)) {
|
||||
WorldPlayerType worldPlayerType = askForWorldPlayerType();
|
||||
if (worldPlayerType != null) {
|
||||
movablePlayerList.setWorldPlayerType(worldPlayerType);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void setViewerFacade(ViewerFacade viewerFacade) {
|
||||
contentPane.add(viewerFacade.getComponent(), BorderLayout.CENTER);
|
||||
menuBar.set(viewerFacade);
|
||||
frame.validate();
|
||||
viewerFacade.loadPlayers();
|
||||
threadMaster.setOnRepaintTick(viewerFacade.getOnRepainterTick());
|
||||
threadMaster.setOnFragmentLoadTick(viewerFacade.getOnFragmentLoaderTick());
|
||||
this.viewerFacade.set(viewerFacade);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void clearViewerFacade() {
|
||||
threadMaster.clearOnRepaintTick();
|
||||
threadMaster.clearOnFragmentLoadTick();
|
||||
ViewerFacade viewerFacade = this.viewerFacade.getAndSet(null);
|
||||
if (viewerFacade != null) {
|
||||
contentPane.remove(viewerFacade.getComponent());
|
||||
viewerFacade.dispose();
|
||||
}
|
||||
menuBar.clear();
|
||||
worldSwitcher.clearWorld();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void dispose() {
|
||||
clearViewerFacade();
|
||||
worldSwitcher.clearWorld();
|
||||
seedSearcherWindow.dispose();
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private WorldPlayerType askForWorldPlayerType() {
|
||||
return askForOptions(
|
||||
"Loading World",
|
||||
"This world contains Multiplayer and Singleplayer data. What do you want to load?\n"
|
||||
+ "If you do not know what to do, just choose Singleplayer.",
|
||||
WorldPlayerType.getSelectable());
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldSeed askForSeed() {
|
||||
return new SeedPrompt(frame).askForSeed();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public File askForSaveGame() {
|
||||
return showOpenDialogAndGetSelectedFileOrNull(createSaveGameFileChooser());
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private JFileChooser createSaveGameFileChooser() {
|
||||
JFileChooser result = new JFileChooser(mojangApi.getSaves());
|
||||
result.setFileFilter(new LevelFileFilter());
|
||||
result.setAcceptAllFileFilterUsed(false);
|
||||
result.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
result.setFileHidingEnabled(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private File showOpenDialogAndGetSelectedFileOrNull(JFileChooser fileChooser) {
|
||||
if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
return fileChooser.getSelectedFile();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public File askForCaptureImageSaveFile(String suggestedFilename) {
|
||||
return showSaveDialogAndGetSelectedFileOrNull(createCaptureImageSaveFileChooser(suggestedFilename));
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private JFileChooser createCaptureImageSaveFileChooser(String suggestedFilename) {
|
||||
JFileChooser result = new JFileChooser();
|
||||
result.setFileFilter(new PNGFileFilter());
|
||||
result.setAcceptAllFileFilterUsed(false);
|
||||
result.setSelectedFile(new File(suggestedFilename));
|
||||
return result;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private File showSaveDialogAndGetSelectedFileOrNull(JFileChooser fileChooser) {
|
||||
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
return fileChooser.getSelectedFile();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayInfo(String title, String message) {
|
||||
AmidstMessageBox.displayInfo(frame, title, message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayError(String message) {
|
||||
AmidstMessageBox.displayError(frame, "Error", message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayError(Exception e) {
|
||||
AmidstMessageBox.displayError(frame, "Error", e);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public boolean askToConfirmSaveGameManipulation() {
|
||||
return askToConfirmYesNo(
|
||||
"Save Game Manipulation",
|
||||
"WARNING: You are about to change the contents of the save game directory. There is a chance that it gets corrupted.\n"
|
||||
+ "We try to minimize the risk by creating a backup of the changed file, before it is changed.\n"
|
||||
+ "If the backup fails, we will not write the changes.\n"
|
||||
+ "You can find the backup files in the directory 'amidst/backup', which is placed in the save game directory.\n"
|
||||
+ "Especially, make sure to not have the save game loaded in Minecraft during this process.\n\n"
|
||||
+ "Do you want to proceed?");
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public boolean askToConfirmYesNo(String title, String message) {
|
||||
return AmidstMessageBox.askToConfirmYesNo(frame, title, message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldType askForWorldType() {
|
||||
String worldTypeSetting = settings.worldType.get();
|
||||
if (worldTypeSetting.equals(WorldType.PROMPT_EACH_TIME)) {
|
||||
return askForOptions("World Type", "Enter world type\n", WorldType.getSelectable());
|
||||
} else {
|
||||
return WorldType.from(worldTypeSetting);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T askForOptions(String title, String message, List<T> choices) {
|
||||
Object[] choicesArray = choices.toArray();
|
||||
return (T) JOptionPane
|
||||
.showInputDialog(frame, message, title, JOptionPane.PLAIN_MESSAGE, null, choicesArray, choicesArray[0]);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public String askForCoordinates() {
|
||||
return askForString("Go To", "Enter coordinates: (Ex. 123,456)");
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public String askForPlayerHeight(long currentHeight) {
|
||||
Object input = JOptionPane.showInputDialog(
|
||||
frame,
|
||||
"Enter new player height:",
|
||||
"Move Player",
|
||||
JOptionPane.QUESTION_MESSAGE,
|
||||
null,
|
||||
null,
|
||||
currentHeight);
|
||||
if (input != null) {
|
||||
return input.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private String askForString(String title, String message) {
|
||||
return JOptionPane.showInputDialog(frame, message, title, JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displaySeedSearcherWindow() {
|
||||
seedSearcherWindow.show();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldExporterConfiguration askForExportConfiguration() {
|
||||
// TODO: implement me!
|
||||
// TODO: display gui to create configuration
|
||||
return new WorldExporterConfiguration();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
package amidst.gui.main;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import amidst.AmidstSettings;
|
||||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.logging.AmidstMessageBox;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
import amidst.mojangapi.world.WorldSeed;
|
||||
import amidst.mojangapi.world.WorldType;
|
||||
import amidst.mojangapi.world.export.WorldExporterConfiguration;
|
||||
import amidst.mojangapi.world.player.WorldPlayerType;
|
||||
|
||||
@NotThreadSafe
|
||||
public class MainWindowDialogs {
|
||||
private final AmidstSettings settings;
|
||||
private final MojangApi mojangApi;
|
||||
private final JFrame frame;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public MainWindowDialogs(AmidstSettings settings, MojangApi mojangApi, JFrame frame) {
|
||||
this.settings = settings;
|
||||
this.mojangApi = mojangApi;
|
||||
this.frame = frame;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldPlayerType askForWorldPlayerType() {
|
||||
return askForOptions(
|
||||
"Loading World",
|
||||
"This world contains Multiplayer and Singleplayer data. What do you want to load?\n"
|
||||
+ "If you do not know what to do, just choose Singleplayer.",
|
||||
WorldPlayerType.getSelectable());
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldSeed askForSeed() {
|
||||
return new SeedPrompt(frame).askForSeed();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public File askForSaveGame() {
|
||||
return showOpenDialogAndGetSelectedFileOrNull(createSaveGameFileChooser());
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private JFileChooser createSaveGameFileChooser() {
|
||||
JFileChooser result = new JFileChooser(mojangApi.getSaves());
|
||||
result.setFileFilter(new LevelFileFilter());
|
||||
result.setAcceptAllFileFilterUsed(false);
|
||||
result.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
result.setFileHidingEnabled(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private File showOpenDialogAndGetSelectedFileOrNull(JFileChooser fileChooser) {
|
||||
if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
return fileChooser.getSelectedFile();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public File askForCaptureImageSaveFile(String suggestedFilename) {
|
||||
return showSaveDialogAndGetSelectedFileOrNull(createCaptureImageSaveFileChooser(suggestedFilename));
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private JFileChooser createCaptureImageSaveFileChooser(String suggestedFilename) {
|
||||
JFileChooser result = new JFileChooser();
|
||||
result.setFileFilter(new PNGFileFilter());
|
||||
result.setAcceptAllFileFilterUsed(false);
|
||||
result.setSelectedFile(new File(suggestedFilename));
|
||||
return result;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private File showSaveDialogAndGetSelectedFileOrNull(JFileChooser fileChooser) {
|
||||
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
|
||||
return fileChooser.getSelectedFile();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayInfo(String title, String message) {
|
||||
AmidstMessageBox.displayInfo(frame, title, message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayError(String message) {
|
||||
AmidstMessageBox.displayError(frame, "Error", message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayError(Exception e) {
|
||||
AmidstMessageBox.displayError(frame, "Error", e);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public boolean askToConfirmSaveGameManipulation() {
|
||||
return askToConfirmYesNo(
|
||||
"Save Game Manipulation",
|
||||
"WARNING: You are about to change the contents of the save game directory. There is a chance that it gets corrupted.\n"
|
||||
+ "We try to minimize the risk by creating a backup of the changed file, before it is changed.\n"
|
||||
+ "If the backup fails, we will not write the changes.\n"
|
||||
+ "You can find the backup files in the directory 'amidst/backup', which is placed in the save game directory.\n"
|
||||
+ "Especially, make sure to not have the save game loaded in Minecraft during this process.\n\n"
|
||||
+ "Do you want to proceed?");
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public boolean askToConfirmYesNo(String title, String message) {
|
||||
return AmidstMessageBox.askToConfirmYesNo(frame, title, message);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldType askForWorldType() {
|
||||
String worldTypeSetting = settings.worldType.get();
|
||||
if (worldTypeSetting.equals(WorldType.PROMPT_EACH_TIME)) {
|
||||
return askForOptions("World Type", "Enter world type\n", WorldType.getSelectable());
|
||||
} else {
|
||||
return WorldType.from(worldTypeSetting);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T askForOptions(String title, String message, List<T> choices) {
|
||||
Object[] choicesArray = choices.toArray();
|
||||
return (T) JOptionPane
|
||||
.showInputDialog(frame, message, title, JOptionPane.PLAIN_MESSAGE, null, choicesArray, choicesArray[0]);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public String askForCoordinates() {
|
||||
return askForString("Go To", "Enter coordinates: (Ex. 123,456)");
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public String askForPlayerHeight(long currentHeight) {
|
||||
Object input = JOptionPane.showInputDialog(
|
||||
frame,
|
||||
"Enter new player height:",
|
||||
"Move Player",
|
||||
JOptionPane.QUESTION_MESSAGE,
|
||||
null,
|
||||
null,
|
||||
currentHeight);
|
||||
if (input != null) {
|
||||
return input.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private String askForString(String title, String message) {
|
||||
return JOptionPane.showInputDialog(frame, message, title, JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldExporterConfiguration askForExportConfiguration() {
|
||||
// TODO: implement me!
|
||||
// TODO: display gui to create configuration
|
||||
return new WorldExporterConfiguration();
|
||||
}
|
||||
}
|
|
@ -23,23 +23,23 @@ public class UpdatePrompt {
|
|||
public static UpdatePrompt from(
|
||||
AmidstVersion currentVersion,
|
||||
WorkerExecutor workerExecutor,
|
||||
MainWindow mainWindow,
|
||||
MainWindowDialogs dialogs,
|
||||
boolean silent) {
|
||||
if (mainWindow != null) {
|
||||
if (dialogs != null) {
|
||||
if (silent) {
|
||||
return new UpdatePrompt(
|
||||
currentVersion,
|
||||
workerExecutor,
|
||||
NOOP_CONSUMER,
|
||||
NOOP,
|
||||
message -> mainWindow.askToConfirmYesNo(TITLE, message));
|
||||
message -> dialogs.askToConfirmYesNo(TITLE, message));
|
||||
} else {
|
||||
return new UpdatePrompt(
|
||||
currentVersion,
|
||||
workerExecutor,
|
||||
e -> mainWindow.displayError(e),
|
||||
() -> mainWindow.displayInfo(TITLE, NO_UPDATES_AVAILABLE),
|
||||
message -> mainWindow.askToConfirmYesNo(TITLE, message));
|
||||
e -> dialogs.displayError(e),
|
||||
() -> dialogs.displayInfo(TITLE, NO_UPDATES_AVAILABLE),
|
||||
message -> dialogs.askToConfirmYesNo(TITLE, message));
|
||||
}
|
||||
} else {
|
||||
if (silent) {
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
package amidst.gui.main;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import amidst.dependency.injection.Factory1;
|
||||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.main.menu.AmidstMenu;
|
||||
import amidst.gui.main.viewer.ViewerFacade;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
import amidst.mojangapi.file.MojangApiParsingException;
|
||||
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
|
||||
import amidst.mojangapi.world.World;
|
||||
import amidst.mojangapi.world.WorldSeed;
|
||||
import amidst.mojangapi.world.WorldType;
|
||||
import amidst.mojangapi.world.player.MovablePlayerList;
|
||||
import amidst.mojangapi.world.player.WorldPlayerType;
|
||||
import amidst.threading.ThreadMaster;
|
||||
|
||||
@NotThreadSafe
|
||||
public class WorldSwitcher {
|
||||
private final MojangApi mojangApi;
|
||||
private final Factory1<World, ViewerFacade> viewerFacadeFactory;
|
||||
private final ThreadMaster threadMaster;
|
||||
private final JFrame frame;
|
||||
private final Container contentPane;
|
||||
private final AtomicReference<ViewerFacade> viewerFacadeReference;
|
||||
private final MainWindowDialogs dialogs;
|
||||
private final Supplier<AmidstMenu> menuBarSupplier;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public WorldSwitcher(
|
||||
MojangApi mojangApi,
|
||||
Factory1<World, ViewerFacade> viewerFacadeFactory,
|
||||
ThreadMaster threadMaster,
|
||||
JFrame frame,
|
||||
Container contentPane,
|
||||
AtomicReference<ViewerFacade> viewerFacadeReference,
|
||||
MainWindowDialogs dialogs,
|
||||
Supplier<AmidstMenu> menuBarSupplier) {
|
||||
this.mojangApi = mojangApi;
|
||||
this.viewerFacadeFactory = viewerFacadeFactory;
|
||||
this.threadMaster = threadMaster;
|
||||
this.frame = frame;
|
||||
this.contentPane = contentPane;
|
||||
this.viewerFacadeReference = viewerFacadeReference;
|
||||
this.dialogs = dialogs;
|
||||
this.menuBarSupplier = menuBarSupplier;
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayWorld(WorldSeed worldSeed, WorldType worldType) {
|
||||
try {
|
||||
setWorld(mojangApi.createWorldFromSeed(worldSeed, worldType));
|
||||
} catch (IllegalStateException | MinecraftInterfaceException e) {
|
||||
AmidstLogger.warn(e);
|
||||
dialogs.displayError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void displayWorld(File file) {
|
||||
try {
|
||||
setWorld(mojangApi.createWorldFromSaveGame(file));
|
||||
} catch (IllegalStateException | MinecraftInterfaceException | IOException | MojangApiParsingException e) {
|
||||
AmidstLogger.warn(e);
|
||||
dialogs.displayError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void setWorld(World world) {
|
||||
clearViewerFacade();
|
||||
if (decideWorldPlayerType(world.getMovablePlayerList())) {
|
||||
setViewerFacade(viewerFacadeFactory.create(world));
|
||||
} else {
|
||||
frame.revalidate();
|
||||
frame.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private boolean decideWorldPlayerType(MovablePlayerList movablePlayerList) {
|
||||
if (movablePlayerList.getWorldPlayerType().equals(WorldPlayerType.BOTH)) {
|
||||
WorldPlayerType worldPlayerType = dialogs.askForWorldPlayerType();
|
||||
if (worldPlayerType != null) {
|
||||
movablePlayerList.setWorldPlayerType(worldPlayerType);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void setViewerFacade(ViewerFacade viewerFacade) {
|
||||
contentPane.add(viewerFacade.getComponent(), BorderLayout.CENTER);
|
||||
menuBarSupplier.get().set(viewerFacade);
|
||||
frame.validate();
|
||||
viewerFacade.loadPlayers();
|
||||
threadMaster.setOnRepaintTick(viewerFacade.getOnRepainterTick());
|
||||
threadMaster.setOnFragmentLoadTick(viewerFacade.getOnFragmentLoaderTick());
|
||||
viewerFacadeReference.set(viewerFacade);
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void clearViewerFacade() {
|
||||
threadMaster.clearOnRepaintTick();
|
||||
threadMaster.clearOnFragmentLoadTick();
|
||||
ViewerFacade viewerFacade = viewerFacadeReference.getAndSet(null);
|
||||
if (viewerFacade != null) {
|
||||
contentPane.remove(viewerFacade.getComponent());
|
||||
viewerFacade.dispose();
|
||||
}
|
||||
menuBarSupplier.get().clear();
|
||||
}
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public void clearWorld() {
|
||||
clearViewerFacade();
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import java.util.function.Consumer;
|
|||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.main.MainWindow;
|
||||
import amidst.gui.main.MainWindowDialogs;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.mojangapi.MojangApi;
|
||||
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
|
||||
|
@ -17,7 +17,7 @@ import amidst.threading.worker.ProgressReportingWorker;
|
|||
|
||||
@NotThreadSafe
|
||||
public class SeedSearcher {
|
||||
private final MainWindow mainWindow;
|
||||
private final MainWindowDialogs dialogs;
|
||||
private final MojangApi mojangApi;
|
||||
private final WorkerExecutor workerExecutor;
|
||||
|
||||
|
@ -25,8 +25,8 @@ public class SeedSearcher {
|
|||
private volatile boolean isStopRequested = false;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public SeedSearcher(MainWindow mainWindow, MojangApi mojangApi, WorkerExecutor workerExecutor) {
|
||||
this.mainWindow = mainWindow;
|
||||
public SeedSearcher(MainWindowDialogs dialogs, MojangApi mojangApi, WorkerExecutor workerExecutor) {
|
||||
this.dialogs = dialogs;
|
||||
this.mojangApi = mojangApi.createSilentPlayerlessCopy();
|
||||
this.workerExecutor = workerExecutor;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class SeedSearcher {
|
|||
doSearch(reporter, configuration);
|
||||
} catch (IllegalStateException | MinecraftInterfaceException e) {
|
||||
AmidstLogger.warn(e);
|
||||
mainWindow.displayError(e);
|
||||
dialogs.displayError(e);
|
||||
} finally {
|
||||
this.isSearching = false;
|
||||
this.isStopRequested = false;
|
||||
|
|
|
@ -17,7 +17,8 @@ import amidst.AmidstMetaData;
|
|||
import amidst.documentation.AmidstThread;
|
||||
import amidst.documentation.CalledOnlyBy;
|
||||
import amidst.documentation.NotThreadSafe;
|
||||
import amidst.gui.main.MainWindow;
|
||||
import amidst.gui.main.MainWindowDialogs;
|
||||
import amidst.gui.main.WorldSwitcher;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.mojangapi.file.json.filter.WorldFilterJson_MatchAll;
|
||||
import amidst.mojangapi.world.WorldSeed;
|
||||
|
@ -28,7 +29,8 @@ import net.miginfocom.swing.MigLayout;
|
|||
@NotThreadSafe
|
||||
public class SeedSearcherWindow {
|
||||
private final AmidstMetaData metadata;
|
||||
private final MainWindow mainWindow;
|
||||
private final MainWindowDialogs dialogs;
|
||||
private final WorldSwitcher worldSwitcher;
|
||||
private final SeedSearcher seedSearcher;
|
||||
|
||||
private final JTextArea searchQueryTextArea;
|
||||
|
@ -38,9 +40,14 @@ public class SeedSearcherWindow {
|
|||
private final JFrame frame;
|
||||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
public SeedSearcherWindow(AmidstMetaData metadata, MainWindow mainWindow, SeedSearcher seedSearcher) {
|
||||
public SeedSearcherWindow(
|
||||
AmidstMetaData metadata,
|
||||
MainWindowDialogs dialogs,
|
||||
WorldSwitcher worldSwitcher,
|
||||
SeedSearcher seedSearcher) {
|
||||
this.metadata = metadata;
|
||||
this.mainWindow = mainWindow;
|
||||
this.dialogs = dialogs;
|
||||
this.worldSwitcher = worldSwitcher;
|
||||
this.seedSearcher = seedSearcher;
|
||||
this.searchQueryTextArea = createSearchQueryTextArea();
|
||||
this.worldTypeComboBox = createWorldTypeComboBox();
|
||||
|
@ -113,7 +120,7 @@ public class SeedSearcherWindow {
|
|||
seedSearcher.search(seedSearcherConfiguration, worldSeed -> seedFound(worldSeed, worldType));
|
||||
} else {
|
||||
AmidstLogger.warn("invalid configuration");
|
||||
mainWindow.displayError("invalid configuration");
|
||||
dialogs.displayError("invalid configuration");
|
||||
}
|
||||
}
|
||||
updateGUI();
|
||||
|
@ -137,7 +144,7 @@ public class SeedSearcherWindow {
|
|||
|
||||
@CalledOnlyBy(AmidstThread.EDT)
|
||||
private void seedFound(WorldSeed worldSeed, WorldType worldType) {
|
||||
mainWindow.displayWorld(worldSeed, worldType);
|
||||
worldSwitcher.displayWorld(worldSeed, worldType);
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ public class MojangApi {
|
|||
}
|
||||
|
||||
public String getProfileName() {
|
||||
String profileName = this.profileName;
|
||||
if (profileName != null) {
|
||||
return profileName;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue