543 lines
16 KiB
Java
543 lines
16 KiB
Java
package gui.backend;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.awt.Dimension;
|
|
import java.awt.Font;
|
|
import java.awt.FontFormatException;
|
|
|
|
/**
|
|
* A class solely to store user settings relating to default behaviors,
|
|
* difficulty, filepaths, and more.
|
|
*
|
|
* These user settings are stored in a settings file that must be stored
|
|
* either in "~/.config/sudoku/settings.json" or
|
|
* "%APPDATA%/Local/Sudoku/settings.json" depending on the user's operating
|
|
* system.
|
|
*
|
|
* (Currently) Configurable settings include:
|
|
* - Default puzzles directory for .sdku files;
|
|
* - New file Properties;
|
|
* - Font;
|
|
* - Window size;
|
|
* - Window resizing (experimental);
|
|
* - Cell start mode, meaning if a cell is blank and selected, input
|
|
* is either going to the notes or entering a value;
|
|
* - Application default open behavior;
|
|
* - Theme, specifically by providing a default.theme file formatted for JSON;
|
|
* - Auto-fill notes with possible values;
|
|
* - Auto-check user-entered values with the correct values;
|
|
* - Auto-save and auto-save frequency;
|
|
*/
|
|
public class Settings {
|
|
private final String os;
|
|
|
|
// The directory where the settings file is located.
|
|
private String appDirectory;
|
|
|
|
// The default directory for .sdku files.
|
|
private String defaultDirectory;
|
|
|
|
// The properties for creating a new .sdku file.
|
|
private int newFileProperties;
|
|
|
|
// The font to be used throughout the application.
|
|
private Font font;
|
|
|
|
// The default dimension of the application window.
|
|
private Dimension dimension;
|
|
|
|
// The default dimension of the cells in the application window.
|
|
private Dimension cellDimension;
|
|
|
|
// Resizable setting
|
|
private boolean resizable;
|
|
|
|
// Cell GUI Start Mode
|
|
private boolean cellGUIStartMode;
|
|
|
|
// Default open state for the application.
|
|
private int defaultOpenState;
|
|
|
|
// Theme object storing the colors for the GUI components.
|
|
private Theme theme;
|
|
|
|
// Auto-fill notes
|
|
private boolean autoFillNotes;
|
|
|
|
// Auto check values
|
|
private boolean autoCheckValues;
|
|
|
|
// Auto-save whenever a new note or value is changed.
|
|
private boolean autoSave;
|
|
|
|
// Auto-save frequency
|
|
private int autoSaveFrequency;
|
|
|
|
/**
|
|
* Create a new Settings object, initializing the default settings
|
|
* or reading in the settings from settings file if it exists.
|
|
*
|
|
* While the defaultDirectory can be modified, it will not change where
|
|
* the settings file is located. The settings file is always located in
|
|
* either "~/.config/sudoku/" or "%APPDATA%/Local/Sudoku/", depending
|
|
* on the user's operating system.
|
|
*
|
|
* The settings file is settings.json.
|
|
*/
|
|
public Settings() {
|
|
os = System.getProperty("os.name").toLowerCase();
|
|
if(os.startsWith("windows"))
|
|
appDirectory = System.getProperty("user.home") +
|
|
"\\AppData\\Local\\Sudoku\\";
|
|
else
|
|
appDirectory = System.getProperty("user.home") +
|
|
"/.config/sudoku/";
|
|
|
|
File dir = new File(appDirectory);
|
|
|
|
// If the app directory does not exist, create it and populate a
|
|
// settings.json file with the default settings.
|
|
if (!dir.exists() || !dir.isDirectory()) {
|
|
dir.mkdirs();
|
|
defaultSettings();
|
|
updateSettingsFile();
|
|
|
|
} else readSettings();
|
|
}
|
|
|
|
/**
|
|
* Set the default settings for the application and write them to the
|
|
* settings file.
|
|
*/
|
|
private void defaultSettings() {
|
|
// Setup the default directory for .sdku puzzle files.
|
|
defaultDirectory = appDirectory + "puzzles";
|
|
File dir = new File(defaultDirectory);
|
|
|
|
// Create the puzzles directory.
|
|
if(!dir.exists() || !dir.isDirectory())
|
|
dir.mkdirs();
|
|
|
|
// Load the font from the system directory.
|
|
if(loadFont("HackNerdFont-Regular") == 0)
|
|
font = new Font("Hack Nerd Font", Font.PLAIN, 16);
|
|
|
|
// If the font does not exist, use Arial as the default font.
|
|
else
|
|
font = new Font("Arial", Font.PLAIN, 16);
|
|
|
|
// Set other default settings.
|
|
newFileProperties = 0;
|
|
dimension = new Dimension(600, 800);
|
|
resizable = false;
|
|
cellGUIStartMode = true;
|
|
defaultOpenState = 0;
|
|
theme = new Theme(new File(appDirectory + "default.theme"));
|
|
autoFillNotes = false;
|
|
autoCheckValues = true;
|
|
autoSave = false;
|
|
autoSaveFrequency = 0;
|
|
setCellDimensions();
|
|
|
|
// Write the default settings to the settings.json file.
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* Open and write the settings to the settings file.
|
|
*
|
|
* This method is called whenever a setting is updated.
|
|
*/
|
|
private void updateSettingsFile() {
|
|
// TODO: Write the settings to the settings file.
|
|
}
|
|
|
|
/**
|
|
* Read the settings from the settings file.
|
|
*
|
|
* If the settings file does not exist, the default settings will be used
|
|
* to populate the Settings file.
|
|
*/
|
|
private void readSettings() {
|
|
File settingsFile = new File(appDirectory + "/settings.json");
|
|
if (!settingsFile.exists() && !settingsFile.isDirectory()) {
|
|
defaultSettings();
|
|
return;
|
|
}
|
|
|
|
// TODO: Read the settings from the settings file.
|
|
}
|
|
|
|
/**
|
|
* Load the font from the resources folder in the user's system directory.
|
|
*
|
|
* @return int 0 if successful, 1 if the file does not exist.
|
|
*/
|
|
private int loadFont(String fontName) {
|
|
// Load the font from the system directory.
|
|
String fontFilepath;
|
|
if(os.startsWith("windows"))
|
|
fontFilepath = System.getProperty("user.home") +
|
|
"\\AppData\\Local\\Microsoft\\Windows\\Fonts\\" +
|
|
fontName + ".ttf";
|
|
else if(os.startsWith("mac"))
|
|
fontFilepath = "/Library/Fonts/" + fontName + ".ttf";
|
|
else {
|
|
fontName = "HackNerdFontMono-Regular";
|
|
fontFilepath = "/usr/share/fonts/TTF/" + fontName + ".ttf";
|
|
}
|
|
// Register the font with the GraphicsEnvironment.
|
|
try {
|
|
GraphicsEnvironment ge = GraphicsEnvironment.
|
|
getLocalGraphicsEnvironment();
|
|
|
|
ge.registerFont(Font.createFont(
|
|
Font.TRUETYPE_FONT,
|
|
new File(fontFilepath)
|
|
));
|
|
|
|
return 0;
|
|
|
|
} catch(IOException | FontFormatException e) {
|
|
System.out.println("Filepath of font not found: " +
|
|
fontFilepath + " does not exist.");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The Default Directory is a configurable setting, where the user can
|
|
* specify a default directory to store .sdku files. This is useful for
|
|
* eliminating the need for user input for file operations.
|
|
*
|
|
* By default, the default directory is either "~/.config/sudoku/puzzles"
|
|
* or "%APPDATA%/Local/Sudoku/Puzzles", depending on the user's operating
|
|
* system.
|
|
*
|
|
* @return String
|
|
*/
|
|
public String getDefaultDirectory() {
|
|
return defaultDirectory;
|
|
}
|
|
|
|
/**
|
|
* Set the default directory and write it to the settings file.
|
|
*
|
|
* @param defaultDirectory
|
|
*/
|
|
public void setDefaultDirectory(String defaultDirectory) {
|
|
this.defaultDirectory = defaultDirectory;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* New File Properties is a configurable setting, where the following
|
|
* values are allowable:
|
|
* 0 - Create a new, blank .sdku file
|
|
* 1 - Create a new, random .sdku file
|
|
*
|
|
* Integer is being used instead of boolean since additional properties
|
|
* may be added in the future.
|
|
*
|
|
* @return int
|
|
*/
|
|
public int getNewFileProperties() {
|
|
return newFileProperties;
|
|
}
|
|
|
|
/**
|
|
* Set the new file properties and write them to the settings file.
|
|
*
|
|
* @param newFileProperties
|
|
*/
|
|
public void setNewFileProperties(int newFileProperties) {
|
|
this.newFileProperties = newFileProperties;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The Font is a configurable setting, where the user can specify a
|
|
* font to be used throughout the application.
|
|
*
|
|
* Fonts are loaded from the system directory. In Windows, the font
|
|
* is loaded from C:\Windows\Fonts\. In MacOS, the font is loaded
|
|
* from /Library/Fonts/. In Linux, the font is loaded from
|
|
* /usr/share/fonts/.
|
|
*
|
|
* @return Font
|
|
*/
|
|
public Font getFont() {
|
|
return font;
|
|
}
|
|
|
|
/**
|
|
* Set the font and write it to the settings file.
|
|
*
|
|
* @param font
|
|
*/
|
|
public void setFont(Font font) {
|
|
this.font = font;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The default dimension of the application window.
|
|
*
|
|
* The user can specify both the starting width and height of the app,
|
|
* and the app will remember the last used dimensions as well.
|
|
*
|
|
* @return Dimension
|
|
*/
|
|
public Dimension getDimension() {
|
|
return dimension;
|
|
}
|
|
|
|
/**
|
|
* Set the default dimension and write it to the settings file.
|
|
*
|
|
* @param dimension
|
|
*/
|
|
public void setDimension(Dimension dimension) {
|
|
this.dimension = dimension;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The resizable setting for the application window.
|
|
*
|
|
* By default, the application window is not resizable and is considered
|
|
* an experimental feature. Dynamic layout is not yet supported.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public boolean getResizable() {
|
|
return resizable;
|
|
}
|
|
|
|
/**
|
|
* Set the resizable setting and write it to the settings file.
|
|
*
|
|
* @param resizable
|
|
*/
|
|
public void setResizable(boolean resizable) {
|
|
this.resizable = resizable;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The Cell GUI Start Mode is a configurable setting, where the user can
|
|
* specify whether the cell GUI should start in notes mode or value mode.
|
|
*
|
|
* By default, the cell GUI starts in value mode, ie. returns false.
|
|
* Set to true to start in notes mode.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public boolean getCellGUIStartMode() {
|
|
return cellGUIStartMode;
|
|
}
|
|
|
|
/**
|
|
* Set the cell GUI start mode and write it to the settings file.
|
|
*
|
|
* @param cellGUIStartMode
|
|
*/
|
|
public void setCellGUIStartMode(boolean cellGUIStartMode) {
|
|
this.cellGUIStartMode = cellGUIStartMode;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The default open state for the application. The following values
|
|
* are accepted:
|
|
* 0 - Open the default easy.sdku file, default behavior;
|
|
* 1 - Open the last opened .sdku file;
|
|
* 2 - Open a new, blank .sdku file; and
|
|
* 3 - Open a new, random .sdku file.
|
|
*
|
|
* NOTE: The value 2 is not yet supported.
|
|
*
|
|
* @return
|
|
*/
|
|
public int getDefaultOpenState() {
|
|
return defaultOpenState;
|
|
}
|
|
|
|
/**
|
|
* Set the default open state for the application and write it to the
|
|
* settings file.
|
|
*
|
|
* @param defaultOpenState
|
|
*/
|
|
public void setDefaultOpenState(int defaultOpenState) {
|
|
this.defaultOpenState = defaultOpenState;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The Theme object stores the colors for the GUI components.
|
|
*
|
|
* The available colors for customization are:
|
|
* - primaryBackground
|
|
* - secondaryBackground
|
|
* - primaryText
|
|
* - secondaryText
|
|
* - primaryHighlight
|
|
* - secondaryHighlight
|
|
* - primaryBorder
|
|
* - secondaryBorder
|
|
* - primaryButton
|
|
* - secondaryButton
|
|
* - primaryButtonHighlight
|
|
* - secondaryButtonHighlight
|
|
* - primaryButtonBorder
|
|
* - secondaryButtonBorder
|
|
*
|
|
* @see Theme
|
|
* @return
|
|
*/
|
|
public Theme getTheme() {
|
|
return theme;
|
|
}
|
|
|
|
/**
|
|
* Set the theme and write it to the settings file.
|
|
*
|
|
* @param theme
|
|
*/
|
|
public void setTheme(Theme theme) {
|
|
this.theme = theme;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The Auto-fill notes setting is a configurable setting, where the user
|
|
* can specify whether notes should be automatically filled in when a
|
|
* value is placed in a cell.
|
|
*
|
|
* By default, the auto-fill notes setting is set to false.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public boolean getAutoFillNotes() {
|
|
return autoFillNotes;
|
|
}
|
|
|
|
/**
|
|
* Set the auto-fill notes setting and write it to the settings file.
|
|
*
|
|
* @param autoFillNotes
|
|
*/
|
|
public void setAutoFillNotes(boolean autoFillNotes) {
|
|
this.autoFillNotes = autoFillNotes;
|
|
setCellGUIStartMode(autoFillNotes);
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The Auto-check values setting is a configurable setting, where the user
|
|
* can specify whether values should be automatically checked when placed
|
|
* in a cell.
|
|
*
|
|
* By default, the auto-check values setting is set to false.
|
|
*
|
|
* @return
|
|
*/
|
|
public boolean getAutoCheckValues() {
|
|
return autoCheckValues;
|
|
}
|
|
|
|
/**
|
|
* Set the auto-check values setting and write it to the settings file.
|
|
*
|
|
* @param autoCheckValues
|
|
*/
|
|
public void setAutoCheckValues(boolean autoCheckValues) {
|
|
this.autoCheckValues = autoCheckValues;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The default dimensions of the cells in the application window.
|
|
*
|
|
* The default dimensions are set to 50x50 pixels.
|
|
*
|
|
* @return
|
|
*/
|
|
public Dimension getCellDimensions() {
|
|
return cellDimension;
|
|
}
|
|
|
|
private void setCellDimensions() {
|
|
int height;
|
|
int width;
|
|
|
|
if(dimension.height < 500) height = 50;
|
|
else height = dimension.height / 10;
|
|
|
|
if(dimension.width < 500) width = 50;
|
|
else width = dimension.width / 10;
|
|
|
|
cellDimension = new Dimension(width, height);
|
|
}
|
|
|
|
/**
|
|
* Auto-save is a user-configurable setting to automatically save the
|
|
* puzzle anytime they make a change. Additionally, auto-save will
|
|
* result in the file being automatically saved every 60 seconds, to
|
|
* preserve the elapsed time tracking.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public boolean getAutoSave() {
|
|
return autoSave;
|
|
}
|
|
|
|
/**
|
|
* Set the auto-save feature to a specified state.
|
|
*
|
|
* @param autoSave
|
|
*/
|
|
public void setAutoSave(boolean autoSave) {
|
|
this.autoSave = autoSave;
|
|
updateSettingsFile();
|
|
}
|
|
|
|
/**
|
|
* The auto save frequnecy, in seconds.
|
|
*
|
|
* By default, auto-save will save whenever the user makes changes on the
|
|
* puzzle. However, since elapsed time and other future features are not
|
|
* user-controlled events, the frequency is used to specify in a separate
|
|
* thread how often the .sdku file should be saved.
|
|
*
|
|
* For performance and realistic necessity for preserving this kind of
|
|
* information, the frequency should (not required) be following:
|
|
* - 0: off;
|
|
* - 5: 5 second intervals;
|
|
* - 30: 30 second intervals;
|
|
* - 60: 60 second intervals.
|
|
*
|
|
* If auto-save is off, then this value is 0 automatically. When auto-save
|
|
* is turned on, by default the value is 30.
|
|
*
|
|
* @return auto-save frequency
|
|
*/
|
|
public int getAutoSaveFrequency() {
|
|
return autoSaveFrequency;
|
|
}
|
|
|
|
/**
|
|
* Set the auto-save frequency, in seconds.
|
|
*
|
|
* @param autoSaveFrequency
|
|
*/
|
|
public void setAutoSaveFrequency(int autoSaveFrequency) {
|
|
this.autoSaveFrequency = autoSaveFrequency;
|
|
updateSettingsFile();
|
|
}
|
|
}
|