-
Notifications
You must be signed in to change notification settings - Fork 0
ConfigManager
Relevant source files
The ConfigManager system is responsible for managing all persistent user preferences in the MouseMacros application. It handles loading, saving, and providing access to configuration settings that control application behavior across categories including appearance, storage, execution, and hotkey mappings. The configuration is persisted as a JSON file (config.cfg) in the platform-specific application data directory.
For runtime state management such as window sizes and recent directories, see CacheManager. For details on individual configuration categories and their effects, see Configuration Files and Settings.
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L1-L133
The following diagram shows how ConfigManager fits into the configuration persistence architecture:
flowchart TD
ConfigManager["ConfigManager"]
ConfigClass["Config (inner class)"]
GsonInstance["Gson (pretty-printed)"]
FileUtil["FileUtil"]
ConfigDir["CONFIG_DIR"]
ConfigFile["config.cfg (JSON)"]
SettingsDialog["SettingsDialog"]
MacroSettingsDialog["MacroSettingsDialog"]
MainFrame["MainFrame"]
ComponentUtil["ComponentUtil"]
Localizer["Localizer"]
MacroManager["MacroManager"]
StaticBlock["static { } block"]
LoadConfig["loadConfig()"]
StaticBlock --> FileUtil
StaticBlock --> ConfigFile
LoadConfig --> ConfigFile
LoadConfig --> GsonInstance
LoadConfig --> ConfigClass
ConfigManager --> ConfigFile
ConfigManager --> FileUtil
SettingsDialog --> ConfigManager
MacroSettingsDialog --> ConfigManager
MainFrame --> ConfigManager
ComponentUtil --> ConfigManager
Localizer --> ConfigManager
MacroManager --> ConfigManager
subgraph Initialization ["Initialization"]
StaticBlock
LoadConfig
StaticBlock --> LoadConfig
end
subgraph subGraph2 ["Consuming Components"]
SettingsDialog
MacroSettingsDialog
MainFrame
ComponentUtil
Localizer
MacroManager
end
subgraph subGraph1 ["Storage Layer"]
FileUtil
ConfigDir
ConfigFile
FileUtil --> ConfigDir
end
subgraph subGraph0 ["Configuration Management"]
ConfigManager
ConfigClass
GsonInstance
ConfigManager --> ConfigClass
ConfigManager --> GsonInstance
end
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L14-L29, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L46-L76
The Config inner class src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L31-L44
represents the complete configuration state. All fields have default values that are used when creating a new configuration.
| Field | Type | Default Value | Description |
|---|---|---|---|
followSystemSettings |
boolean |
true |
When enabled, language and theme follow OS settings |
lang |
String |
"zh_cn" |
Language code (e.g., en_us, zh_cn, ja_jp) |
enableDarkMode |
boolean |
false |
Dark theme toggle (only used when followSystemSettings is false) |
enableDefaultStorage |
boolean |
false |
Use default path for macro file operations |
defaultMmcStoragePath |
String |
"" |
Default directory for saving/loading .mmc files |
enableQuickMode |
boolean |
false |
Skip recorded delays during playback |
allowLongStr |
boolean |
false |
Allow tooltips to display long strings |
readjustFrameMode |
String |
RFM_STANDARDIZED |
Window resize behavior: MIXED, STANDARDIZED, or MEMORIZED
|
keyMap |
Map<String, String> |
new HashMap<>() |
Hotkey mappings (e.g., "keyRecord" → "F2") |
enableCustomMacroSettings |
boolean |
false |
Use per-macro execution settings instead of global |
repeatTime |
int |
1 |
Number of times to repeat macro playback |
repeatDelay |
double |
0 |
Delay in seconds between macro repetitions |
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L31-L44
The ConfigManager defines three constants src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L21-L23
for controlling window resizing behavior when language changes:
| Constant | Value | Behavior |
|---|---|---|
RFM_MIXED |
"MIXED" |
Uses cached sizes when available, otherwise standardized sizes |
RFM_STANDARDIZED |
"STANDARDIZED" |
Always calculates new recommended size based on content |
RFM_MEMORIZED |
"MEMORIZED" |
Always uses cached historical window sizes |
These constants are referenced by ComponentUtil when applying language changes to determine whether to resize windows.
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L21-L23
The ConfigManager initializes during class loading through a static block src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L25-L29
:
sequenceDiagram
participant JVM
participant ConfigManager
participant FileUtil
participant Filesystem
JVM->>ConfigManager: "Load class"
ConfigManager->>ConfigManager: "Enter static block"
ConfigManager->>FileUtil: "getLocalStoragePath()"
FileUtil->>Filesystem: "Detect OS, resolve path"
Filesystem-->>FileUtil: "Platform-specific path"
FileUtil-->>ConfigManager: "Path object"
ConfigManager->>ConfigManager: "Set CONFIG_DIR"
ConfigManager->>ConfigManager: "Construct CONFIG_PATH"
ConfigManager->>ConfigManager: "Call loadConfig()"
ConfigManager->>Filesystem: "Read config.cfg"
Filesystem-->>ConfigManager: "JSON string or null"
ConfigManager->>ConfigManager: "Deserialize or create default"
ConfigManager->>ConfigManager: "Assign to config field"
The CONFIG_DIR field src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L15
stores the platform-specific application data directory (e.g., %LOCALAPPDATA%/MouseMacros on Windows), while CONFIG_PATH src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L17
points to the config.cfg file within that directory.
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L25-L29, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L15-L17
The loadConfig() method src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L49-L63
implements the configuration loading logic with fallback behavior:
flowchart TD
Start["loadConfig()"]
ReadFile["FileUtil.readFile(CONFIG_PATH)"]
CheckNull["json == null or empty?"]
ParseJson["gson.fromJson(json, Config.class)"]
CreateDefault1["new Config()"]
SaveDefault1["saveConfig(cfg)"]
CreateDefault2["new Config()"]
SaveDefault2["saveConfig(_config)"]
Return1["Return cfg"]
Return2["Return parsed Config"]
Return3["Return _config"]
Start --> ReadFile
ReadFile --> CheckNull
ReadFile --> CreateDefault2
CheckNull --> CreateDefault1
CheckNull --> ParseJson
CreateDefault1 --> SaveDefault1
SaveDefault1 --> Return1
ParseJson --> Return2
CreateDefault2 --> SaveDefault2
SaveDefault2 --> Return3
Loading Logic:
- Attempts to read
config.cfgusingFileUtil.readFile() - If file is missing or empty, creates a new
Configwith defaults and saves it - If file exists, deserializes JSON using Gson
- On any
IOException, creates and saves a default configuration - Returns the loaded or newly created
Configobject
The reloadConfig() method src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L46
provides a way to refresh the static config field after external changes.
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L46-L63
The saveConfig() method src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L66-L76
persists configuration changes to disk:
flowchart TD
Input["Config object"]
EnsureDir["Create CONFIG_DIR if needed"]
Serialize["gson.toJson(config)"]
WriteFile["FileUtil.writeFile(CONFIG_PATH, json)"]
HandleError["e.printStackTrace()"]
Input --> EnsureDir
EnsureDir --> Serialize
Serialize --> WriteFile
WriteFile --> HandleError
Saving Process:
- Ensures the parent directory (
CONFIG_DIR) exists, creating it if necessary src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L69-L70 - Serializes the
Configobject to pretty-printed JSON using Gson src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L71 - Writes the JSON string to
config.cfgusingFileUtil.writeFile()src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L72 - Catches and prints any
IOExceptionthat occurs src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L73-L75
The Gson instance src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L18
is configured with .setPrettyPrinting() to make the JSON file human-readable.
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L66-L76, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L18
The getAvailableLangs() method src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132
detects all available language files at runtime, supporting both development (source directory) and production (JAR file) environments.
flowchart TD
Start["getAvailableLangs()"]
DevMode["Localizer.isDevMode()"]
DevPath["List files in 'lang' directory"]
JarResource["Get lang/ resource URL"]
CheckProtocol["dirURL protocol?"]
JarMode["Read JAR entries"]
FileMode["List directory files"]
ExtractNames["Extract .json filenames"]
ReturnArray["Return String[] array"]
Start --> DevMode
DevMode --> DevPath
DevMode --> JarResource
DevPath --> ExtractNames
JarResource --> CheckProtocol
CheckProtocol --> JarMode
CheckProtocol --> FileMode
JarMode --> ExtractNames
FileMode --> ExtractNames
ExtractNames --> ReturnArray
When Localizer.isDevMode() returns true src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L81-L91
:
- Lists files in the
langdirectory usingFileUtil.listFileNames() - Strips
.jsonextensions to get language codes
When running from a JAR src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L93-L129
:
JAR Protocol Handling:
- Gets the
lang/resource URL from the class loader src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L94 - Checks if the protocol is
"jar"src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L95 - Extracts the JAR file path from the URL src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L96-L103
- Opens the JAR file and enumerates all entries src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L104-L105
- Filters entries starting with
"lang/"and ending with".json"src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L108 - Extracts the language code from each entry name src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L109
File Protocol Fallback:
- If the protocol is
"file"src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L114 lists files in the directory directly - Filters for
.jsonfiles src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L116
Platform-Specific Path Handling:
- On Windows, removes leading
/from JAR paths src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L101-L103 - URL-decodes the path to handle special characters src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L100
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132
The following diagram shows how various components interact with ConfigManager:
flowchart TD
SettingsDialog["SettingsDialog"]
MacroSettingsDialog["MacroSettingsDialog"]
MainFrame["MainFrame"]
ConfigField["ConfigManager.config"]
LoadMethod["loadConfig()"]
SaveMethod["saveConfig(Config)"]
ReloadMethod["reloadConfig()"]
LangsMethod["getAvailableLangs()"]
AppearanceFields["followSystemSettings<br>lang<br>enableDarkMode<br>allowLongStr<br>readjustFrameMode"]
StorageFields["enableDefaultStorage<br>defaultMmcStoragePath"]
ExecutionFields["enableQuickMode<br>enableCustomMacroSettings<br>repeatTime<br>repeatDelay"]
HotkeyFields["keyMap"]
ThemeSystem["ComponentUtil<br>(Theme Application)"]
LocalizationSystem["Localizer<br>(Language Loading)"]
FileSystem["MacroManager<br>(File Operations)"]
PlaybackSystem["MacroManager<br>(Playback Execution)"]
HotkeySystem["GlobalMouseListener<br>(Hotkey Detection)"]
SettingsDialog --> ConfigField
MacroSettingsDialog --> ConfigField
MainFrame --> ConfigField
SettingsDialog --> SaveMethod
MacroSettingsDialog --> SaveMethod
SettingsDialog --> LangsMethod
ConfigField --> AppearanceFields
ConfigField --> StorageFields
ConfigField --> ExecutionFields
ConfigField --> HotkeyFields
AppearanceFields --> ThemeSystem
AppearanceFields --> LocalizationSystem
StorageFields --> FileSystem
ExecutionFields --> PlaybackSystem
HotkeyFields --> HotkeySystem
subgraph subGraph3 ["Consuming Systems"]
ThemeSystem
LocalizationSystem
FileSystem
PlaybackSystem
HotkeySystem
end
subgraph subGraph2 ["Config Fields Groups"]
AppearanceFields
StorageFields
ExecutionFields
HotkeyFields
end
subgraph subGraph1 ["ConfigManager API"]
ConfigField
LoadMethod
SaveMethod
ReloadMethod
LangsMethod
end
subgraph subGraph0 ["UI Components"]
SettingsDialog
MacroSettingsDialog
MainFrame
end
Components typically access configuration directly through the static config field:
ConfigManager.config.followSystemSettingsConfigManager.config.langConfigManager.config.enableDarkMode- etc.
Components modify configuration and persist changes:
- Read current config:
Config cfg = ConfigManager.config - Modify fields:
cfg.lang = "en_us" - Save changes:
ConfigManager.saveConfig(cfg) - Optionally reload:
ConfigManager.reloadConfig()
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L19, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L46, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L66-L76
The config.cfg file uses JSON format with pretty-printing enabled. Example structure:
{
"followSystemSettings": true,
"lang": "zh_cn",
"enableDarkMode": false,
"enableDefaultStorage": false,
"defaultMmcStoragePath": "",
"enableQuickMode": false,
"allowLongStr": false,
"readjustFrameMode": "STANDARDIZED",
"keyMap": {
"keyRecord": "F2",
"keyStop": "F3",
"keyPlay": "F4",
"keyAbort": "F5"
},
"enableCustomMacroSettings": false,
"repeatTime": 1,
"repeatDelay": 0.0
}The file is located at CONFIG_DIR\config.cfg, where CONFIG_DIR resolves to platform-specific paths (see File and Path Utilities for path resolution details).
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L18, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L71
// Access appearance settings
boolean useDarkMode = ConfigManager.config.enableDarkMode;
String currentLang = ConfigManager.config.lang;
// Access execution settings
boolean quickMode = ConfigManager.config.enableQuickMode;
int repeatCount = ConfigManager.config.repeatTime;
// Access storage settings
boolean useDefaultPath = ConfigManager.config.enableDefaultStorage;
String defaultPath = ConfigManager.config.defaultMmcStoragePath;
// Get current config
Config cfg = ConfigManager.config;
// Modify settings
cfg.lang = "en_us";
cfg.enableDarkMode = true;
cfg.repeatTime = 5;
// Persist changes
ConfigManager.saveConfig(cfg);
// Reload if needed (updates static field)
ConfigManager.reloadConfig();
// Get all available language files
String[] langs = ConfigManager.getAvailableLangs();
// Returns: ["en_us", "zh_cn", "ja_jp", "ko_kr", "ru_ru", "es_es", "fr_fr"]
// Populate UI dropdown
for (String lang : langs) {
comboBox.addItem(lang);
}
Sources: src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L19, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L66-L76, src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132