mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-11 14:22:12 +00:00
Added: Configuration in TOML format
This commit is contained in:
@@ -44,6 +44,7 @@ import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -61,11 +62,13 @@ import javax.swing.JOptionPane;
|
||||
*/
|
||||
public final class Configuration {
|
||||
|
||||
private static final String CONFIG_NAME = "config.bin";
|
||||
private static final ConfigurationStorage legacyStorage = new LegacyConfigurationStorage();
|
||||
|
||||
private static final File unspecifiedFile = new File("unspecified");
|
||||
private static final ConfigurationStorage storage = new TomlConfigurationStorage();
|
||||
|
||||
private static File directory = unspecifiedFile;
|
||||
private static final File UNSPECIFIED_FILE = new File("unspecified");
|
||||
|
||||
private static File directory = UNSPECIFIED_FILE;
|
||||
|
||||
/**
|
||||
* Log level
|
||||
@@ -168,6 +171,7 @@ public final class Configuration {
|
||||
public static ConfigurationItem<Boolean> openFolderAfterFlaExport = null;
|
||||
|
||||
@ConfigurationCategory("export")
|
||||
@ConfigurationDefaultString("")
|
||||
public static ConfigurationItem<String> overrideTextExportFileName = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@@ -1144,10 +1148,32 @@ public final class Configuration {
|
||||
@ConfigurationCategory("display")
|
||||
public static ConfigurationItem<Boolean> snapAlignCenterAlignmentVertical = null;
|
||||
|
||||
|
||||
private static Map<String, String> configurationDescriptions = new LinkedHashMap<>();
|
||||
private static Map<String, String> configurationTitles = new LinkedHashMap<>();
|
||||
|
||||
private enum OSId {
|
||||
WINDOWS, OSX, UNIX
|
||||
}
|
||||
|
||||
|
||||
public static void setConfigurationDescriptions(Map<String, String> configurationDescriptions) {
|
||||
Configuration.configurationDescriptions = configurationDescriptions;
|
||||
}
|
||||
|
||||
public static void setConfigurationTitles(Map<String, String> configurationTitles) {
|
||||
Configuration.configurationTitles = configurationTitles;
|
||||
}
|
||||
|
||||
|
||||
public static String getConfigurationTitle(String confirationName) {
|
||||
return configurationTitles.get(confirationName);
|
||||
}
|
||||
|
||||
public static String getConfigurationDescription(String confirationName) {
|
||||
return configurationDescriptions.get(confirationName);
|
||||
}
|
||||
|
||||
private static OSId getOSId() {
|
||||
String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
if ((OS.indexOf("mac") >= 0) || (OS.indexOf("darwin") >= 0)) {
|
||||
@@ -1165,7 +1191,7 @@ public final class Configuration {
|
||||
* @return FFDec home directory
|
||||
*/
|
||||
public static String getFFDecHome() {
|
||||
if (directory == unspecifiedFile) {
|
||||
if (directory == UNSPECIFIED_FILE) {
|
||||
directory = null;
|
||||
String userHome = null;
|
||||
try {
|
||||
@@ -1379,52 +1405,24 @@ public final class Configuration {
|
||||
}
|
||||
|
||||
private static String getConfigFile() throws IOException {
|
||||
return getFFDecHome() + CONFIG_NAME;
|
||||
return getFFDecHome() + storage.getConfigName();
|
||||
}
|
||||
|
||||
private static HashMap<String, Object> loadFromFile(String file) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
HashMap<String, Object> cfg = (HashMap<String, Object>) ois.readObject();
|
||||
return cfg;
|
||||
} catch (ClassNotFoundException | IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return new HashMap<>();
|
||||
|
||||
private static String getLegacyConfigFile() throws IOException {
|
||||
return getFFDecHome() + legacyStorage.getConfigName();
|
||||
}
|
||||
|
||||
private static void saveToFile(String file) {
|
||||
HashMap<String, Object> config = new HashMap<>();
|
||||
for (Entry<String, Field> entry : getConfigurationFields(false, true).entrySet()) {
|
||||
try {
|
||||
String name = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
ConfigurationItem item = (ConfigurationItem) field.get(null);
|
||||
if (item.hasValue) {
|
||||
config.put(name, item.get());
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
|
||||
oos.writeObject(config);
|
||||
} catch (IOException ex) {
|
||||
//TODO: move this to GUI
|
||||
ex.printStackTrace();
|
||||
JOptionPane.showMessageDialog(null, "Cannot save configuration.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
Logger.getLogger(Configuration.class.getName()).severe("Configuration directory is read only.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save configuration to file
|
||||
*/
|
||||
public static void saveConfig() {
|
||||
try {
|
||||
saveToFile(getConfigFile());
|
||||
storage.saveToFile(getConfigFile());
|
||||
} catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
legacyStorage.saveToFile(getLegacyConfigFile());
|
||||
} catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
@@ -1449,7 +1447,14 @@ public final class Configuration {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void setConfigurationFields() {
|
||||
try {
|
||||
HashMap<String, Object> config = loadFromFile(getConfigFile());
|
||||
Map<String, Object> config;
|
||||
|
||||
if (new File(getConfigFile()).exists()) {
|
||||
config = storage.loadFromFile(getConfigFile());
|
||||
} else {
|
||||
config = legacyStorage.loadFromFile(getLegacyConfigFile());
|
||||
}
|
||||
|
||||
for (Entry<String, Field> entry : getConfigurationFields(false, true).entrySet()) {
|
||||
String name = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
@@ -1544,6 +1549,18 @@ public final class Configuration {
|
||||
defaultValue = Color.black;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultValue == null) {
|
||||
Class<?> type = ConfigurationItem.getConfigurationFieldType(field);
|
||||
if (type.isEnum()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) type;
|
||||
defaultValue = enumClass.getEnumConstants()[0];
|
||||
}
|
||||
if (type == String.class) {
|
||||
defaultValue = "";
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@@ -1562,7 +1579,7 @@ public final class Configuration {
|
||||
*/
|
||||
public static Map<String, Field> getConfigurationFields(boolean lowerCaseNames, boolean alsoRemoved) {
|
||||
Field[] fields = Configuration.class.getDeclaredFields();
|
||||
Map<String, Field> result = new HashMap<>();
|
||||
Map<String, Field> result = new LinkedHashMap<>();
|
||||
for (Field field : fields) {
|
||||
if (!alsoRemoved) {
|
||||
ConfigurationRemoved removedAnnotation = field.getAnnotation(ConfigurationRemoved.class);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.configuration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface ConfigurationStorage {
|
||||
public String getConfigName();
|
||||
|
||||
public Map<String, Object> loadFromFile(String file);
|
||||
|
||||
public void saveToFile(String file);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.configuration;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class LegacyConfigurationStorage implements ConfigurationStorage {
|
||||
|
||||
@Override
|
||||
public String getConfigName() {
|
||||
return "config.bin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> loadFromFile(String file) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> cfg = (HashMap<String, Object>) ois.readObject();
|
||||
return cfg;
|
||||
} catch (ClassNotFoundException | IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public void saveToFile(String file) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
for (Map.Entry<String, Field> entry : Configuration.getConfigurationFields(false, true).entrySet()) {
|
||||
try {
|
||||
String name = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
ConfigurationItem item = (ConfigurationItem) field.get(null);
|
||||
if (item.hasValue) {
|
||||
config.put(name, item.get());
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
|
||||
oos.writeObject(config);
|
||||
} catch (IOException ex) {
|
||||
//TODO: move this to GUI
|
||||
ex.printStackTrace();
|
||||
JOptionPane.showMessageDialog(null, "Cannot save configuration.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
Logger.getLogger(Configuration.class.getName()).severe("Configuration directory is read only.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,10 @@ public class SwfSpecificCustomConfiguration implements Serializable {
|
||||
|
||||
public static final String LIST_SEPARATOR = "{*sep*}";
|
||||
|
||||
public Map<String, String> getAllCustomData() {
|
||||
return customData;
|
||||
}
|
||||
|
||||
public List<String> getCustomDataAsList(String key) {
|
||||
String data = getCustomData(key, "");
|
||||
String[] parts = (data + LIST_SEPARATOR).split(Pattern.quote(LIST_SEPARATOR));
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.configuration;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppResources;
|
||||
import com.jpexs.decompiler.flash.ApplicationInfo;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.tomlj.Toml;
|
||||
import org.tomlj.TomlParseError;
|
||||
import org.tomlj.TomlParseResult;
|
||||
import org.tomlj.TomlTable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TomlConfigurationStorage implements ConfigurationStorage {
|
||||
|
||||
public String getConfigName() {
|
||||
return "config.toml";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> loadFromFile(String file) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
TomlParseResult tomlResult;
|
||||
try {
|
||||
tomlResult = Toml.parse(Paths.get(file));
|
||||
} catch (IOException ex) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!tomlResult.errors().isEmpty()) {
|
||||
System.err.println("Error parsing configuration file:");
|
||||
for (TomlParseError error : tomlResult.errors()) {
|
||||
System.err.println("- " + error);
|
||||
}
|
||||
}
|
||||
|
||||
TomlTable configurationTable = tomlResult.getTable("configuration");
|
||||
if (configurationTable == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Field> entry : Configuration.getConfigurationFields(false, true).entrySet()) {
|
||||
try {
|
||||
String name = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
ConfigurationItem item = (ConfigurationItem) field.get(null);
|
||||
ConfigurationName nameAnnotation = field.getAnnotation(ConfigurationName.class);
|
||||
if (nameAnnotation != null) {
|
||||
name = nameAnnotation.value();
|
||||
}
|
||||
String key = name;
|
||||
if (key.contains(".")) {
|
||||
key = "\"" + key + "\"";
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
|
||||
switch (name) {
|
||||
case "fontPairingMap":
|
||||
TomlTable fontPairingTable = configurationTable.getTable(key);
|
||||
if (fontPairingTable != null) {
|
||||
Map<String, String> fontPairingMap = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> fontEntry : fontPairingTable.entrySet()) {
|
||||
if (fontEntry.getValue() instanceof String) {
|
||||
fontPairingMap.put(fontEntry.getKey(), (String) fontEntry.getValue());
|
||||
}
|
||||
}
|
||||
value = fontPairingMap;
|
||||
}
|
||||
break;
|
||||
case "swfSpecificConfigs":
|
||||
TomlTable swfSpecificConfigsTable = configurationTable.getTable(key);
|
||||
if (swfSpecificConfigsTable != null) {
|
||||
Map<String, SwfSpecificConfiguration> swfSpecificConfigs = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> swfEntry : swfSpecificConfigsTable.entrySet()) {
|
||||
String swfKey = swfEntry.getKey();
|
||||
if (swfEntry.getValue() instanceof TomlTable) {
|
||||
SwfSpecificConfiguration swfSpecificConfig = new SwfSpecificConfiguration();
|
||||
TomlTable configsTable = (TomlTable) swfEntry.getValue();
|
||||
TomlTable swfSpecificFontPairingTable = configsTable.getTable("fontPairingMap");
|
||||
Map<String, String> swfSpecificFontPairingMap = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> fontEntry : swfSpecificFontPairingTable.entrySet()) {
|
||||
if (fontEntry.getValue() instanceof String) {
|
||||
swfSpecificFontPairingMap.put(fontEntry.getKey(), (String) fontEntry.getValue());
|
||||
}
|
||||
}
|
||||
swfSpecificConfig.fontPairingMap = swfSpecificFontPairingMap;
|
||||
swfSpecificConfig.lastSelectedPath = configsTable.getString("lastSelectedPath");
|
||||
swfSpecificConfigs.put(swfKey, swfSpecificConfig);
|
||||
}
|
||||
}
|
||||
value = swfSpecificConfigs;
|
||||
}
|
||||
break;
|
||||
case "swfSpecificCustomConfigs":
|
||||
TomlTable swfSpecificCustomConfigsTable = configurationTable.getTable(key);
|
||||
if (swfSpecificCustomConfigsTable != null) {
|
||||
Map<String, SwfSpecificCustomConfiguration> swfSpecificCustomConfigs = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> swfEntry : swfSpecificCustomConfigsTable.entrySet()) {
|
||||
String swfKey = swfEntry.getKey();
|
||||
if (swfEntry.getValue() instanceof TomlTable) {
|
||||
SwfSpecificCustomConfiguration swfSpecificCustomConfig = new SwfSpecificCustomConfiguration();
|
||||
Map<String, String> swfSpecificCustomConfigMap = swfSpecificCustomConfig.getAllCustomData();
|
||||
TomlTable configsTable = (TomlTable) swfEntry.getValue();
|
||||
|
||||
for (Map.Entry<String, Object> customDataEntry : configsTable.entrySet()) {
|
||||
if (customDataEntry.getValue() instanceof String) {
|
||||
swfSpecificCustomConfigMap.put(customDataEntry.getKey(), (String) customDataEntry.getValue());
|
||||
}
|
||||
}
|
||||
swfSpecificCustomConfigs.put(swfKey, swfSpecificCustomConfig);
|
||||
}
|
||||
}
|
||||
value = swfSpecificCustomConfigs;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
|
||||
if (type instanceof Class) {
|
||||
switch (((Class) type).getSimpleName()) {
|
||||
case "Boolean":
|
||||
value = configurationTable.getBoolean(key);
|
||||
break;
|
||||
case "Calendar":
|
||||
OffsetDateTime offsetDateTime = configurationTable.getOffsetDateTime(key);
|
||||
if (offsetDateTime != null) {
|
||||
Date date = Date.from(offsetDateTime.toInstant());
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
value = calendar;
|
||||
}
|
||||
break;
|
||||
case "Color":
|
||||
String colorString = configurationTable.getString(key);
|
||||
if (colorString != null) {
|
||||
Pattern colorPattern = Pattern.compile("#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$");
|
||||
Matcher m = colorPattern.matcher(colorString);
|
||||
if (m.matches()) {
|
||||
value = new Color(Integer.parseInt(m.group(1), 16), Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Double":
|
||||
value = configurationTable.getDouble(key);
|
||||
break;
|
||||
case "Integer":
|
||||
Long longValue = configurationTable.getLong(key);
|
||||
if (longValue != null) {
|
||||
value = (Integer) (int) (long) longValue;
|
||||
}
|
||||
break;
|
||||
case "String":
|
||||
value = configurationTable.getString(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != null) {
|
||||
result.put(name, value);
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static List<String> wordWrap(String text, int maxLineLength) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
String[] words = text.split(" ");
|
||||
StringBuilder line = new StringBuilder();
|
||||
|
||||
for (String word : words) {
|
||||
if (line.length() + word.length() + 1 > maxLineLength) {
|
||||
lines.add(line.toString().trim());
|
||||
line = new StringBuilder();
|
||||
}
|
||||
line.append(word).append(" ");
|
||||
}
|
||||
|
||||
if (!line.toString().isEmpty()) {
|
||||
lines.add(line.toString().trim());
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static String stringOfChar(char c, int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String comment(String comment) {
|
||||
return "# " + String.join(System.lineSeparator() + "# ", wordWrap(comment, 80 - 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToFile(String file) {
|
||||
boolean showComments = false;
|
||||
boolean modifiedOnly = true;
|
||||
if (new File(file).exists()) {
|
||||
TomlParseResult tomlResult;
|
||||
try {
|
||||
tomlResult = Toml.parse(Paths.get(file));
|
||||
TomlTable metaTable = tomlResult.getTable("meta");
|
||||
if (metaTable != null) {
|
||||
showComments = metaTable.getBoolean("showComments") == Boolean.TRUE;
|
||||
modifiedOnly = metaTable.getBoolean("modifiedOnly") == Boolean.TRUE;
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
try (
|
||||
Writer w = new FileWriter(file); PrintWriter pw = new PrintWriter(w)) {
|
||||
String header = AppResources.translate("configurationFile").replace("%app%", ApplicationInfo.APPLICATION_NAME);
|
||||
String splitter = stringOfChar('-', header.length());
|
||||
pw.println("# " + splitter);
|
||||
pw.println("# " + header);
|
||||
pw.println("# " + splitter);
|
||||
pw.println();
|
||||
pw.println(comment(AppResources.translate("configurationFile.comment")));
|
||||
pw.println();
|
||||
pw.println(comment(AppResources.translate("configurationFile.modify")));
|
||||
pw.println();
|
||||
pw.println(comment(AppResources.translate("configurationFile.meta")));
|
||||
pw.println("[meta]");
|
||||
pw.println();
|
||||
Calendar generatedCalendarValue = Calendar.getInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssXXX");
|
||||
sdf.setTimeZone(generatedCalendarValue.getTimeZone());
|
||||
String generatedValue = sdf.format(generatedCalendarValue.getTime());
|
||||
pw.println(comment(AppResources.translate("configurationFile.meta.saveDate")));
|
||||
pw.println("saveDate = " + generatedValue);
|
||||
pw.println();
|
||||
pw.println(comment(AppResources.translate("configurationFile.meta.appVersion")));
|
||||
pw.println("appVersion = \"" + ApplicationInfo.version + "\"");
|
||||
pw.println();
|
||||
|
||||
pw.println(comment(AppResources.translate("configurationFile.meta.showComments")));
|
||||
pw.println("showComments = " + (showComments ? "true" : "false") + "");
|
||||
pw.println();
|
||||
|
||||
pw.println(comment(AppResources.translate("configurationFile.meta.modifiedOnly")));
|
||||
pw.println("modifiedOnly = " + (modifiedOnly ? "true" : "false") + "");
|
||||
pw.println();
|
||||
|
||||
pw.println(comment(AppResources.translate("configurationFile.configuration")));
|
||||
pw.println("[configuration]");
|
||||
pw.println();
|
||||
|
||||
for (Map.Entry<String, Field> entry : Configuration.getConfigurationFields(false, true).entrySet()) {
|
||||
try {
|
||||
String name = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
ConfigurationItem item = (ConfigurationItem) field.get(null);
|
||||
ConfigurationName nameAnnotation = field.getAnnotation(ConfigurationName.class);
|
||||
if (nameAnnotation != null) {
|
||||
name = nameAnnotation.value();
|
||||
}
|
||||
String key = name;
|
||||
if (key.contains(".")) {
|
||||
key = "\"" + key + "\"";
|
||||
}
|
||||
|
||||
if (!item.hasValue && modifiedOnly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String title = Configuration.getConfigurationTitle(name);
|
||||
String description = Configuration.getConfigurationDescription(name);
|
||||
|
||||
if (showComments) {
|
||||
if (title != null && !title.isEmpty()) {
|
||||
pw.println("# " + title.replace("\n", "\n# "));
|
||||
}
|
||||
if (description != null && !description.isEmpty()) {
|
||||
List<String> descriptionLines = wordWrap(description, 80 - 4);
|
||||
boolean first = true;
|
||||
for (String descriptionLine : descriptionLines) {
|
||||
pw.println("#" + (first ? " - " : " ") + descriptionLine);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
pw.println("#");
|
||||
}
|
||||
Object value = item.get();
|
||||
Object defaultValue = Configuration.getDefaultValue(field);
|
||||
String savedValue = null;
|
||||
String savedDefaultValue = null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
String valueType = null;
|
||||
if (value == null) {
|
||||
savedValue = "";
|
||||
} else {
|
||||
switch (name) {
|
||||
case "fontPairingMap":
|
||||
@SuppressWarnings("unchecked") HashMap<String, String> fontPairingMap = (HashMap<String, String>) value;
|
||||
sb.append("{");
|
||||
for (String fontKey : fontPairingMap.keySet()) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(Helper.escapeJavaString(fontKey));
|
||||
sb.append("\" = \"");
|
||||
sb.append(Helper.escapeJavaString(fontPairingMap.get(fontKey)));
|
||||
sb.append("\"");
|
||||
first = false;
|
||||
}
|
||||
sb.append("}");
|
||||
break;
|
||||
case "swfSpecificConfigs":
|
||||
@SuppressWarnings("unchecked") HashMap<String, SwfSpecificConfiguration> swfSpecificConfigs = (HashMap<String, SwfSpecificConfiguration>) value;
|
||||
sb.append("{");
|
||||
for (String swfKey : swfSpecificConfigs.keySet()) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(Helper.escapeJavaString(swfKey));
|
||||
sb.append("\" = {");
|
||||
SwfSpecificConfiguration swfSpecificConf = swfSpecificConfigs.get(swfKey);
|
||||
sb.append("fontPairingMap = {");
|
||||
boolean first2 = true;
|
||||
for (String fontKey : swfSpecificConf.fontPairingMap.keySet()) {
|
||||
if (!first2) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(Helper.escapeJavaString(fontKey));
|
||||
sb.append("\" = \"");
|
||||
sb.append(Helper.escapeJavaString(swfSpecificConf.fontPairingMap.get(fontKey)));
|
||||
sb.append("\"");
|
||||
first2 = false;
|
||||
}
|
||||
sb.append("}, lastSelectedPath = \"");
|
||||
if (swfSpecificConf.lastSelectedPath != null) {
|
||||
sb.append(Helper.escapeJavaString(swfSpecificConf.lastSelectedPath));
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append("}");
|
||||
first = false;
|
||||
}
|
||||
sb.append("}");
|
||||
savedValue = sb.toString();
|
||||
break;
|
||||
case "swfSpecificCustomConfigs":
|
||||
@SuppressWarnings("unchecked") HashMap<String, SwfSpecificCustomConfiguration> swfSpecificCustomConfigs = (HashMap<String, SwfSpecificCustomConfiguration>) value;
|
||||
sb.append("{");
|
||||
for (String swfKey : swfSpecificCustomConfigs.keySet()) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(Helper.escapeJavaString(swfKey));
|
||||
sb.append("\" = {");
|
||||
SwfSpecificCustomConfiguration swfSpecificCustomConf = swfSpecificCustomConfigs.get(swfKey);
|
||||
boolean first2 = true;
|
||||
for (String customKey : swfSpecificCustomConf.getAllCustomData().keySet()) {
|
||||
if (!first2) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(Helper.escapeJavaString(customKey));
|
||||
sb.append("\" = \"");
|
||||
sb.append(Helper.escapeJavaString(swfSpecificCustomConf.getAllCustomData().get(customKey)));
|
||||
sb.append("\"");
|
||||
first2 = false;
|
||||
}
|
||||
sb.append("}");
|
||||
first = false;
|
||||
}
|
||||
sb.append("}");
|
||||
savedValue = sb.toString();
|
||||
break;
|
||||
default:
|
||||
Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
|
||||
if (type instanceof Class) {
|
||||
switch (((Class) type).getSimpleName()) {
|
||||
case "Boolean":
|
||||
Boolean booleanValue = (Boolean) value;
|
||||
savedValue = booleanValue == Boolean.TRUE ? "true" : "false";
|
||||
savedDefaultValue = defaultValue == Boolean.TRUE ? "true" : "false";
|
||||
valueType = "Boolean";
|
||||
break;
|
||||
case "Calendar":
|
||||
Calendar calendarValue = (Calendar) value;
|
||||
sdf.setTimeZone(calendarValue.getTimeZone());
|
||||
savedValue = sdf.format(calendarValue.getTime());
|
||||
if (defaultValue != null) {
|
||||
savedDefaultValue = sdf.format(((Calendar) defaultValue).getTime());
|
||||
}
|
||||
valueType = "Calendar";
|
||||
break;
|
||||
case "Color":
|
||||
Color colorValue = (Color) value;
|
||||
savedValue = "\"" + new RGB(colorValue).toHexRGB() + "\"";
|
||||
if (defaultValue != null) {
|
||||
savedDefaultValue = "\"" + new RGB((Color) defaultValue).toHexRGB() + "\"";
|
||||
}
|
||||
valueType = "Color";
|
||||
break;
|
||||
case "Double":
|
||||
savedValue = "" + value;
|
||||
if (defaultValue != null) {
|
||||
savedDefaultValue = "" + defaultValue;
|
||||
}
|
||||
valueType = "Double";
|
||||
break;
|
||||
case "Integer":
|
||||
savedValue = "" + value;
|
||||
if (defaultValue != null) {
|
||||
savedDefaultValue = "" + defaultValue;
|
||||
}
|
||||
valueType = "Integer";
|
||||
break;
|
||||
case "String":
|
||||
String stringValue = value.toString();
|
||||
if (stringValue.contains("\\") && !stringValue.matches("^.*[\b\t\n\f\r\"'\\x00-\\x08\\x1A-\\x1F\\x7F].*$")) {
|
||||
savedValue = "'" + stringValue + "'";
|
||||
} else {
|
||||
savedValue = "\"" + Helper.escapeJavaString(stringValue) + "\"";
|
||||
}
|
||||
if (defaultValue != null) {
|
||||
stringValue = defaultValue.toString();
|
||||
if (stringValue.contains("\\") && !stringValue.matches("^.*[\b\t\n\f\r\"'\\x00-\\x08\\x1A-\\x1F\\x7F].*$")) {
|
||||
savedDefaultValue = "'" + stringValue + "'";
|
||||
} else {
|
||||
savedDefaultValue = "\"" + Helper.escapeJavaString(stringValue) + "\"";
|
||||
}
|
||||
}
|
||||
valueType = "String";
|
||||
break;
|
||||
default:
|
||||
String stringOtherValue = value.toString();
|
||||
savedValue = "\"" + Helper.escapeJavaString(stringOtherValue) + "\"";
|
||||
if (defaultValue != null) {
|
||||
savedDefaultValue = "" + "\"" + Helper.escapeJavaString(defaultValue.toString()) + "\"";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (showComments && valueType != null) {
|
||||
pw.println("# " + AppResources.translate("valueType") + " " + AppResources.translate("valueType." + valueType));
|
||||
}
|
||||
|
||||
Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
|
||||
if (showComments && type instanceof Class) {
|
||||
Class c = (Class) type;
|
||||
if (c.isEnum()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) type;
|
||||
Enum<?>[] values = enumType.getEnumConstants();
|
||||
sb = new StringBuilder();
|
||||
first = true;
|
||||
for (Enum<?> enumValue : values) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("\"");
|
||||
sb.append(enumValue.toString());
|
||||
sb.append("\"");
|
||||
first = false;
|
||||
}
|
||||
pw.println("# " + AppResources.translate("valueType") + " " + enumType.getSimpleName());
|
||||
pw.println("# " + AppResources.translate("possibleValues") + " " + sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (showComments && savedDefaultValue != null) {
|
||||
pw.println("# " + AppResources.translate("defaultValue") + " " + savedDefaultValue);
|
||||
}
|
||||
|
||||
ConfigurationRemoved removed = field.getAnnotation(ConfigurationRemoved.class);
|
||||
|
||||
if (showComments && removed != null) {
|
||||
pw.println("# " + AppResources.translate("configuration.removed"));
|
||||
}
|
||||
|
||||
if (showComments) {
|
||||
pw.println();
|
||||
}
|
||||
if (!item.hasValue || savedValue.isEmpty()) {
|
||||
pw.print("# ");
|
||||
}
|
||||
pw.print(key + " = ");
|
||||
if (item.hasValue) {
|
||||
pw.println(savedValue);
|
||||
} else {
|
||||
pw.println(savedDefaultValue);
|
||||
}
|
||||
if (showComments) {
|
||||
pw.println();
|
||||
}
|
||||
} catch (IllegalArgumentException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(TomlConfigurationStorage.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,3 +41,23 @@ error.swf.invalid = Invalid SWF file, wrong signature.
|
||||
error.swf.headerTooShort = SWF header is too short.
|
||||
error.abc.invalid = Invalid ABC file.
|
||||
error.swf.decryptionProblem = Invalid SWF file, decryption failed.
|
||||
#after 23.0.1
|
||||
defaultValue = Default value:
|
||||
possibleValues = Possible values:
|
||||
valueType = Value type:
|
||||
valueType.Double = Floating point
|
||||
valueType.Boolean = true/false
|
||||
valueType.Calendar = DateTime
|
||||
valueType.Color = Color
|
||||
valueType.Integer = Integer
|
||||
valueType.String = String
|
||||
configurationFile = Configuration file of %app%
|
||||
configurationFile.comment = Line starting with hash is a comment
|
||||
configurationFile.modify = WARNING: This file is overwritten on every application exit. If you make changes to values, make sure FFDec is not running.
|
||||
configurationFile.meta = Section - Meta info of how configuration is stored
|
||||
configurationFile.meta.saveDate = When this file was last modified by the app
|
||||
configurationFile.meta.appVersion = Last version of tha app that modified this file
|
||||
configurationFile.meta.showComments = Show configuration comments - set to true (and exit app again to resave) to show configuration titles and descriptions.
|
||||
configurationFile.meta.modifiedOnly = Store modified items only in this file - set to false (and exit app again to resave) to show all.
|
||||
configurationFile.configuration = Section - Actual configuration
|
||||
configuration.removed = WARNING: This configuration was REMOVED. It is unused.
|
||||
@@ -41,4 +41,24 @@ error.swf.invalid = Neplatn\u00fd SWF soubor, \u0161patn\u00e1 signatura.
|
||||
error.swf.headerTooShort = SWF hlavi\u010dka je p\u0159\u00edli\u0161 kr\u00e1tk\u00e1.
|
||||
error.abc.invalid = Neplatn\u00fd ABC soubor.
|
||||
#after 18.4.1
|
||||
error.swf.decryptionProblem = Neplatn\u00fd SWF soubor, selhalo de\u0161ifrov\u00e1n\u00ed.
|
||||
error.swf.decryptionProblem = Neplatn\u00fd SWF soubor, selhalo de\u0161ifrov\u00e1n\u00ed.
|
||||
#after 23.0.1
|
||||
defaultValue = V\u00fdchoz\u00ed hodnota:
|
||||
possibleValues = Mo\u017en\u00e9 hodnoty:
|
||||
valueType = Typ hodnoty:
|
||||
valueType.Double = Desetinn\u00e9 \u010d\u00edslo
|
||||
valueType.Boolean = true/false
|
||||
valueType.Calendar = Datum + \u010das
|
||||
valueType.Color = Barva
|
||||
valueType.Integer = Cel\u00e9 \u010d\u00edslo
|
||||
valueType.String = \u0158et\u011bzec
|
||||
configurationFile = Konfigura\u010dn\u00ed soubor programu %app%
|
||||
configurationFile.comment = \u0158\u00e1dek za\u010d\u00ednaj\u00edc\u00ed na m\u0159\u00ed\u017eku je koment\u00e1\u0159
|
||||
configurationFile.modify = VAROV\u00c1N\u00cd: Tento soubor je p\u0159episov\u00e1n p\u0159i ka\u017ed\u00e9m ukon\u010den\u00ed aplikace. Pokud prov\u00e1d\u00edte zm\u011bny hodnot, ujist\u011bte se, \u017ee aplikace neb\u011b\u017e\u00ed.
|
||||
configurationFile.meta = Sekce - Metainformace o tom, jak je konfigurace ulo\u017een\u00e1
|
||||
configurationFile.meta.saveDate = Kdy byl tento soubor naposledy upraven aplikac\u00ed
|
||||
configurationFile.meta.appVersion = Posledn\u00ed verze aplikace, kter\u00e1 tento soubor upravila
|
||||
configurationFile.meta.showComments = Zobrazit koment\u00e1\u0159e ke konfiguraci - nastavte to na true (a ukon\u010dete aplikaci pro nov\u00e9 ulo\u017een\u00ed) pro zobrazen\u00ed n\u00e1zv\u016f a popis\u016f konfigurace.
|
||||
configurationFile.meta.modifiedOnly = Ukl\u00e1dat do tohoto souboru pouze zm\u011bn\u011bn\u00e9 hodnoty - nastavte na false (a ukon\u010dete aplikaci pro nov\u00e9 ulo\u017een\u00ed) pro zobrazen\u00ed v\u0161eho.
|
||||
configurationFile.configuration = Sekce - Vlastn\u00ed konfigurace
|
||||
configuration.removed = VAROV\u00c1N\u00cd: Tato konfigurace byla ODSTRAN\u011aNA. Nepou\u017e\u00edv\u00e1 se.
|
||||
Reference in New Issue
Block a user