mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Merge remote-tracking branch 'origin/121-settings-menu' into UI
# Conflicts: # app/src/main/java/org/toop/app/menu/OptionsMenu.java # app/src/main/resources/assets/localization/localization_de.properties # app/src/main/resources/assets/localization/localization_en_US.properties # app/src/main/resources/assets/localization/localization_es.properties # app/src/main/resources/assets/localization/localization_fr.properties # app/src/main/resources/assets/localization/localization_it.properties # app/src/main/resources/assets/localization/localization_nl.properties # app/src/main/resources/assets/localization/localization_zh.properties
This commit is contained in:
@@ -11,7 +11,7 @@ import java.util.Locale;
|
||||
|
||||
public final class CreditsMenu extends Menu {
|
||||
private Locale currentLocale = AppContext.getLocale();
|
||||
private LocalizationAsset loc = ResourceManager.get("localization.properties");
|
||||
private LocalizationAsset loc = ResourceManager.get("localization_en_us.properties");
|
||||
public CreditsMenu() {
|
||||
try {
|
||||
new EventFlow()
|
||||
|
||||
@@ -14,10 +14,14 @@ import org.toop.framework.eventbus.EventFlow;
|
||||
import org.toop.local.AppContext;
|
||||
import org.toop.local.LocalizationEvents;
|
||||
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class OptionsMenu extends Menu {
|
||||
private Locale currentLocale = AppContext.getLocale();
|
||||
private LocalizationAsset loc = ResourceManager.get("localization");
|
||||
|
||||
private final LocalizationAsset loc = ResourceManager.get("localization.properties");
|
||||
private Text chooseLang;
|
||||
private Button english,dutch,german,french,italian,spanish,chinese;
|
||||
@@ -65,5 +69,65 @@ public final class OptionsMenu extends Menu {
|
||||
chinese.setText(loc.getString("languageChinese",currentLocale));
|
||||
});
|
||||
|
||||
}
|
||||
final Region background = createBackground();
|
||||
|
||||
GraphicsDevice currentScreen = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
|
||||
|
||||
LocalizationAsset locFiles = ResourceManager.get(LocalizationAsset.class, "localization");
|
||||
final Label selectLanguageLabel = new Label(loc.getString("optionsMenuLabelSelectLanguage", currentLocale));
|
||||
final ChoiceBox<Locale> selectLanguage = new ChoiceBox<>();
|
||||
selectLanguage.setValue(currentLocale);
|
||||
for (Locale locFile : locFiles.getAvailableLocales()) {
|
||||
selectLanguage.getItems().add(locFile);
|
||||
}
|
||||
|
||||
selectLanguage.setOnAction((event) -> {
|
||||
Locale selectedLocale = selectLanguage.getSelectionModel().getSelectedItem();
|
||||
AppContext.setLocale(selectedLocale);
|
||||
App.pop();
|
||||
App.push(new OptionsMenu());
|
||||
});
|
||||
|
||||
// GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
// GraphicsDevice[] devices = ge.getScreenDevices();
|
||||
// final ChoiceBox<GraphicsDevice> selectScreen = new ChoiceBox<>();
|
||||
// for (GraphicsDevice screen : devices) {
|
||||
// selectScreen.getItems().add(screen);
|
||||
// }
|
||||
//
|
||||
// selectScreen.setOnAction((event) -> {
|
||||
// int selectedIndex = selectScreen.getSelectionModel().getSelectedIndex();
|
||||
// Object selectedItem = selectScreen.getSelectionModel().getSelectedItem();
|
||||
//
|
||||
// System.out.println("Selection made: [" + selectedIndex + "] " + selectedItem);
|
||||
// System.out.println(" ChoiceBox.getValue(): " + selectScreen.getValue());
|
||||
// });
|
||||
//
|
||||
// final ChoiceBox<DisplayMode> selectWindowSize = new ChoiceBox<>();
|
||||
// for (DisplayMode displayMode : currentScreen.getDisplayModes()) {
|
||||
// selectWindowSize.getItems().add(displayMode);
|
||||
// }
|
||||
//
|
||||
//// if (currentScreen.isFullScreenSupported()) {}
|
||||
// final CheckBox setFullscreen = new CheckBox("Fullscreen");
|
||||
|
||||
final VBox optionsBox = new VBox(10, selectLanguageLabel, selectLanguage);
|
||||
optionsBox.setAlignment(Pos.CENTER);
|
||||
optionsBox.setPickOnBounds(false);
|
||||
optionsBox.setTranslateY(50);
|
||||
optionsBox.setTranslateX(25);
|
||||
|
||||
final Button credits = createButton("Credits", () -> { App.push(new CreditsMenu()); });
|
||||
final Button options = createButton("Exit Options", () -> { App.push(new MainMenu()); });
|
||||
final Button quit = createButton("Quit", () -> { App.quitPopup(); });
|
||||
|
||||
final VBox controlBox = new VBox(10, credits, options, quit);
|
||||
controlBox.setAlignment(Pos.BOTTOM_LEFT);
|
||||
controlBox.setPickOnBounds(false);
|
||||
controlBox.setTranslateY(-50);
|
||||
controlBox.setTranslateX(25);
|
||||
|
||||
pane = new StackPane(background, optionsBox, controlBox);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,10 @@ import java.util.Locale;
|
||||
public class AppContext {
|
||||
private static Locale currentLocale = Locale.getDefault();
|
||||
|
||||
public static void setLocale(Locale locale) {
|
||||
currentLocale = locale;
|
||||
}
|
||||
|
||||
public static void setCurrentLocale(Locale locale) {
|
||||
currentLocale = locale;
|
||||
new EventFlow().addPostEvent(new LocalizationEvents.LanguageHasChanged(locale.getLanguage())).asyncPostEvent();
|
||||
|
||||
@@ -34,3 +34,7 @@ gameSelectMenuEnterIP=Gib hier deine IP-Adresse ein:
|
||||
# Game Menu
|
||||
gameMenuHint=Tipp
|
||||
gameMenuBack=Zur\u00FCck
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Sprache:
|
||||
@@ -2,8 +2,8 @@
|
||||
windowTitle=ISY Games Selector
|
||||
|
||||
# Main Menu buttons
|
||||
mainMenuSelectTicTacToe=Tic Tac Toe
|
||||
mainMenuSelectReversi=Reversi
|
||||
mainMenuSelectTicTacToe=Tic Tac Toe\u5426
|
||||
mainMenuSelectReversi=Reversi\u5426
|
||||
mainMenuSelectSudoku=Sudoku
|
||||
mainMenuSelectBattleship=Battleship
|
||||
mainMenuSelectOther=Other
|
||||
@@ -33,4 +33,7 @@ gameSelectMenuEnterIP=Enter your IP address here:
|
||||
|
||||
# Game Menu
|
||||
gameMenuHint=Hint
|
||||
gameMenuBack=Back
|
||||
gameMenuBack=Back
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Language:
|
||||
@@ -34,3 +34,7 @@ gameSelectMenuEnterIP=Introduce aqu\u00ED tu direcci\u00F3n IP:
|
||||
# Game Menu
|
||||
gameMenuHint=Pista
|
||||
gameMenuBack=Atr\u00E1s
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Idioma:
|
||||
@@ -34,3 +34,7 @@ gameSelectMenuEnterIP=Entrez votre adresse IP ici :
|
||||
# Game Menu
|
||||
gameMenuHint=Indice
|
||||
gameMenuBack=Retour
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Langue:
|
||||
@@ -35,3 +35,7 @@ gameSelectMenuEnterIP=Inserisci qui il tuo indirizzo IP:
|
||||
gameMenuHint=Suggerimento
|
||||
gameMenuBack=Indietro
|
||||
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Lingua:
|
||||
@@ -34,3 +34,7 @@ gameSelectMenuEnterIP=Voer hier je IP-adres in:
|
||||
# Game Menu
|
||||
gameMenuHint=Hint
|
||||
gameMenuBack=Terug
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=Taal:
|
||||
@@ -46,3 +46,7 @@ gameSelectMenuEnterIP=\u5728\u6B64\u8F93\u5165\u4F60\u7684IP\u5730\u5740\uFF1A
|
||||
# Game Menu
|
||||
gameMenuHint=\u63D0\u793A
|
||||
gameMenuBack=\u8FD4\u56DE
|
||||
|
||||
|
||||
# Options menu
|
||||
optionsMenuLabelSelectLanguage=\u8BED\u8A00:
|
||||
@@ -158,6 +158,7 @@ public class ResourceLoader {
|
||||
Map<String, BundledResource> bundledResources = new HashMap<>();
|
||||
|
||||
for (File file : files) {
|
||||
boolean skipAdd = false;
|
||||
BaseResource resource = resourceMapper(file, BaseResource.class);
|
||||
switch (resource) {
|
||||
case null -> {
|
||||
@@ -165,13 +166,11 @@ public class ResourceLoader {
|
||||
}
|
||||
case BundledResource br -> {
|
||||
String key = resource.getClass().getName() + ":" + br.getBaseName();
|
||||
if (bundledResources.containsKey(key)) {
|
||||
bundledResources.get(key).loadFile(file);
|
||||
resource = (BaseResource) bundledResources.get(key);
|
||||
} else {
|
||||
br.loadFile(file);
|
||||
bundledResources.put(key, br);
|
||||
}
|
||||
if (!bundledResources.containsKey(key)) {bundledResources.put(key, br);}
|
||||
bundledResources.get(key).loadFile(file);
|
||||
resource = (BaseResource) bundledResources.get(key);
|
||||
assets.add(new ResourceMeta<>(br.getBaseName(), resource));
|
||||
skipAdd = true;
|
||||
}
|
||||
case PreloadResource pr -> pr.load();
|
||||
default -> {
|
||||
@@ -181,7 +180,7 @@ public class ResourceLoader {
|
||||
BaseResource finalResource = resource;
|
||||
boolean alreadyAdded = assets.stream()
|
||||
.anyMatch(a -> a.getResource() == finalResource);
|
||||
if (!alreadyAdded) {
|
||||
if (!alreadyAdded && !skipAdd) {
|
||||
assets.add(new ResourceMeta<>(file.getName(), resource));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,33 +8,90 @@ import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents a localization resource asset that loads and manages property files
|
||||
* containing key-value pairs for different locales.
|
||||
* <p>
|
||||
* This class implements {@link LoadableResource} to support loading/unloading
|
||||
* and {@link BundledResource} to represent resources that can contain multiple
|
||||
* localized bundles.
|
||||
* </p>
|
||||
* <p>
|
||||
* Files handled by this class must have the {@code .properties} extension,
|
||||
* optionally with a locale suffix, e.g., {@code messages_en_US.properties}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Example usage:
|
||||
* <pre>{@code
|
||||
* LocalizationAsset asset = new LocalizationAsset(new File("messages_en_US.properties"));
|
||||
* asset.load();
|
||||
* String greeting = asset.getString("hello", Locale.US);
|
||||
* }</pre>
|
||||
* </p>
|
||||
*/
|
||||
@FileExtension({"properties"})
|
||||
public class LocalizationAsset extends BaseResource implements LoadableResource, BundledResource {
|
||||
private final Map<Locale, ResourceBundle> bundles = new HashMap<>();
|
||||
private boolean isLoaded = false;
|
||||
private final Locale fallback = Locale.forLanguageTag("");
|
||||
|
||||
/** Map of loaded resource bundles, keyed by locale. */
|
||||
private final Map<Locale, ResourceBundle> bundles = new HashMap<>();
|
||||
|
||||
/** Flag indicating whether this asset has been loaded. */
|
||||
private boolean isLoaded = false;
|
||||
|
||||
/** Basename of the given asset */
|
||||
private final String baseName = "localization";
|
||||
|
||||
/** Fallback locale used when no matching locale is found. */
|
||||
private final Locale fallback = Locale.forLanguageTag("en_US");
|
||||
|
||||
/**
|
||||
* Constructs a new LocalizationAsset for the specified file.
|
||||
*
|
||||
* @param file the property file to load
|
||||
*/
|
||||
public LocalizationAsset(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the resource file into memory and prepares localized bundles.
|
||||
*/
|
||||
@Override
|
||||
public void load() {
|
||||
loadFile(getFile());
|
||||
isLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads all loaded resource bundles, freeing memory.
|
||||
*/
|
||||
@Override
|
||||
public void unload() {
|
||||
bundles.clear();
|
||||
isLoaded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this asset has been loaded.
|
||||
*
|
||||
* @return {@code true} if the asset is loaded, {@code false} otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return isLoaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a localized string for the given key and locale.
|
||||
* If an exact match for the locale is not found, a fallback
|
||||
* matching the language or the default locale will be used.
|
||||
*
|
||||
* @param key the key of the string
|
||||
* @param locale the desired locale
|
||||
* @return the localized string
|
||||
* @throws MissingResourceException if no resource bundle is available for the locale
|
||||
*/
|
||||
public String getString(String key, Locale locale) {
|
||||
Locale target = findBestLocale(locale);
|
||||
ResourceBundle bundle = bundles.get(target);
|
||||
@@ -43,6 +100,13 @@ public class LocalizationAsset extends BaseResource implements LoadableResource,
|
||||
return bundle.getString(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the best matching locale among loaded bundles.
|
||||
* Prefers an exact match, then language-only match, then fallback.
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @return the best matching locale
|
||||
*/
|
||||
private Locale findBestLocale(Locale locale) {
|
||||
if (bundles.containsKey(locale)) return locale;
|
||||
for (Locale l : bundles.keySet()) {
|
||||
@@ -51,13 +115,24 @@ public class LocalizationAsset extends BaseResource implements LoadableResource,
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable set of all locales for which bundles are loaded.
|
||||
*
|
||||
* @return available locales
|
||||
*/
|
||||
public Set<Locale> getAvailableLocales() {
|
||||
return Collections.unmodifiableSet(bundles.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a specific property file as a resource bundle.
|
||||
* The locale is extracted from the file name if present.
|
||||
*
|
||||
* @param file the property file to load
|
||||
* @throws RuntimeException if the file cannot be read
|
||||
*/
|
||||
@Override
|
||||
public void loadFile(File file) {
|
||||
String baseName = getBaseName(file.getName());
|
||||
try (InputStreamReader reader =
|
||||
new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
|
||||
Locale locale = extractLocale(file.getName(), baseName);
|
||||
@@ -68,20 +143,40 @@ public class LocalizationAsset extends BaseResource implements LoadableResource,
|
||||
isLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base name of the underlying file (without locale or extension).
|
||||
*
|
||||
* @return the base name
|
||||
*/
|
||||
@Override
|
||||
public String getBaseName() {
|
||||
return getBaseName(getFile().getName());
|
||||
return this.baseName;
|
||||
}
|
||||
|
||||
private String getBaseName(String fileName) {
|
||||
int underscoreIndex = fileName.indexOf('_');
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
if (underscoreIndex > 0) {
|
||||
return fileName.substring(0, underscoreIndex);
|
||||
}
|
||||
return fileName.substring(0, dotIndex);
|
||||
}
|
||||
// /**
|
||||
// * Extracts the base name from a file name.
|
||||
// *
|
||||
// * @param fileName the file name
|
||||
// * @return base name without locale or extension
|
||||
// */
|
||||
// private String getBaseName(String fileName) {
|
||||
// int dotIndex = fileName.lastIndexOf('.');
|
||||
// String nameWithoutExtension = (dotIndex > 0) ? fileName.substring(0, dotIndex) : fileName;
|
||||
//
|
||||
// int underscoreIndex = nameWithoutExtension.indexOf('_');
|
||||
// if (underscoreIndex > 0) {
|
||||
// return nameWithoutExtension.substring(0, underscoreIndex);
|
||||
// }
|
||||
// return nameWithoutExtension;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Extracts a locale from a file name based on the pattern "base_LOCALE.properties".
|
||||
*
|
||||
* @param fileName the file name
|
||||
* @param baseName the base name
|
||||
* @return extracted locale, or fallback if none found
|
||||
*/
|
||||
private Locale extractLocale(String fileName, String baseName) {
|
||||
int underscoreIndex = fileName.indexOf('_');
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
|
||||
@@ -66,4 +66,9 @@ public interface BundledResource {
|
||||
* @return the base name used to identify this bundled resource
|
||||
*/
|
||||
String getBaseName();
|
||||
|
||||
// /**
|
||||
// Returns the name
|
||||
// */
|
||||
// String getDefaultName();
|
||||
}
|
||||
Reference in New Issue
Block a user