studio.kdb.Config Maven / Gradle / Ivy
package studio.kdb;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import studio.core.AuthenticationManager;
import studio.core.Credentials;
import studio.core.DefaultAuthenticationMechanism;
import studio.kdb.config.ActionOnExit;
import studio.kdb.config.KdbMessageLimitAction;
import studio.ui.ServerList;
import studio.ui.Util;
import studio.utils.*;
import studio.utils.log4j.EnvConfig;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Config {
private static final Logger log = LogManager.getLogger();
private enum ConfigType { STRING, INT, DOUBLE, BOOLEAN, FONT, BOUNDS, COLOR, ENUM, SIZE, FILE_CHOOSER}
private static final Map defaultValues = new HashMap();
private static final Map configTypes = new HashMap();
//@TODO migrate all other keys under such approach
public static final String SHOW_SERVER_COMBOBOX = configDefault("showServerComboBox", ConfigType.BOOLEAN, true);
public static final String AUTO_SAVE = configDefault("isAutoSave", ConfigType.BOOLEAN, false);
public static final String ACTION_ON_EXIT = configDefault("actionOnExit", ConfigType.ENUM, ActionOnExit.SAVE);
public static final String SERVER_LIST_BOUNDS = configDefault("serverList", ConfigType.BOUNDS, new Dimension(ServerList.DEFAULT_WIDTH, ServerList.DEFAULT_HEIGHT));
public static final String CHART_BOUNDS = configDefault("chartBounds", ConfigType.BOUNDS, 0.5);
public static final String CELL_RIGHT_PADDING = configDefault("cellRightPadding", ConfigType.DOUBLE, 0.5);
public static final String CELL_MAX_WIDTH = configDefault("cellMaxWidth", ConfigType.INT, 200);
public static final String RSTA_ANIMATE_BRACKET_MATCHING = configDefault("rstaAnimateBracketMatching", ConfigType.BOOLEAN, true);
public static final String RSTA_HIGHLIGHT_CURRENT_LINE = configDefault("rstaHighlightCurrentLine", ConfigType.BOOLEAN, true);
public static final String RSTA_WORD_WRAP = configDefault("rstaWordWrap", ConfigType.BOOLEAN, false);
public static final String DEFAULT_LINE_ENDING = configDefault("defaultLineEnding", ConfigType.ENUM, LineEnding.Unix);
public static final String COLOR_CHARVECTOR = configDefault("token.CHARVECTOR", ConfigType.COLOR, new Color(0,200,20));
public static final String COLOR_EOLCOMMENT = configDefault("token.EOLCOMMENT", ConfigType.COLOR, Color.GRAY);
public static final String COLOR_IDENTIFIER = configDefault("token.IDENTIFIER", ConfigType.COLOR, new Color(180,160,0));
public static final String COLOR_OPERATOR = configDefault("token.OPERATOR", ConfigType.COLOR, Color.BLACK);
public static final String COLOR_BOOLEAN = configDefault("token.BOOLEAN", ConfigType.COLOR, new Color(51,204,255));
public static final String COLOR_BYTE = configDefault("token.BYTE", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_SHORT = configDefault("token.SHORT", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_LONG = configDefault("token.LONG", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_REAL = configDefault("token.REAL", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_INTEGER = configDefault("token.INTEGER", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_FLOAT = configDefault("token.FLOAT", ConfigType.COLOR, new Color(51,104,255));
public static final String COLOR_TIMESTAMP = configDefault("token.TIMESTAMP", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_TIMESPAN = configDefault("token.TIMESPAN", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_DATETIME = configDefault("token.DATETIME", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_DATE = configDefault("token.DATE", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_MONTH = configDefault("token.MONTH", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_MINUTE = configDefault("token.MINUTE", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_SECOND = configDefault("token.SECOND", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_TIME = configDefault("token.TIME", ConfigType.COLOR, new Color(184,138,0));
public static final String COLOR_SYMBOL = configDefault("token.SYMBOL", ConfigType.COLOR, new Color(179,0,134));
public static final String COLOR_KEYWORD = configDefault("token.KEYWORD", ConfigType.COLOR, new Color(0,0,255));
public static final String COLOR_COMMAND = configDefault("token.COMMAND", ConfigType.COLOR, new Color(240,180,0));
public static final String COLOR_SYSTEM = configDefault("token.SYSTEM", ConfigType.COLOR, new Color(240,180,0));
public static final String COLOR_WHITESPACE = configDefault("token.WHITESPACE", ConfigType.COLOR, Color.BLACK);
public static final String COLOR_DEFAULT = configDefault("token.DEFAULT", ConfigType.COLOR, Color.BLACK);
public static final String COLOR_BRACKET = configDefault("token.BRACKET", ConfigType.COLOR, Color.BLACK);
public static final String COLOR_ERROR = configDefault("token.ERROR", ConfigType.COLOR, Color.RED);
public static final String COLOR_BACKGROUND = configDefault("token.BACKGROUND", ConfigType.COLOR, Color.WHITE);
public static final String FONT_EDITOR = configDefault("font", ConfigType.FONT, new Font("Monospaced", Font.PLAIN, 14));
public static final String FONT_TABLE = configDefault("fontTable", ConfigType.FONT, new Font("SansSerif", Font.PLAIN, 12));
public static final String EDITOR_TAB_SIZE = configDefault("editorTabSize", ConfigType.INT, 5); // 5 is a default value for RSyntaxTextArea
public static final String EDITOR_TAB_EMULATED = configDefault("editorTabEmulated", ConfigType.BOOLEAN, false);
public static final String AUTO_REPLACE_TAB_ON_OPEN = configDefault("autoReplaceTabOnOpen", ConfigType.BOOLEAN, false);
public static final String MAX_FRACTION_DIGITS = configDefault("maxFractionDigits", ConfigType.INT, 7);
public static final String EMULATED_DOUBLE_CLICK_TIMEOUT = configDefault("emulatedDoubleClickTimeout", ConfigType.INT, 500);
public static final String OPEN_FILE_CHOOSER = configDefault("openFileChooser", ConfigType.FILE_CHOOSER, new FileChooserConfig());
public static final String SAVE_FILE_CHOOSER = configDefault("saveFileChooser", ConfigType.FILE_CHOOSER, new FileChooserConfig());
public static final String EXPORT_FILE_CHOOSER = configDefault("exportFileChooser", ConfigType.FILE_CHOOSER, new FileChooserConfig());
public static final String SESSION_INVALIDATION_ENABLED = configDefault("sessionInvalidationEnabled", ConfigType.BOOLEAN, false);
public static final String SESSION_INVALIDATION_TIMEOUT_IN_HOURS = configDefault("sessionInvalidationTimeoutInHours", ConfigType.INT, 12);
public static final String SESSION_REUSE = configDefault("sessionsReuse", ConfigType.BOOLEAN, true);
public static final String KDB_MESSAGE_SIZE_LIMIT_MB = configDefault("kdbMessageSizeLimitMB", ConfigType.INT, 10);
public static final String KDB_MESSAGE_SIZE_LIMIT_ACTION = configDefault("kdbMessageSizeLimitAction", ConfigType.ENUM, KdbMessageLimitAction.ASK);
private enum FontStyle {
Plain(Font.PLAIN), Bold(Font.BOLD), Italic(Font.ITALIC), ItalicAndBold(Font.BOLD|Font.ITALIC);
private int style;
FontStyle(int style) {
this.style = style;
}
public int getStyle() {
return style;
}
}
private static final String CONFIG_FILENAME = "studio.properties";
private static final String WORKSPACE_FILENAME = "workspace.properties";
private static final String BACKUP_FOLDER = "backup";
private static final String VERSION13 = "1.3";
private static final String VERSION12 = "1.2";
private static final String OLD_VERSION = "1.1";
private static final String VERSION = VERSION13;
private final String filename;
private PropertiesConfig config;
private PropertiesConfig workspaceConfig;
private Map servers;
private Collection serverNames;
private ServerTreeNode serverTree;
private HistoricalList serverHistory;
private static final String CONN_COL_WORDS = "server, host, connection, handle";
private static final String HOST_COL_WORDS = "server, host";
private static final String PORT_COL_WORDS = "port";
private TableConnExtractor tableConnExtractor;
private FilesBackup filesBackup;
// Can be overridden in test cases
protected static Config instance = new Config();
public enum ExecAllOption {Execute, Ask, Ignore}
protected Config(String filename) {
this.filename = filename;
init(filename);
}
private static void copyConfig(String configFileName) throws IOException {
Path src = Paths.get(EnvConfig.getFilepath(null, configFileName));
Path target = Paths.get(EnvConfig.getFilepath(configFileName));
if (Files.exists(src)) {
log.info("Copying from {} to {}", src, target);
Files.copy(src, target);
}
}
private Config() {
filename = EnvConfig.getFilepath(CONFIG_FILENAME);
String env = EnvConfig.getEnvironment();
if (env != null && ! Files.exists(Paths.get(filename))) {
log.info("Config for environment {} is not found. Copying from default location: {}", env, EnvConfig.getBaseFolder(null));
try {
copyConfig(CONFIG_FILENAME);
copyConfig(WORKSPACE_FILENAME);
} catch (IOException e) {
log.error("Error during copying configs", e);
}
}
init(filename);
}
void saveToDisk() {
config.saveToDisk();
workspaceConfig.saveToDisk();
}
public void exit() {
saveToDisk();
log.info("Shutting down");
System.exit(0);
}
private String getWorkspaceFilename() {
return EnvConfig.getFilepath(WORKSPACE_FILENAME);
}
public Workspace loadWorkspace() {
Workspace workspace = new Workspace();
String filename = getWorkspaceFilename();
log.info("Loading workspace from {}", filename);
File workspaceFile = new File(filename);
if (workspaceFile.exists()) {
try (InputStream inp = new FileInputStream(workspaceFile)) {
Properties p = new Properties();
p.load(inp);
log.info("Loaded {} properties in workspace file", p.size());
workspace.load(p);
StringBuilder str = new StringBuilder();
Workspace.Window[] windows = workspace.getWindows();
for (Workspace.Window window: windows) {
if (str.length()>0) str.append(", ");
if (window == null) str.append("null");
else {
Workspace.Tab[] tabs = window.getAllTabs();
str.append(tabs == null ? "null tabs" : "" + tabs.length);
}
}
log.info("Number of tabs in loaded windows: " + str);
} catch (IOException e) {
log.error("Can't load workspace", e);
}
}
return workspace;
}
public void saveWorkspace(Workspace workspace) {
workspaceConfig.clear();
workspace.save(workspaceConfig);
workspaceConfig.save();
}
private String[] getWords(String value) {
return Stream.of(value.split(","))
.map(String::trim)
.map(String::toLowerCase)
.toArray(String[]::new);
}
private void initTableConnExtractor() {
tableConnExtractor = new TableConnExtractor();
tableConnExtractor.setMaxConn(getTableMaxConnectionPopup());
tableConnExtractor.setConnWords(getWords(getConnColWords()));
tableConnExtractor.setHostWords(getWords(getHostColWords()));
tableConnExtractor.setPortWords(getWords(getPortColWords()));
}
public TableConnExtractor getTableConnExtractor() {
return tableConnExtractor;
}
public int getTableMaxConnectionPopup() {
return Integer.parseInt(config.getProperty("tableMaxConnectionPopup","5"));
}
public String getConnColWords() {
return config.getProperty("connColWords", CONN_COL_WORDS);
}
public String getHostColWords() {
return config.getProperty("hostColWords", HOST_COL_WORDS);
}
public String getPortColWords() {
return config.getProperty("portColWords", PORT_COL_WORDS);
}
public void setTableMaxConnectionPopup(int maxConn) {
config.setProperty("tableMaxConnectionPopup", "" + maxConn);
save();
initTableConnExtractor();
}
public void setConnColWords(String words) {
config.setProperty("connColWords", words);
save();
initTableConnExtractor();
}
public void setHostColWords(String words) {
config.setProperty("hostColWords", words);
save();
initTableConnExtractor();
}
public void setPortColWords(String words) {
config.setProperty("portColWords", words);
save();
initTableConnExtractor();
}
public ExecAllOption getExecAllOption() {
String value = config.getProperty("execAllOption", "Ask");
try {
return ExecAllOption.valueOf(value);
} catch (IllegalArgumentException e) {
log.info(value + " - can't parse execAllOption from Config. Reset to default: Ask");
return ExecAllOption.Ask;
}
}
public void setExecAllOption(ExecAllOption option) {
config.setProperty("execAllOption", option.toString());
save();
}
public String getNotesHash() {
return config.getProperty("notesHash","");
}
public void setNotesHash(String notesHash) {
config.setProperty("notesHash", notesHash);
save();
}
public String getEncoding() {
return config.getProperty("encoding", "UTF-8");
}
public static Config getInstance() {
return instance;
}
private void init(String filename) {
filesBackup = new FilesBackup(EnvConfig.getFilepath(BACKUP_FOLDER));
config = new PropertiesConfig(filesBackup, filename);
workspaceConfig = new PropertiesConfig(filesBackup, getWorkspaceFilename());
load(filename);
checkForUpgrade();
initTableConnExtractor();
}
protected void load(String filename) {
Path file = Paths.get(filename);
Path dir = file.getParent();
if (Files.notExists(dir)) {
try {
log.info("No folder with configuration found. Creating " + dir);
Files.createDirectories(dir);
} catch (IOException e) {
log.error("Can't create configuration folder {}", dir, e);
}
}
if (Files.exists(file)) {
try {
InputStream in = Files.newInputStream(file);
config.load(in);
log.info("Loaded {} properties from config {}", config.size(), file);
in.close();
} catch (IOException e) {
log.error("Can't read configuration from file {}", filename, e);
}
}
}
public String getFilename() {
return filename;
}
private void upgradeTo12() {
try {
log.info("Found old config. Converting...");
String[] names = config.getProperty("Servers", "").split(",");
List list = new ArrayList<>();
for (String name : names) {
name = name.trim();
if (name.equals("")) continue;
try {
Server server = initServerFromKey(name).newName(name);
list.add(server);
} catch (IllegalArgumentException e) {
log.warn("Error during parsing server " + name, e);
}
}
config.remove("Servers");
config.entrySet().removeIf(e -> e.getKey().toString().startsWith("server."));
config.setProperty("version", VERSION12);
initServers();
String[] results = addServers(true, list.toArray(new Server[0]));
boolean error = false;
for(String result: results) {
if (result == null) continue;
if (!error) {
error = true;
log.warn("Found errors during conversion");
}
log.warn(result);
}
log.info("Done");
} catch (IllegalArgumentException e) {
log.error("Ups... Can't convert", e);
}
}
private void upgradeTo13() {
String fullName = config.getProperty("lruServer", "");
config.remove("lruServer");
if (! fullName.equals("")) {
Server server = getServer(fullName);
if (server != Server.NO_SERVER) addServerToHistory(server);
}
save();
}
private void migrateSaveOnExit() {
String oldSaveOnExitKey = "isSaveOnExit";
if (config.containsKey(oldSaveOnExitKey)) {
boolean saveOnExit = get(oldSaveOnExitKey, true);
log.info("Migrate isSaveOnExit config property with old value {}", saveOnExit);
config.remove(oldSaveOnExitKey);
setEnum(ACTION_ON_EXIT, saveOnExit ? ActionOnExit.SAVE : ActionOnExit.NOTHING);
}
}
private void checkForUpgrade() {
if (config.size() == 0) {
log.info("Found no or empty config");
config.setProperty("version", VERSION);
initServers();
initServerHistory();
return;
}
if (config.getProperty("version", OLD_VERSION).equals(OLD_VERSION)) {
upgradeTo12();
config.setProperty("version", VERSION12);
}
initServers();
if (config.getProperty("version").equals(VERSION12)) {
initServerHistory();
upgradeTo13();
config.setProperty("version", VERSION13);
}
initServerHistory();
migrateSaveOnExit();
config.setProperty("version", VERSION);
}
protected void save() {
config.save();
}
// "".split(",") return {""}; we need to get zero length array
private String[] split(String str) {
str = str.trim();
if (str.length() == 0) return new String[0];
return str.split(",");
}
public int getServerHistoryDepth() {
return Integer.parseInt(config.getProperty("serverHistoryDepth", "20"));
}
public void setServerHistoryDepth(int depth) {
serverHistory.setDepth(depth);
config.setProperty("serverHistoryDepth", "" + depth);
save();
}
private void initServerHistory() {
int depth = getServerHistoryDepth();
serverHistory = new HistoricalList<>(depth);
for (int i=depth-1; i>=0; i--) {
String key = "serverHistory." + i;
if (! config.containsKey(key)) continue;
Server server = getServer(config.getProperty(key));
if (server == Server.NO_SERVER) continue;
serverHistory.add(server);
}
}
public List getServerHistory() {
return Collections.unmodifiableList(serverHistory);
}
public void addServerToHistory(Server server) {
serverHistory.add(server);
for (int i=serverHistory.size()-1; i>=0; i--) {
String key = "serverHistory." + i;
config.setProperty(key, serverHistory.get(i).getFullName());
}
save();
}
public void setAcceptedLicense(Date d) {
config.put("licenseAccepted", d.toString());
save();
}
public String[] getMRUFiles() {
String mru = config.getProperty("mrufiles", "");
return split(mru);
}
public void saveMRUFiles(String[] mruFiles) {
String value = Stream.of(mruFiles).limit(9).collect(Collectors.joining(","));
config.put("mrufiles", value);
save();
}
public String getLookAndFeel() {
return config.getProperty("lookandfeel");
}
public void setLookAndFeel(String lf) {
config.put("lookandfeel", lf);
save();
}
// Resolve or create a new server by connection string.
// Accept possible various connectionString such as:
// `:host:port:user:password
// host:port
// If user and password are not found, defaults form default AuthenticationMechanism are used
public Server getServerByConnectionString(String connectionString) {
String defaultAuth = getDefaultAuthMechanism();
return QConnection.getByConnection(connectionString, defaultAuth, getDefaultCredentials(defaultAuth), servers.values());
}
public Credentials getDefaultCredentials(String authenticationMechanism) {
String user = config.getProperty("auth." + authenticationMechanism + ".user", "");
String password = config.getProperty("auth." + authenticationMechanism + ".password", "");
return new Credentials(user, password);
}
public void setDefaultCredentials(String authenticationMechanism, Credentials credentials) {
config.setProperty("auth." + authenticationMechanism + ".user", credentials.getUsername());
config.setProperty("auth." + authenticationMechanism + ".password", credentials.getPassword());
save();
}
public String getDefaultAuthMechanism() {
return config.getProperty("auth", DefaultAuthenticationMechanism.NAME);
}
public void setDefaultAuthMechanism(String authMechanism) {
config.setProperty("auth", authMechanism);
save();
}
public int getResultTabsCount() {
return Integer.parseInt(config.getProperty("resultTabsCount","5"));
}
public void setResultTabsCount(int value) {
config.setProperty("resultTabsCount", "" + value);
save();
}
public int getMaxCharsInResult() {
return Integer.parseInt(config.getProperty("maxCharsInResult", "50000"));
}
public void setMaxCharsInResult(int value) {
config.setProperty("maxCharsInResult", "" + value);
save();
}
public int getMaxCharsInTableCell() {
return Integer.parseInt(config.getProperty("maxCharsInTableCell", "256"));
}
public void setMaxCharsInTableCell(int value) {
config.setProperty("maxCharsInTableCell", "" + value);
save();
}
public Collection getServerNames() {
return Collections.unmodifiableCollection(serverNames);
}
public Server[] getServers() {
return servers.values().toArray(new Server[servers.size()]);
}
public Server getServer(String name) {
if (servers.containsKey(name)) return servers.get(name);
return Server.NO_SERVER;
}
public ServerTreeNode getServerTree() {
return serverTree;
}
private Server initServerFromKey(String key) {
String host = config.getProperty("server." + key + ".host", "");
int port = Integer.parseInt(config.getProperty("server." + key + ".port", "-1"));
String username = config.getProperty("server." + key + ".user", "");
String password = config.getProperty("server." + key + ".password", "");
Color backgroundColor = get("server." + key + ".backgroundColor", Color.WHITE);
String authenticationMechanism = config.getProperty("server." + key + ".authenticationMechanism", DefaultAuthenticationMechanism.NAME);
boolean useTLS = Boolean.parseBoolean(config.getProperty("server." + key + ".useTLS", "false"));
return new Server("", host, port, username, password, backgroundColor, authenticationMechanism, useTLS);
}
private Server initServerFromProperties(int number) {
return initServerFromKey("" + number);
}
private void initServers() {
serverNames = new ArrayList<>();
serverTree = new ServerTreeNode();
servers = new HashMap<>();
initServerTree("serverTree.", serverTree, 0);
log.info("Loaded {} server from the config", servers.size());
}
private int initServerTree(String keyPrefix, ServerTreeNode parent, int number) {
for (int index = 0; ; index++) {
String key = keyPrefix + index;
String folderKey = key + "folder";
if (config.containsKey(folderKey)) {
ServerTreeNode node = parent.add(config.getProperty(folderKey));
number = initServerTree(key + ".", node, number);
} else if (config.containsKey(key)) {
String name = config.getProperty(key);
Server server = initServerFromProperties(number).newName(name);
server.setFolder(parent);
String fullName = server.getFullName();
servers.put(fullName, server);
serverNames.add(fullName);
parent.add(server);
number++;
} else {
break;
}
}
return number;
}
private void saveAllServers() {
config.entrySet().removeIf(e -> e.getKey().toString().startsWith("serverTree."));
config.entrySet().removeIf(e -> e.getKey().toString().startsWith("server."));
saveServerTree("serverTree.", serverTree, 0);
save();
}
private void saveServerDetails(Server server, int number) {
config.setProperty("server." + number + ".host", server.getHost());
config.setProperty("server." + number + ".port", "" + server.getPort());
config.setProperty("server." + number + ".user", "" + server.getUsername());
config.setProperty("server." + number + ".password", "" + server.getPassword());
config.setProperty("server." + number + ".backgroundColor", "" + Integer.toHexString(server.getBackgroundColor().getRGB()).substring(2));
config.setProperty("server." + number + ".authenticationMechanism", server.getAuthenticationMechanism());
config.setProperty("server." + number + ".useTLS", "" + server.getUseTLS());
}
private int saveServerTree(String keyPrefix, ServerTreeNode node, int number) {
int count = node.getChildCount();
for(int index = 0; index> T get(String key, T defaultValue) {
String value = config.getProperty(key);
if (value == null) return defaultValue;
try {
return (T) Enum.valueOf(defaultValue.getClass(), value);
} catch (IllegalArgumentException e) {
log.error("Failed to parse {} for config key {}", value, key, e);
}
return defaultValue;
}
public > T getEnum(String key) {
return get(key, (T) checkAndGetDefaultValue(key, ConfigType.ENUM));
}
public > boolean setEnum(String key, T value) {
T currentValue = getEnum(key);
if (currentValue == value) {
return false;
}
config.setProperty(key, value.name());
save();
return true;
}
private Font get(String key, Font defaultValue) {
String name = config.getProperty(key + ".name");
if (name == null) return defaultValue;
int size = get(key + ".size", 14);
int style = get(key +".style", FontStyle.Plain).getStyle();
return new Font(name, style, size);
}
public Font getFont(String key) {
return get(key, (Font) checkAndGetDefaultValue(key, ConfigType.FONT));
}
// Returns whether the value was changed
public boolean setFont(String key, Font value) {
Font currentValue = getFont(key);
if (currentValue.equals(value))
if (currentValue == value) {
return false;
}
config.setProperty(key + ".name", value.getName());
config.setProperty(key + ".size", "" + value.getSize());
int style = value.getStyle();
if (style < 0 || style > 3) style = 0; // Not sure if it is posible
FontStyle fontStyle = FontStyle.values()[style];
config.setProperty(key + ".style", fontStyle.name());
save();
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy