# Macro Settings Dialog > **Relevant source files** > * [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java) ## Purpose and Scope The Macro Settings Dialog provides a user interface for configuring custom macro playback behavior, specifically the ability to enable custom settings and define how many times a recorded macro should repeat during playback. This dialog is accessed from the main application window and persists its configuration to `config.cfg`. For general application settings (language, dark mode, default storage paths), see [Settings Dialog](Settings-Dialog). For hotkey configuration, see [Hotkey Dialog](Exit-Dialog). For the underlying configuration persistence mechanism, see [ConfigManager](ConfigManager). **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L1-L138](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L1-L138) --- ## Class Overview The `MacroSettingsDialog` class extends `JDialog` and is implemented in [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L16](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L16-L16) ### Key Characteristics | Property | Value | Purpose | | --- | --- | --- | | Modal | `true` | Blocks interaction with parent window until closed | | Window Name | `"macro_settings"` | Used for window size caching | | Layout | `BorderLayout` | Main layout with 10px gaps | | Icon | `IconConsts.CHECK_BOX` | Custom checkbox icons for consistent theming | **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L18-L26](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L18-L26) --- ## UI Component Hierarchy The dialog follows a hierarchical structure with a title section, main content panel with indented sub-settings, and bottom action panel. ```mermaid flowchart TD Dialog["MacroSettingsDialog
(JDialog)"] ContentPanel["content
(JPanel with BoxLayout.Y_AXIS)"] Title["macroSettingsTitle
(JLabel - 18pt Bold)"] Separator1["JSeparator"] EnablePanel["enableCustomSettingsPanel
(FlowLayout.LEFT)"] EnableLabel["enableCustomSettingsLabel
(JLabel)"] EnableCheckbox["enableCustomSettingsBox
(JCheckBox)"] SubPanel["subSettingsPanel
(BoxLayout.Y_AXIS, 32px left indent)"] RepeatTimesPanel["repeatTimesPanel
(FlowLayout.LEFT)"] RepeatTimesLabel["repeatTimesLabel
(JLabel)"] RepeatTimesField["repeatTimesField
(JTextField, 7 columns)"] RepeatDelayPanel["repeatDelayPanel
(FlowLayout.LEFT)"] RepeatDelayLabel["repeatDelayLabel
(JLabel)"] RepeatDelayField["repeatDelayField
(JTextField, 7 columns)"] SavePanelContainer["savePanel
(FlowLayout.CENTER)"] SaveButton["saveSettingsBtn
(JButton)"] Dialog --> ContentPanel Dialog --> SavePanelContainer subgraph BorderLayout.SOUTH ["BorderLayout.SOUTH"] SavePanelContainer SaveButton SavePanelContainer --> SaveButton end subgraph BorderLayout.CENTER ["BorderLayout.CENTER"] ContentPanel Title Separator1 EnablePanel EnableLabel EnableCheckbox SubPanel RepeatTimesPanel RepeatTimesLabel RepeatTimesField RepeatDelayPanel RepeatDelayLabel RepeatDelayField ContentPanel --> Title ContentPanel --> Separator1 ContentPanel --> EnablePanel ContentPanel --> SubPanel EnablePanel --> EnableLabel EnablePanel --> EnableCheckbox SubPanel --> RepeatTimesPanel SubPanel --> RepeatDelayPanel RepeatTimesPanel --> RepeatTimesLabel RepeatTimesPanel --> RepeatTimesField RepeatDelayPanel --> RepeatDelayLabel RepeatDelayPanel --> RepeatDelayField end ``` **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L24-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L24-L98) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L124-L126](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L124-L126) --- ## Configuration Options The dialog exposes three interconnected configuration options from the `config` object: ### Enable Custom Macro Settings | Field | Type | Config Path | Default State | | --- | --- | --- | --- | | Checkbox | `JCheckBox` | `config.enableCustomMacroSettings` | Read from config | | Localization Key | String | `"macro_settings.enable_custom_macro_settings"` | - | When this checkbox is **disabled**, both text fields become non-editable and default to `repeatTime = 1` and `repeatDelay = 0`. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L37-L43](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L37-L43) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L106](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L106-L106) ### Repeat Count | Field | Type | Config Path | Validation Rules | | --- | --- | --- | --- | | Text Field | `JTextField` | `config.repeatTime` | Positive integers, -1, or empty | | Columns | 7 | - | Sufficient for 10-digit integers | | Localization Key | String | `"macro_settings.repeat_times"` | - | The repeat count determines how many times the `MacroManager` will execute the recorded action sequence during playback. A value of `-1` represents infinite repetition. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L55-L68](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L55-L68) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L108](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L108-L108) ### Repeat Delay | Field | Type | Config Path | Validation Rules | | --- | --- | --- | --- | | Text Field | `JTextField` | `config.repeatDelay` | Non-negative numbers with up to 3 decimal places | | Columns | 7 | - | Sufficient for decimal values | | Localization Key | String | `"macro_settings.repeat_delay"` | - | The repeat delay specifies the time in seconds to wait between each repetition of the macro. This delay is applied after completing one full execution of the action sequence before starting the next repetition. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L70-L80](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L70-L80) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L115](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L115-L115) --- ## Input Validation System Both text fields implement strict input validation using `DocumentFilter` instances to prevent invalid data entry at the keystroke level. ### Repeat Times Field Validation The `repeatTimesField` uses a custom `DocumentInputFilter` that validates integer input: ```mermaid flowchart TD Input["User Input"] Filter["DocumentInputFilter
isValidContent()"] Check1["Is '-1'?"] Check2["Matches \d+
(positive int)?"] Check3["Is empty string?"] Check4["Is single '-'?"] Accept["Input Accepted"] Reject["Input Rejected"] Input --> Filter Filter --> Check1 Check1 --> Accept Check1 --> Check2 Check2 --> Accept Check2 --> Check3 Check3 --> Accept Check3 --> Check4 Check4 --> Accept Check4 --> Reject ``` **Validation Pattern**: `text.equals("-1") || text.matches("\\d+") || text.isEmpty() || text.equals("-")` **Special Cases**: * **`-1`**: Allowed as a special value for infinite repetition * **Single `"-"`**: Allowed temporarily to facilitate typing `-1` * **Empty string**: Allowed to clear the field * **Positive integers**: Any sequence of digits **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L62-L68](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L62-L68) ### Repeat Delay Field Validation The `repeatDelayField` uses a custom `DocumentInputFilter` that validates decimal number input: ```mermaid flowchart TD Input["User Input"] Filter["DocumentInputFilter
isValidContent()"] Check1["Matches \d*\.\d{0,3}
(decimal with up to 3 places)?"] Check2["Is empty string?"] Accept["Input Accepted"] Reject["Input Rejected"] Input --> Filter Filter --> Check1 Check1 --> Accept Check1 --> Check2 Check2 --> Accept Check2 --> Reject ``` **Validation Pattern**: `text.matches("\\d*(\\.\\d{0,3})?") || text.isEmpty()` **Allowed Values**: * **Integers**: `0`, `1`, `123` * **Decimals**: `0.5`, `1.234`, `10.1` * **Partial input**: `.`, `1.`, `1.2` (facilitates typing) * **Empty string**: Allowed to clear the field * **Maximum precision**: 3 decimal places **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L74-L80](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L74-L80) ### DocumentInputFilter Implementation Both fields use the `DocumentInputFilter` class from [io.github.samera2022.mouse_macros.filter.DocumentInputFilter 1](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/io.github.samera2022.mouse_macros.filter.DocumentInputFilter#L1-LNaN) which extends `AbstractDocument.DocumentFilter`. The filter intercepts all text modification operations and validates the resulting string before allowing the change. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L62-L80](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L62-L80) --- ## State Linkage and Event Handling The dialog implements reactive state management where both text fields' enabled states follow the checkbox state. ```mermaid sequenceDiagram participant User participant enableCustomSettingsBox participant followSysListener participant repeatTimesField participant repeatDelayField note over enableCustomSettingsBox,repeatDelayField: Initial State Setup enableCustomSettingsBox->>followSysListener: addItemListener(followSysListener) followSysListener->>followSysListener: itemStateChanged(null) followSysListener->>enableCustomSettingsBox: isSelected()? loop [Enabled] followSysListener->>repeatTimesField: setEnabled(true) followSysListener->>repeatDelayField: setEnabled(true) followSysListener->>repeatTimesField: setEnabled(false) followSysListener->>repeatTimesField: setText("1") followSysListener->>repeatDelayField: setEnabled(false) followSysListener->>repeatDelayField: setText("0") note over User,repeatDelayField: User Interaction User->>enableCustomSettingsBox: Toggle checkbox enableCustomSettingsBox->>followSysListener: itemStateChanged(event) followSysListener->>enableCustomSettingsBox: isSelected()? followSysListener->>repeatTimesField: setEnabled(true) followSysListener->>repeatDelayField: setEnabled(true) followSysListener->>repeatTimesField: setEnabled(false) followSysListener->>repeatTimesField: setText("1") followSysListener->>repeatDelayField: setEnabled(false) followSysListener->>repeatDelayField: setText("0") end ``` ### Implementation The linkage is implemented via an `ItemListener` attached to the checkbox that controls both text fields: | Action | Checkbox State | repeatTimesField | repeatDelayField | | --- | --- | --- | --- | | Enable | Selected | `setEnabled(true)` | `setEnabled(true)` | | Disable | Not Selected | `setEnabled(false)`, `setText("1")` | `setEnabled(false)`, `setText("0")` | The listener is invoked immediately after registration with `itemStateChanged(null)` to establish the initial state based on the loaded configuration. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L128-L138](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L128-L138) --- ## Save Operation and Data Flow When the user clicks the save button, the dialog validates input from both fields, updates the configuration object, persists to disk, and closes. ```mermaid sequenceDiagram participant User participant saveSettingsBtn participant MacroSettingsDialog participant config object participant ConfigManager participant config.cfg User->>saveSettingsBtn: Click "Save Settings" saveSettingsBtn->>MacroSettingsDialog: ActionListener triggered MacroSettingsDialog->>MacroSettingsDialog: text = repeatTimesField.getText() MacroSettingsDialog->>MacroSettingsDialog: delayText = repeatDelayField.getText() loop [Parse successful] MacroSettingsDialog->>config object: config.enableCustomMacroSettings = checkbox.isSelected() MacroSettingsDialog->>config object: config.repeatTime = Integer.parseInt(text) MacroSettingsDialog->>MacroSettingsDialog: printStackTrace() MacroSettingsDialog->>config object: (value unchanged) MacroSettingsDialog->>MacroSettingsDialog: config.repeatDelay = Double.parseDouble(delayText) end MacroSettingsDialog->>ConfigManager: printStackTrace() ConfigManager->>config.cfg: (value unchanged) MacroSettingsDialog->>ConfigManager: saveConfig(config) ConfigManager->>config.cfg: Write JSON to config.cfg ConfigManager->>config object: reloadConfig() MacroSettingsDialog->>MacroSettingsDialog: Read config.cfg note over MacroSettingsDialog: Window closes ``` ### Error Handling | Scenario | Behavior | Code Reference | | --- | --- | --- | | Empty repeatTimes field | repeatTime not updated, no error | [MacroSettingsDialog.java L105](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MacroSettingsDialog.java#L105-L105) | | Empty repeatDelay field | repeatDelay not updated, no error | [MacroSettingsDialog.java L113](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MacroSettingsDialog.java#L113-L113) | | Invalid integer format (repeatTime) | Exception printed, value unchanged | [MacroSettingsDialog.java L109-L111](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MacroSettingsDialog.java#L109-L111) | | Invalid decimal format (repeatDelay) | Exception printed, value unchanged | [MacroSettingsDialog.java L116-L118](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MacroSettingsDialog.java#L116-L118) | | Valid input | Save and reload config | [MacroSettingsDialog.java L120-L122](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MacroSettingsDialog.java#L120-L122) | **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L102-L123](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L102-L123) --- ## Integration Points ### Configuration Manager The dialog reads and writes to the global `config` object via `ConfigManager`: | Operation | Method | Purpose | | --- | --- | --- | | Read | `config.enableCustomMacroSettings` | Initialize checkbox state | | Read | `config.repeatTime` | Initialize repeatTimes text field | | Read | `config.repeatDelay` | Initialize repeatDelay text field | | Write | `ConfigManager.saveConfig(config)` | Persist changes to disk | | Reload | `ConfigManager.reloadConfig()` | Refresh in-memory config | **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L15](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L15-L15) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L40](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L40-L40) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L56](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L56-L56) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L71](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L71-L71) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L120-L121](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L120-L121) ### Localization All user-facing strings are externalized using the `Localizer` service: | UI Element | Translation Key | | --- | --- | | Dialog title | `"macro_settings"` | | Main title label | `"macro_settings"` | | Enable checkbox label | `"macro_settings.enable_custom_macro_settings"` | | Repeat times label | `"macro_settings.repeat_times"` | | Repeat delay label | `"macro_settings.repeat_delay"` | | Save button | `"macro_settings.save_settings"` | **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L20](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L20-L20) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L30](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L30-L30) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L38](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L38-L38) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L55](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L55-L55) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L70](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L70-L70) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L101](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L101-L101) ### Theming System The dialog applies the current theme (dark/light mode) via `ComponentUtil.setMode()`: ``` ComponentUtil.setMode(getContentPane(), config.enableDarkMode ? OtherConsts.DARK_MODE : OtherConsts.LIGHT_MODE); ``` The `IconConsts.CHECK_BOX` provides themed checkbox icons that adapt to the current color scheme. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L142](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L142-L142) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L39](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L39-L39) ### Window Size Caching The dialog's dimensions are persisted and restored via `ComponentUtil.adjustFrameWithCache()`, which calculates optimal window dimensions based on component content and applies cached sizes when available: | Parameter | Value | Purpose | | --- | --- | --- | | Window Name | `"macro_settings"` | Set via `setName()`, used for cache lookup | | Default Height | 170 px | Base height for calculation | | Component Arrays | 4 arrays | Title, main panel, sub-panel, save button | The method analyzes the localized text width of each component array to determine the optimal window width, then applies or caches the result. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L21](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L21-L21) [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L143-L148](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L143-L148) ### Window Lifecycle The dialog uses `WindowClosingAdapter` to handle window close events, which saves the window size to cache before disposal. **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L150](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L150-L150) --- ## Usage Context The Macro Settings Dialog is opened from the `MainFrame` via a dedicated button. The settings configured here affect how the `MacroManager` executes playback: * When `enableCustomMacroSettings` is `true` and `repeatTime > 1`, the macro will execute the recorded actions multiple times in sequence * When `enableCustomMacroSettings` is `false`, the macro executes once (equivalent to `repeatTime = 1`) For details on how these settings are consumed during macro playback, see [MacroManager](MacroManager). **Sources**: [src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java L1-L138](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MacroSettingsDialog.java#L1-L138)