# Configuration and Persistence
> **Relevant source files**
> * [src/io/github/samera2022/mouse_macros/manager/CacheManager.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java)
> * [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java)
> * [src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java)
## Purpose and Scope
The Configuration and Persistence system manages two distinct categories of application data: durable user preferences and ephemeral runtime state. This dual-persistence architecture separates configuration settings that survive across installations from session-specific UI state that changes during normal operation.
This page covers the overall architecture and integration of both persistence subsystems. For detailed information about specific components, see:
* [ConfigManager](ConfigManager) - Configuration loading, saving, and language discovery
* [Configuration Files and Settings](Configuration-Files-and-Settings) - config.cfg structure and Config class fields
* [CacheManager](CacheManager) - Runtime state caching, cache.json structure, and window management
For information about how configuration integrates with the UI, see [Settings Dialog](Settings-Dialog).
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L1-L133](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L1-L133)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L1-L62](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L1-L62)
---
## Architecture Overview
The persistence system employs a dual-manager architecture that separates durable configuration from volatile runtime state:
### Persistence Architecture Diagram
```mermaid
flowchart TD
ConfigStatic["ConfigManager static block
lines 25-29"]
CacheStatic["CacheManager static field
line 17"]
ConfigManager["ConfigManager
Static Utility Class"]
CacheManager["CacheManager
Static Utility Class"]
ConfigObj["Config
User Preferences
lines 31-44"]
CacheObj["Cache
Runtime State
CacheManager:23-28"]
ConfigFile["config.cfg
CONFIG_DIR"]
CacheFile["cache.json
CACHE_PATH"]
FileUtil["FileUtil
getLocalStoragePath()"]
Gson["Gson
JSON Serialization"]
SettingsDialog["SettingsDialog
reads/writes config"]
MacroSettingsDialog["MacroSettingsDialog
reads/writes config"]
ExitDialog["ExitDialog
reads/writes cache"]
MainFrame["MainFrame
reads config and cache"]
MacroManager["MacroManager
reads config"]
ConfigStatic --> ConfigManager
CacheStatic --> CacheManager
ConfigManager --> ConfigObj
CacheManager --> CacheObj
ConfigManager --> Gson
ConfigManager --> FileUtil
CacheManager --> Gson
CacheManager --> FileUtil
ConfigObj --> ConfigFile
CacheObj --> CacheFile
FileUtil --> ConfigFile
FileUtil --> CacheFile
SettingsDialog --> ConfigManager
MacroSettingsDialog --> ConfigManager
ExitDialog --> CacheManager
MainFrame --> ConfigManager
MainFrame --> CacheManager
MacroManager --> ConfigManager
subgraph Consumers ["Consumers"]
SettingsDialog
MacroSettingsDialog
ExitDialog
MainFrame
MacroManager
end
subgraph subGraph4 ["File I/O"]
FileUtil
Gson
end
subgraph subGraph3 ["Persistence Layer"]
ConfigFile
CacheFile
end
subgraph subGraph2 ["Data Objects"]
ConfigObj
CacheObj
end
subgraph subGraph1 ["Manager Layer"]
ConfigManager
CacheManager
end
subgraph subGraph0 ["Static Initialization"]
ConfigStatic
CacheStatic
end
```
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L14-L29](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L14-L29)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L17](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L17)
* [src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java L1-L103](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java#L1-L103)
---
## Persistence Components
The system consists of two primary manager classes that work in parallel to manage different types of application state:
### ConfigManager
`ConfigManager` is a static utility class that manages durable user preferences. It exposes a single public static field:
| Field | Type | Purpose |
| --- | --- | --- |
| `config` | `Config` | Application-level settings (language, theme, hotkeys, macro settings) |
The field is initialized in a static block [ConfigManager.java L25-L29](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ConfigManager.java#L25-L29)
ensuring configuration is loaded before any other application code executes.
**Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L14-L29](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L14-L29)
### CacheManager
`CacheManager` is a static utility class that manages ephemeral runtime state. It exposes a single public static field:
| Field | Type | Purpose |
| --- | --- | --- |
| `cache` | `Cache` | Runtime UI state (last used directories, window sizes, exit preferences) |
The field is initialized during class loading [CacheManager.java L17](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/CacheManager.java#L17-L17)
loading cached state from the previous session.
**Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L13-L17](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L13-L17)
### Data Structure Class Diagram
```mermaid
classDiagram
class Config {
+boolean followSystemSettings
+String lang
+boolean enableDarkMode
+boolean enableDefaultStorage
+String defaultMmcStoragePath
+boolean enableQuickMode
+boolean allowLongStr
+String readjustFrameMode
+Map keyMap
+boolean enableCustomMacroSettings
+int repeatTime
+double repeatDelay
}
class Cache {
+String lastLoadDirectory
+String lastSaveDirectory
+Map windowSizeMap
+String defaultCloseOperation
}
class ConfigManager {
+static String CONFIG_DIR
+static Config config
+static Config loadConfig()
+static void saveConfig(Config)
+static void reloadConfig()
+static String[] getAvailableLangs()
}
class CacheManager {
+static Cache cache
+static void reloadCache()
+static void saveCache()
}
ConfigManager --> Config
CacheManager --> Cache
```
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L31-L44](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L31-L44)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L23-L28](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L23-L28)
### Config Fields Reference
| Field Name | Type | Default Value | Purpose |
| --- | --- | --- | --- |
| `followSystemSettings` | `boolean` | `true` | When enabled, synchronizes `lang` and `enableDarkMode` with OS settings |
| `lang` | `String` | `"zh_cn"` | Current language code (e.g., "en_us", "zh_cn", "ja_jp") |
| `enableDarkMode` | `boolean` | `false` | Dark theme enabled state |
| `enableDefaultStorage` | `boolean` | `false` | When true, uses `defaultMmcStoragePath` for file operations |
| `defaultMmcStoragePath` | `String` | `""` (empty) | Default directory for saving/loading .mmc macro files |
| `enableQuickMode` | `boolean` | `false` | Enables quick playback mode (ignores recorded delays) |
| `allowLongStr` | `boolean` | `false` | Allows long strings in UI components |
| `readjustFrameMode` | `String` | `"STANDARDIZED"` | Frame resize mode: `MIXED`, `STANDARDIZED`, or `MEMORIZED` |
| `keyMap` | `Map` | `new HashMap<>()` | Custom hotkey assignments (e.g., "record" → "F2") |
| `enableCustomMacroSettings` | `boolean` | `false` | Enables per-macro custom settings |
| `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](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L31-L44)
### Cache Fields Reference
| Field Name | Type | Default Value | Purpose |
| --- | --- | --- | --- |
| `lastLoadDirectory` | `String` | `""` (empty) | Last directory used for loading macro files |
| `lastSaveDirectory` | `String` | `""` (empty) | Last directory used for saving macro files |
| `windowSizeMap` | `Map` | `new HashMap<>()` | Stores window sizes by window name |
| `defaultCloseOperation` | `String` | `""` (empty) | Default close behavior: `exit_on_close`, `minimize_to_tray`, or empty |
**Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L23-L28](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L23-L28)
---
## Persistence Strategy
The system persists data to two separate JSON files in platform-specific application data directories:
### File Locations
The storage directory is resolved via `FileUtil.getLocalStoragePath()` [ConfigManager.java L26](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ConfigManager.java#L26-L26)
which returns platform-specific paths:
* **Windows:** `%LOCALAPPDATA%/MouseMacros/`
* **macOS:** `~/Library/Application Support/MouseMacros/`
* **Linux:** `~/.local/share/MouseMacros/`
The two persistence files are:
| File | Manager | Constant | Content |
| --- | --- | --- | --- |
| `config.cfg` | `ConfigManager` | `CONFIG_PATH` | User preferences (`Config` object serialized as JSON) |
| `cache.json` | `CacheManager` | `CACHE_PATH` | Runtime state (`Cache` object serialized as JSON) |
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L15-L27](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L15-L27)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L15](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L15-L15)
### Configuration Serialization Flow
```mermaid
sequenceDiagram
participant Application Code
participant ConfigManager
participant Gson
participant FileUtil
participant File System
note over Application Code,File System: Save Configuration
Application Code->>ConfigManager: saveConfig(config)
ConfigManager->>ConfigManager: Check CONFIG_DIR exists
ConfigManager->>Gson: Create if needed (line 69-70)
Gson-->>ConfigManager: toJson(config)
ConfigManager->>FileUtil: JSON string
FileUtil->>File System: writeFile(CONFIG_PATH, json)
note over Application Code,File System: Load Configuration
Application Code->>ConfigManager: Write UTF-8 encoded JSON
ConfigManager->>FileUtil: loadConfig()
loop [File exists and valid]
FileUtil-->>ConfigManager: readFile(CONFIG_PATH)
ConfigManager->>Gson: JSON string
Gson-->>ConfigManager: fromJson(json, Config.class)
ConfigManager->>ConfigManager: Config object
ConfigManager-->>Application Code: Create new Config()
end
ConfigManager-->>Application Code: Save default config (line 53-54)
```
**Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L49-L76](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L49-L76)
### Cache Serialization Flow
```mermaid
sequenceDiagram
participant Application Code
participant CacheManager
participant Gson
participant java.nio.file.Files
participant File System
note over Application Code,File System: Save Cache
Application Code->>CacheManager: saveCache()
CacheManager->>CacheManager: Get CACHE_PATH
CacheManager->>CacheManager: Ensure parent directory exists
CacheManager->>Gson: (line 42)
Gson-->>CacheManager: toJson(cache)
CacheManager->>java.nio.file.Files: JSON string
java.nio.file.Files->>File System: write(cachePath, json.getBytes())
note over Application Code,File System: Load Cache
CacheManager->>CacheManager: Write UTF-8 encoded JSON
CacheManager->>CacheManager: loadCache() during static init
loop [File exists]
CacheManager->>java.nio.file.Files: Get CACHE_PATH
java.nio.file.Files-->>CacheManager: readAllBytes(cachePath)
CacheManager->>Gson: byte array
Gson-->>CacheManager: fromJson(json, Cache.class)
CacheManager->>CacheManager: Cache object
CacheManager-->>CacheManager: Create new Cache()
end
```
**Sources:** [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L34-L61](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L34-L61)
### Directory Creation
Both managers ensure the parent directory exists before writing:
**ConfigManager** [ConfigManager.java L69-L70](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ConfigManager.java#L69-L70)
:
```
java.io.File dir = new java.io.File(CONFIG_DIR);
if (!dir.exists()) dir.mkdirs();
```
**CacheManager** [CacheManager.java L42](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/CacheManager.java#L42-L42)
:
```
if (cachePath.getParent() != null) Files.createDirectories(cachePath.getParent());
```
This guarantees that persistence files can be saved on first run, even when the application data directory doesn't exist.
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L66-L76](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L66-L76)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L38-L48](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L38-L48)
---
## Static Initialization
Configuration loading occurs during class initialization, before any application code executes. This is achieved through a static initialization block:
### Static Initialization Sequence
```mermaid
sequenceDiagram
participant JVM Class Loader
participant ConfigManager
participant CacheManager
participant FileUtil
participant Gson
note over JVM Class Loader,Gson: ConfigManager Static Initialization
JVM Class Loader->>ConfigManager: Load ConfigManager class
ConfigManager->>ConfigManager: Initialize Gson (line 18)
ConfigManager->>ConfigManager: Execute static block (lines 25-29)
ConfigManager->>FileUtil: getLocalStoragePath()
FileUtil-->>ConfigManager: Platform-specific path
ConfigManager->>ConfigManager: Set CONFIG_DIR and CONFIG_PATH
ConfigManager->>ConfigManager: loadConfig()
loop [config.cfg exists]
ConfigManager->>FileUtil: readFile(CONFIG_PATH)
FileUtil-->>ConfigManager: JSON content
ConfigManager->>Gson: fromJson(json, Config.class)
Gson-->>ConfigManager: Config object
ConfigManager->>ConfigManager: new Config() with defaults
ConfigManager->>ConfigManager: saveConfig(defaultConfig)
ConfigManager->>ConfigManager: Assign to static config field
note over JVM Class Loader,Gson: CacheManager Static Initialization
JVM Class Loader->>CacheManager: Load CacheManager class
CacheManager->>CacheManager: Initialize Gson (line 16)
CacheManager->>CacheManager: Initialize CACHE_PATH (line 15)
CacheManager->>FileUtil: getLocalStoragePath()
FileUtil-->>CacheManager: Platform-specific path
CacheManager->>CacheManager: loadCache() (line 17)
CacheManager->>CacheManager: Read file via Files.readAllBytes
CacheManager->>Gson: fromJson(json, Cache.class)
Gson-->>CacheManager: Cache object
CacheManager->>CacheManager: new Cache() with defaults
end
CacheManager->>CacheManager: Assign to static cache field
note over JVM Class Loader,Gson: Both managers ready for use
```
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L18-L29](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L18-L29)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L15-L17](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L15-L17)
### Access Patterns
Once initialized, both managers are accessed statically throughout the application:
**Configuration Access:**
```
// Direct field access
String language = ConfigManager.config.lang;
boolean darkMode = ConfigManager.config.enableDarkMode;
int repeatCount = ConfigManager.config.repeatTime;
```
**Cache Access:**
```
// Direct field access
String lastDir = CacheManager.cache.lastLoadDirectory;
String defaultOp = CacheManager.cache.defaultCloseOperation;
// Persistence
CacheManager.cache.lastSaveDirectory = "/path/to/dir";
CacheManager.saveCache();
```
Configuration access pattern appears in [SettingsDialog.java L11](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L11-L11)
and [MainFrame](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame)
while cache access pattern appears in [ExitDialog.java L83-L88](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ExitDialog.java#L83-L88)
**Sources:**
* [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L1-L180](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L1-L180)
* [src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java L81-L100](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java#L81-L100)
---
## System Integration
The configuration system integrates with the operating system through the `followSystemSettings` flag, enabling automatic synchronization with OS preferences.
### System Settings Synchronization
When `config.followSystemSettings` is `true`, the application queries the OS for:
1. **System Language:** Via `SystemUtil.getSystemLang(availableLangs)`
2. **Dark Mode Preference:** Via `SystemUtil.isSystemDarkMode()`
This synchronization occurs in the `SettingsDialog` [SettingsDialog.java L154-L168](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L154-L168)
:
```mermaid
flowchart TD
FollowSys["config.followSystemSettings"]
SysUtil["SystemUtil"]
GetLang["getSystemLang()"]
GetDark["isSystemDarkMode()"]
OSLang["System Language
Locale"]
OSDark["Windows Registry
AppsUseLightTheme"]
LangCombo["langCombo
Disabled when following"]
DarkBox["darkModeBox
Disabled when following"]
FollowSys --> SysUtil
GetLang --> OSLang
GetDark --> OSDark
OSLang --> LangCombo
OSDark --> DarkBox
subgraph subGraph3 ["UI State"]
LangCombo
DarkBox
end
subgraph OS ["OS"]
OSLang
OSDark
end
subgraph subGraph1 ["System Queries"]
SysUtil
GetLang
GetDark
SysUtil --> GetLang
SysUtil --> GetDark
end
subgraph Configuration ["Configuration"]
FollowSys
end
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L154-L168](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L154-L168)
### ItemListener Implementation
The synchronization logic is implemented through an `ItemListener` attached to the "Follow System Settings" checkbox:
**Key behaviors:**
* When checked: Disables manual controls and queries system settings
* When unchecked: Re-enables manual controls, preserving last user selections
* Initial load: Executes once during dialog construction [SettingsDialog.java L168](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L168-L168)
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L154-L168](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L154-L168)
---
## Language Discovery
The `ConfigManager.getAvailableLangs()` method [ConfigManager.java L69-L114](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ConfigManager.java#L69-L114)
detects available language files for the language selector in `SettingsDialog`. It handles two runtime environments:
### Environment Detection Flow
```mermaid
flowchart TD
Start["getAvailableLangs()"]
CheckDevMode["Localizer.isDevMode()"]
DevPath["Read lang/ directory
from filesystem
(lines 72-81)"]
DevList["FileUtil.listFileNames('lang')"]
DevFilter["Filter *.json files
Remove .json extension"]
CheckProtocol["Check resource protocol"]
JarPath["JAR protocol
(lines 85-96)"]
FilePath["file protocol
(lines 97-109)"]
JarEnum["Enumerate JAR entries
Filter lang/*.json"]
FileList["List directory
Filter *.json"]
Return["Return String[] of lang codes"]
Start --> CheckDevMode
CheckDevMode --> DevPath
CheckDevMode --> CheckProtocol
DevPath --> DevList
DevList --> DevFilter
DevFilter --> Return
CheckProtocol --> JarPath
CheckProtocol --> FilePath
JarPath --> JarEnum
FilePath --> FileList
JarEnum --> Return
FileList --> Return
```
**Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L69-L114](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L69-L114)
### Discovery Scenarios
| Scenario | Detection Method | Implementation |
| --- | --- | --- |
| Development mode | File system access to `lang/` directory | `FileUtil.listFileNames("lang")` [line 73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/line 73) |
| JAR deployment | Enumerate JAR entries matching `lang/*.json` | `JarFile.entries()` iteration [lines 86-96](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/lines 86-96) |
| file:// protocol | URI-based file listing | `File.listFiles()` with filter [lines 99-109](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/lines 99-109) |
All methods strip the `.json` extension to return language codes (e.g., `"en_us"`, `"zh_cn"`).
**Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L69-L114](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L69-L114)
---
## Usage Patterns by Component
Different UI components interact with the persistence system based on their responsibilities:
### SettingsDialog Usage
`SettingsDialog` reads and writes configuration settings [SettingsDialog.java L1-L180](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L1-L180)
:
**Read Pattern:**
```javascript
import static io.github.samera2022.mouse_macros.manager.ConfigManager.config;
// Initialize UI from config
langCombo.setSelectedItem(config.lang);
darkModeBox.setSelected(config.enableDarkMode);
followSystemBox.setSelected(config.followSystemSettings);
```
**Write Pattern:**
```
// Modify in-memory config
config.lang = (String) langCombo.getSelectedItem();
config.enableDarkMode = darkModeBox.isSelected();
config.followSystemSettings = followSystemBox.isSelected();
// Persist changes
ConfigManager.saveConfig(config);
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L1-L180](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L1-L180)
### ExitDialog Usage
`ExitDialog` uses `CacheManager` to persist exit preferences [ExitDialog.java L81-L100](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ExitDialog.java#L81-L100)
:
**Cache Write Pattern:**
```
String op = "";
if (exitOnCloseRadio.isSelected()) op = CacheManager.EXIT_ON_CLOSE;
if (minimizeToTrayRadio.isSelected()) op = CacheManager.MINIMIZE_TO_TRAY;
if (rememberOptionBox.isSelected()) {
CacheManager.cache.defaultCloseOperation = op;
CacheManager.saveCache();
}
switch (op) {
case CacheManager.EXIT_ON_CLOSE:
System.exit(0);
break;
case CacheManager.MINIMIZE_TO_TRAY:
mf.minimizeToTray();
break;
}
```
The cache constants are defined in [CacheManager.java L19-L21](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/CacheManager.java#L19-L21)
:
| Constant | Value | Purpose |
| --- | --- | --- |
| `EXIT_ON_CLOSE` | `"exit_on_close"` | Application exits when closed |
| `MINIMIZE_TO_TRAY` | `"minimize_to_tray"` | Application minimizes to system tray when closed |
| `UNKNOWN` | `""` (empty) | No default close behavior set |
**Sources:**
* [src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java L81-L100](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/ExitDialog.java#L81-L100)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L19-L21](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L19-L21)
### MacroManager Usage
`MacroManager` reads configuration settings for playback behavior:
**Read Pattern:**
```
// Check execution settings
boolean quickMode = ConfigManager.config.enableQuickMode;
int repeatCount = ConfigManager.config.repeatTime;
double repeatDelay = ConfigManager.config.repeatDelay;
// Check storage settings
boolean useDefaultPath = ConfigManager.config.enableDefaultStorage;
String defaultPath = ConfigManager.config.defaultMmcStoragePath;
```
**Sources:** [src/io/github/samera2022/mouse_macros/manager/MacroManager.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/MacroManager.java)
---
## Configuration Constants
`ConfigManager` defines constants for the `readjustFrameMode` setting [ConfigManager.java L21-L23](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/ConfigManager.java#L21-L23)
:
| Constant | Value | Purpose |
| --- | --- | --- |
| `RFM_MIXED` | `"MIXED"` | Use memorized sizes when available, otherwise use standardized sizes |
| `RFM_STANDARDIZED` | `"STANDARDIZED"` | Always calculate standardized window sizes based on content |
| `RFM_MEMORIZED` | `"MEMORIZED"` | Always use memorized window sizes from `CacheManager` |
`CacheManager` defines constants for exit behavior [CacheManager.java L19-L21](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/CacheManager.java#L19-L21)
:
| Constant | Value | Purpose |
| --- | --- | --- |
| `EXIT_ON_CLOSE` | `"exit_on_close"` | Application exits when main window is closed |
| `MINIMIZE_TO_TRAY` | `"minimize_to_tray"` | Application minimizes to system tray when closed |
| `UNKNOWN` | `""` (empty) | No default close behavior configured |
These constants are used throughout the application to maintain consistency in configuration values.
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L21-L23](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L21-L23)
* [src/io/github/samera2022/mouse_macros/manager/CacheManager.java L19-L21](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/CacheManager.java#L19-L21)
---
## Summary
The Configuration System provides:
1. **Static Initialization:** Configuration loaded before application code executes
2. **Two-Tier Persistence:** Separate files for application settings (`config.cfg`) and UI state (`cache.json`)
3. **System Integration:** Optional synchronization with OS language and dark mode settings
4. **Environment Awareness:** Supports both development and JAR-packaged execution
5. **Simple Access:** Static fields enable straightforward configuration access throughout the codebase
6. **Automatic Defaults:** Missing configuration files trigger creation of defaults with sensible values
For implementation details, see the child pages:
* [ConfigManager](ConfigManager) - Core configuration management logic
* [Configuration Files](Configuration-Files-and-Settings) - File structure and field specifications
* [File Chooser Configuration](CacheManager) - UI state persistence mechanism
**Sources:**
* [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L1-L146](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L1-L146)
* [src/io/github/samera2022/mouse_macros/manager/config/FileChooserConfig.java L1-L28](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/config/FileChooserConfig.java#L1-L28)
* [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L1-L180](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L1-L180)