Skip to content

Commit 92c7ee6

Browse files
committed
Allow changing the Projects folder in the program settings
1 parent f2afd84 commit 92c7ee6

File tree

6 files changed

+160
-33
lines changed

6 files changed

+160
-33
lines changed

src/sporemodder/HashManager.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ public static HashManager get() {
7474
private NameRegistry extraRegistry;
7575

7676
private final HashMap<String, NameRegistry> registries = new HashMap<String, NameRegistry>();
77-
78-
private String registryError;
7977

8078
@Override
8179
public void initialize(Properties properties) {
@@ -88,23 +86,23 @@ public void initialize(Properties properties) {
8886
try {
8987
fileRegistry.read(PathManager.get().getProgramFile(fileRegistry.getFileName()));
9088
} catch (Exception e) {
91-
registryError = "The file name registry (reg_file.txt) is corrupt or missing.";
89+
UIManager.get().setInitializationError("The file name registry (reg_file.txt) is corrupt or missing.");
9290
}
9391
try {
9492
typeRegistry.read(PathManager.get().getProgramFile(typeRegistry.getFileName()));
9593
} catch (Exception e) {
96-
registryError = "The types registry (reg_type.txt) is corrupt or missing.";
94+
UIManager.get().setInitializationError("The types registry (reg_type.txt) is corrupt or missing.");
9795
}
9896
try {
9997
propRegistry.read(PathManager.get().getProgramFile(propRegistry.getFileName()));
10098
} catch (Exception e) {
101-
registryError = "The property registry (reg_property.txt) is corrupt or missing.";
99+
UIManager.get().setInitializationError("The property registry (reg_property.txt) is corrupt or missing.");
102100
}
103101
try {
104102
simulatorRegistry.read(PathManager.get().getProgramFile(simulatorRegistry.getFileName()));
105103
simulatorRegistry.read(PathManager.get().getProgramFile("reg_simulator_stub.txt"));
106104
} catch (Exception e) {
107-
registryError = "The simulator attributes registry (reg_simulator.txt or reg_simulator_stub.txt) is corrupt or missing.";
105+
UIManager.get().setInitializationError("The simulator attributes registry (reg_simulator.txt or reg_simulator_stub.txt) is corrupt or missing.");
108106
}
109107

110108
CnvUnit.loadNameRegistry();
@@ -115,12 +113,6 @@ public void initialize(Properties properties) {
115113
registries.put(simulatorRegistry.getFileName(), simulatorRegistry);
116114
registries.put(projectRegistry.getFileName(), projectRegistry);
117115
}
118-
119-
public void showInitializationError() {
120-
if (registryError != null) {
121-
UIManager.get().showDialog(Alert.AlertType.ERROR, registryError);
122-
}
123-
}
124116

125117
public void replaceRegistries(NameRegistry file, NameRegistry prop, NameRegistry type) {
126118
fileRegistry = file == null ? originalFileRegistry : file;

src/sporemodder/MainApp.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ private void init(boolean testInit) {
188188
e.printStackTrace();
189189
}
190190
}
191+
192+
pathManager.loadSettings(settings);
191193

192194
// The path managers might be used in other manager initialization methods,
193195
// so we ensure we initialize them first.
@@ -268,7 +270,7 @@ public void start(Stage primaryStage) {
268270
return;
269271
}
270272

271-
hashManager.showInitializationError();
273+
uiManager.showInitializationError();
272274

273275
if (uiManager.isFirstTime()) {
274276
gameManager.showFirstTimeDialog();

src/sporemodder/PathManager.java

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
package sporemodder;
2121

2222
import java.io.File;
23+
import java.io.IOException;
2324
import java.net.URISyntaxException;
25+
import java.nio.file.Files;
2426
import java.util.Objects;
2527
import java.util.Properties;
2628

@@ -33,6 +35,11 @@ public class PathManager extends AbstractManager {
3335
private File programFolder;
3436
/** The folder where SporeModder projects are. */
3537
private File projectsFolder;
38+
private boolean isDefaultProjectsFolder;
39+
/** Path that will get saved as the Projects folder */
40+
public String nextProjectsFolder;
41+
42+
private static final String PROPERTY_projectsPath = "projectsFolderPath";
3643

3744

3845
/**
@@ -73,8 +80,62 @@ public void initialize(Properties properties) {
7380
// run in ide
7481
programFolder = new File(System.getProperty("user.dir"));
7582
}
76-
77-
projectsFolder = new File(programFolder, "Projects");
83+
}
84+
85+
public void loadSettings(Properties properties) {
86+
String path = properties.getProperty(PROPERTY_projectsPath);
87+
if (path != null) {
88+
projectsFolder = new File(path);
89+
if (!Files.isDirectory(projectsFolder.toPath())) {
90+
UIManager.get().setInitializationError("The path to the projects folder does not exist: " + path);
91+
projectsFolder = null;
92+
}
93+
}
94+
if (projectsFolder == null) {
95+
projectsFolder = getDefaultProjectsFolder();
96+
}
97+
// Check if the custom path points to the same folder
98+
try {
99+
isDefaultProjectsFolder = Files.isSameFile(projectsFolder.toPath(), getDefaultProjectsFolder().toPath());
100+
} catch (IOException e) {
101+
e.printStackTrace();
102+
isDefaultProjectsFolder = path == null || path.isBlank();
103+
}
104+
}
105+
106+
@Override public void saveSettings(Properties properties) {
107+
if (nextProjectsFolder != null) {
108+
// non null but blank means reset to default
109+
if (nextProjectsFolder.isBlank()) {
110+
properties.remove(PROPERTY_projectsPath);
111+
} else {
112+
properties.put(PROPERTY_projectsPath, nextProjectsFolder);
113+
}
114+
} else if (!isDefaultProjectsFolder) {
115+
properties.put(PROPERTY_projectsPath, projectsFolder.getAbsolutePath());
116+
}
117+
}
118+
119+
public File getDefaultProjectsFolder() {
120+
return new File(programFolder, "Projects");
121+
}
122+
123+
public String getProjectsFolderStringForSettings() {
124+
if (nextProjectsFolder != null) {
125+
return nextProjectsFolder;
126+
} else if (isDefaultProjectsFolder) {
127+
return "";
128+
} else {
129+
return projectsFolder.getAbsolutePath();
130+
}
131+
}
132+
133+
public boolean isDefaultProjectsFolder() {
134+
return isDefaultProjectsFolder;
135+
}
136+
137+
public void setNextProjectsFolder(String path) {
138+
nextProjectsFolder = path;
78139
}
79140

80141
/** Returns the folder where the program files are. */

src/sporemodder/UIManager.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ public static class UILoadMessage {
121121
private Image programIcon;
122122

123123
private double dpiScaling;
124+
125+
private String initializationError;
124126

125127

126128
/**
@@ -135,6 +137,16 @@ public Stage getPrimaryStage() {
135137
return primaryStage;
136138
}
137139

140+
public void setInitializationError(String initializationError) {
141+
this.initializationError = initializationError;
142+
}
143+
144+
public void showInitializationError() {
145+
if (initializationError != null) {
146+
UIManager.get().showDialog(Alert.AlertType.ERROR, initializationError);
147+
}
148+
}
149+
138150
@Override
139151
public void initialize(Properties properties) {
140152

src/sporemodder/view/dialogs/ProgramSettingsUI.fxml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,40 @@
66
<?import javafx.scene.control.Label?>
77
<?import javafx.scene.control.TextField?>
88
<?import javafx.scene.control.TitledPane?>
9+
<?import javafx.scene.control.Tooltip?>
910
<?import javafx.scene.layout.BorderPane?>
1011
<?import javafx.scene.layout.HBox?>
1112
<?import javafx.scene.layout.VBox?>
1213

13-
<VBox fx:id="mainNode" prefWidth="600.0" styleClass="dialog-content" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sporemodder.view.dialogs.ProgramSettingsUI">
14+
<VBox fx:id="mainNode" prefWidth="600.0" styleClass="dialog-content" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sporemodder.view.dialogs.ProgramSettingsUI">
1415
<children>
16+
<TitledPane fx:id="gameSettingsPanel1" animated="false" collapsible="false" layoutX="10.0" layoutY="10.0" text="General Settings">
17+
<content>
18+
<VBox prefWidth="465.0">
19+
<children>
20+
<Label text="Projects Folder (leave blank to use default folder):" />
21+
<BorderPane>
22+
<right>
23+
<Button fx:id="findProjectsFolderButton" mnemonicParsing="false" text="Browse..." BorderPane.alignment="CENTER" />
24+
</right>
25+
<center>
26+
<TextField fx:id="projectsFolderTextField" prefHeight="18.0" prefWidth="386.0" BorderPane.alignment="CENTER">
27+
<BorderPane.margin>
28+
<Insets right="10.0" />
29+
</BorderPane.margin>
30+
<tooltip>
31+
<Tooltip text="SporeModder FX will store and load its projects in this folder" />
32+
</tooltip>
33+
</TextField>
34+
</center>
35+
<VBox.margin>
36+
<Insets bottom="10.0" />
37+
</VBox.margin>
38+
</BorderPane>
39+
</children>
40+
</VBox>
41+
</content>
42+
</TitledPane>
1543
<TitledPane fx:id="gameSettingsPanel" animated="false" collapsible="false" text="Game Settings">
1644
<content>
1745
<VBox prefWidth="465.0">

src/sporemodder/view/dialogs/ProgramSettingsUI.java

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package sporemodder.view.dialogs;
2020

2121
import java.io.File;
22+
import java.nio.file.Files;
2223
import java.util.Map;
2324

2425
import javafx.fxml.FXML;
@@ -35,12 +36,9 @@
3536
import javafx.scene.control.Tooltip;
3637
import javafx.stage.DirectoryChooser;
3738
import javafx.stage.FileChooser;
38-
import sporemodder.FileManager;
39-
import sporemodder.GameManager;
39+
import sporemodder.*;
4040
import sporemodder.GameManager.GameType;
4141
import sporemodder.file.shaders.FXCompiler;
42-
import sporemodder.MainApp;
43-
import sporemodder.UIManager;
4442
import sporemodder.util.GamePathConfiguration.GamePathType;
4543
import sporemodder.util.SporeGame;
4644
import sporemodder.view.Controller;
@@ -75,6 +73,9 @@ public class ProgramSettingsUI implements Controller {
7573
@FXML private Control gameTypeLabel;
7674
@FXML private Control styleLabel;
7775
@FXML private Control fxcLabel;
76+
77+
@FXML private TextField projectsFolderTextField;
78+
@FXML private Button findProjectsFolderButton;
7879

7980
private Dialog<ButtonType> dialog;
8081

@@ -93,9 +94,7 @@ public Node getMainNode() {
9394
chooser.getExtensionFilters().add(FileManager.FILEFILTER_ALL);
9495
if (!fxcPathField.getText().isEmpty()) chooser.setInitialDirectory(new File(fxcPathField.getText()).getParentFile());
9596

96-
UIManager.get().setOverlay(true);
9797
File result = chooser.showOpenDialog(UIManager.get().getScene().getWindow());
98-
UIManager.get().setOverlay(false);
9998

10099
if (result != null) {
101100
fxcPathField.setText(result.getAbsolutePath());
@@ -116,10 +115,8 @@ public Node getMainNode() {
116115
findSporeButton.setOnAction(event -> {
117116
DirectoryChooser chooser = new DirectoryChooser();
118117
if (!sporeField.getText().isEmpty()) chooser.setInitialDirectory(new File(sporeField.getText()));
119-
120-
UIManager.get().setOverlay(true);
118+
121119
File result = chooser.showDialog(UIManager.get().getScene().getWindow());
122-
UIManager.get().setOverlay(false);
123120

124121
if (result != null) {
125122
result = gameMgr.findInstallationFolder(GameManager.SPORE_SPOREBIN, result);
@@ -136,10 +133,8 @@ public Node getMainNode() {
136133
findGAButton.setOnAction(event -> {
137134
DirectoryChooser chooser = new DirectoryChooser();
138135
if (!gaField.getText().isEmpty()) chooser.setInitialDirectory(new File(gaField.getText()));
139-
140-
UIManager.get().setOverlay(true);
136+
141137
File result = chooser.showDialog(UIManager.get().getScene().getWindow());
142-
UIManager.get().setOverlay(false);
143138

144139
if (result != null) {
145140
result = gameMgr.findInstallationFolder(GameManager.GA_SPOREBIN, result);
@@ -162,10 +157,8 @@ public Node getMainNode() {
162157
}
163158
chooser.getExtensionFilters().add(FileManager.FILEFILTER_ALL);
164159
chooser.getExtensionFilters().add(FileManager.FILEFILTER_EXE);
165-
166-
UIManager.get().setOverlay(true);
160+
167161
File result = chooser.showOpenDialog(UIManager.get().getScene().getWindow());
168-
UIManager.get().setOverlay(false);
169162

170163
if (result != null) {
171164
customPathField.setText(result.getAbsolutePath());
@@ -223,6 +216,25 @@ public Node getMainNode() {
223216
if (FXCompiler.get().getFXCFile() != null) {
224217
fxcPathField.setText(FXCompiler.get().getFXCFile().getAbsolutePath());
225218
}
219+
220+
221+
findProjectsFolderButton.setOnAction(event -> {
222+
DirectoryChooser chooser = new DirectoryChooser();
223+
File initialDirectory;
224+
if (projectsFolderTextField.getText().isBlank()) {
225+
initialDirectory = PathManager.get().getProjectsFolder();
226+
} else {
227+
initialDirectory = new File(projectsFolderTextField.getText());
228+
}
229+
chooser.setInitialDirectory(initialDirectory);
230+
231+
File result = chooser.showDialog(UIManager.get().getScene().getWindow());
232+
233+
if (result != null) {
234+
projectsFolderTextField.setText(result.getAbsolutePath());
235+
}
236+
});
237+
projectsFolderTextField.setText(PathManager.get().getProjectsFolderStringForSettings());
226238
}
227239

228240
private void applyChanges() {
@@ -284,7 +296,27 @@ else if (!gameMgr.hasGalacticAdventures() || !path.equals(gameMgr.getGalacticAdv
284296
} else {
285297
FXCompiler.get().setFXCFile(new File(path));
286298
}
287-
299+
300+
301+
String newProjectsFolder = null;
302+
if (!projectsFolderTextField.getText().isBlank()) {
303+
File projectsFolder = new File(projectsFolderTextField.getText());
304+
if (!Files.isDirectory(projectsFolder.toPath())) {
305+
UIManager.get().showDialog(AlertType.ERROR, "The Projects folder does not exist: " + projectsFolderTextField.getText());
306+
} else {
307+
newProjectsFolder = projectsFolderTextField.getText();
308+
}
309+
} else {
310+
// Reset projects folder if it has been changed to default
311+
if (!PathManager.get().isDefaultProjectsFolder()) {
312+
newProjectsFolder = "";
313+
}
314+
}
315+
316+
if (newProjectsFolder != null) {
317+
UIManager.get().showDialog("The Projects folder has been changed. The changes won't apply until you restart SporeModder FX.");
318+
PathManager.get().setNextProjectsFolder(newProjectsFolder);
319+
}
288320

289321
MainApp.get().saveSettings();
290322
}
@@ -322,7 +354,7 @@ private void showInternal() {
322354

323355
public static void show() {
324356
ProgramSettingsUI node = UIManager.get().loadUI("dialogs/ProgramSettingsUI");
325-
node.dialog = new Dialog<ButtonType>();
357+
node.dialog = new Dialog<>();
326358
node.showInternal();
327359
}
328360
}

0 commit comments

Comments
 (0)