# User Interface Components
> **Relevant source files**
> * [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java)
> * [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java)
## Purpose and Scope
This document provides an overview of the MouseMacros user interface component architecture, including the main window, dialog system, component hierarchy, and user interaction patterns. It covers the structural organization of UI elements and how they interact with the core macro system.
For detailed documentation on specific dialogs, see:
* Settings configuration UI: [Settings Dialog](Settings-Dialog)
* Macro-specific settings: [Macro Settings Dialog](Macro-Settings-Dialog)
* Hotkey configuration interface: [Hotkey Dialog](Exit-Dialog)
* Information dialogs: [About and Update Dialogs](About-and-Update-Information-Dialogs)
* Theme and styling system: [Theming System](Custom-UI-Components)
For information about the main application window's integration with macro recording and playback, see [Main Window (MainFrame)](Main-Window-(MainFrame))).
---
## UI Component Architecture
The MouseMacros UI is built using Java Swing and follows a dialog-based architecture where the `MainFrame` serves as the primary application window, and multiple specialized `JDialog` subclasses provide configuration and information interfaces.
### Component Hierarchy
```mermaid
flowchart TD
JFrame["JFrame"]
JDialog["JDialog"]
MainFrame["MainFrame
(Primary Application Window)"]
SettingsDialog["SettingsDialog
(Application Settings)"]
MacroSettingsDialog["MacroSettingsDialog
(Macro Configuration)"]
HotkeyDialog["HotkeyDialog
(Hotkey Capture)"]
AboutDialog["AboutDialog
(Author Information)"]
UpdateInfoDialog["UpdateInfoDialog
(Version History)"]
JFrame --> MainFrame
JDialog --> SettingsDialog
JDialog --> MacroSettingsDialog
JDialog --> HotkeyDialog
JDialog --> AboutDialog
JDialog --> UpdateInfoDialog
MainFrame --> SettingsDialog
MainFrame --> MacroSettingsDialog
SettingsDialog --> HotkeyDialog
SettingsDialog --> AboutDialog
SettingsDialog --> UpdateInfoDialog
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L1-L180](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L1-L180), [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L1-L220](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L1-L220)
---
## MainFrame Components
The `MainFrame` class is the primary application window and contains the main UI elements for macro operations.
### Main Window Structure
| Component Type | Field Name | Purpose | Location |
| --- | --- | --- | --- |
| `JButton` | `startBtn` | Initiates macro recording | Row 1 |
| `JButton` | `stopBtn` | Stops macro recording | Row 1 |
| `JButton` | `playBtn` | Plays recorded macro | Row 1 |
| `JButton` | `abortBtn` | Emergency abort for running macros | Row 2 |
| `JButton` | `saveBtn` | Saves macro to `.mmc` file | Row 2 |
| `JButton` | `loadBtn` | Loads macro from `.mmc` file | Row 2 |
| `JButton` | `settingsBtn` | Opens `SettingsDialog` | Row 2 |
| `JButton` | `macroSettingsBtn` | Opens `MacroSettingsDialog` | Row 2 |
| `JTextArea` | `logArea` | Displays status messages | Center |
```mermaid
flowchart TD
Row1["row1: FlowLayout
startBtn | stopBtn | playBtn"]
Row2["row2: FlowLayout
abortBtn | saveBtn | loadBtn | settingsBtn | macroSettingsBtn"]
Separator["JSeparator (Horizontal)"]
Center["Center: BorderLayout.CENTER
JScrollPane containing logArea"]
South["South: BorderLayout.SOUTH
southContainer"]
subgraph subGraph2 ["MainFrame Layout"]
Center
South
subgraph southContainer ["southContainer"]
Separator
subgraph ButtonPanel ["ButtonPanel"]
Row1
Row2
end
end
end
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L26-L112](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L26-L112)
### Button Action Listeners
```mermaid
flowchart TD
startBtn["startBtn"]
StartRecording["MacroManager.startRecording()"]
stopBtn["stopBtn"]
StopRecording["MacroManager.stopRecording()"]
playBtn["playBtn"]
Play["MacroManager.play()"]
abortBtn["abortBtn"]
Abort["MacroManager.stopRecording()"]
saveBtn["saveBtn"]
Save["MacroManager.saveToFile(this)"]
loadBtn["loadBtn"]
Load["MacroManager.loadFromFile(this)"]
settingsBtn["settingsBtn"]
OpenSettings["new SettingsDialog().setVisible(true)"]
macroSettingsBtn["macroSettingsBtn"]
OpenMacro["new MacroSettingsDialog().setVisible(true)"]
startBtn --> StartRecording
stopBtn --> StopRecording
playBtn --> Play
abortBtn --> Abort
saveBtn --> Save
loadBtn --> Load
settingsBtn --> OpenSettings
macroSettingsBtn --> OpenMacro
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L118-L125](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L118-L125)
---
## Dialog System Overview
The application uses modal dialogs for all configuration interfaces. Each dialog is a separate `JDialog` subclass that handles its own layout, event handling, and configuration persistence.
### Dialog Invocation Pattern
All dialogs follow a consistent pattern:
1. Dialog is instantiated when user clicks a button
2. Dialog constructor initializes UI components and applies current configuration
3. Dialog is displayed modally (`setModal(true)`)
4. User interactions update local state
5. "Save" button persists changes via `ConfigManager.saveConfig()`
6. Dialog closes and main window refreshes if needed
```mermaid
sequenceDiagram
participant User
participant MainFrame
participant settingsBtn
participant SettingsDialog
participant ConfigManager
participant Localizer
User->>settingsBtn: Click
settingsBtn->>MainFrame: ActionListener triggered
MainFrame->>SettingsDialog: new SettingsDialog()
SettingsDialog->>ConfigManager: Load current config
SettingsDialog->>SettingsDialog: Initialize UI with config values
SettingsDialog->>SettingsDialog: Apply theme via ComponentUtil
MainFrame->>SettingsDialog: setVisible(true)
note over SettingsDialog: User modifies settings
User->>SettingsDialog: Click "Save Settings"
SettingsDialog->>ConfigManager: saveConfig(config)
SettingsDialog->>ConfigManager: reloadConfig()
SettingsDialog->>Localizer: load(config.lang)
SettingsDialog->>MainFrame: refreshMainFrameTexts()
SettingsDialog->>SettingsDialog: dispose()
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L172-L189](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L172-L189), [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L124-L125](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L124-L125)
---
## Configuration Dialogs
### SettingsDialog Structure
The `SettingsDialog` provides a hierarchical configuration interface with conditional visibility for dependent settings.
**Key UI Elements:**
| Component | Field/Variable | Configuration Key | Description |
| --- | --- | --- | --- |
| `JCheckBox` | `followSysBox` | `config.followSystemSettings` | Master toggle for system integration |
| `JComboBox` | `langCombo` | `config.lang` | Language selection (disabled when following system) |
| `JCheckBox` | `darkModeBox` | `config.enableDarkMode` | Dark mode toggle (disabled when following system) |
| `JCheckBox` | `enableDefaultStorageBox` | `config.enableDefaultStorage` | Enable default macro storage path |
| `JTextField` | `pathField` | `config.defaultMmcStoragePath` | Default storage path (disabled unless enabled) |
| `JButton` | `browseBtn` | N/A | Opens directory chooser |
| `JButton` | `hotkeyBtn` | N/A | Opens `HotkeyDialog` |
| `JButton` | `aboutBtn` | N/A | Opens `AboutDialog` |
| `JButton` | `updateInfoBtn` | N/A | Opens `UpdateInfoDialog` |
```mermaid
flowchart TD
EnableStorage["enableDefaultStorageBox: JCheckBox"]
PathField["pathField: JTextField"]
Browse["browseBtn: JButton"]
FollowSys["followSysBox: JCheckBox"]
Lang["langCombo: JComboBox"]
DarkMode["darkModeBox: JCheckBox"]
SettingsDialog["SettingsDialog"]
Hotkey["hotkeyBtn: JButton"]
About["aboutBtn: JButton"]
Update["updateInfoBtn: JButton"]
Save["saveSettingsBtn: JButton"]
HotkeyDialog["new HotkeyDialog()"]
AboutDialog["new AboutDialog()"]
UpdateInfoDialog["new UpdateInfoDialog()"]
Hotkey --> HotkeyDialog
About --> AboutDialog
Update --> UpdateInfoDialog
subgraph subGraph2 ["Action Buttons"]
Hotkey
About
Update
end
subgraph subGraph1 ["Storage Settings"]
EnableStorage
PathField
Browse
EnableStorage --> PathField
EnableStorage --> Browse
end
subgraph subGraph0 ["Main Settings"]
FollowSys
Lang
DarkMode
FollowSys --> Lang
FollowSys --> DarkMode
end
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L43-L168](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L43-L168)
### MacroSettingsDialog Structure
The `MacroSettingsDialog` provides macro-specific configuration options that override default behavior when enabled.
**Key UI Elements:**
| Component | Purpose | Configuration Key |
| --- | --- | --- |
| `JCheckBox` (custom settings) | Enable custom macro settings | `config.enableCustomMacroSettings` |
| `JSpinner` (repeat count) | Number of times to repeat macro | `config.repeatTime` |
**Sources:** Referenced in [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L98-L98)
---
## Event Flow and State Management
### MainFrame Initialization Sequence
```mermaid
sequenceDiagram
participant MainFrame()
participant ConfigManager
participant SystemUtil
participant Localizer
participant JNativeHook GlobalScreen
participant ComponentUtil
participant CacheManager
MainFrame()->>ConfigManager: Check config.followSystemSettings
loop [followSystemSettings == true]
MainFrame()->>ConfigManager: getAvailableLangs()
MainFrame()->>SystemUtil: getSystemLang(availableLangs)
MainFrame()->>SystemUtil: isSystemDarkMode()
MainFrame()->>ConfigManager: Update config.lang and config.enableDarkMode
end
MainFrame()->>Localizer: load(config.lang)
MainFrame()->>Localizer: setRuntimeSwitch(true)
MainFrame()->>ConfigManager: Load keyMap (hotkeys)
note over MainFrame(): Initialize keyRecord, keyStop, keyPlay, keyAbort
MainFrame()->>MainFrame(): Create logArea (JTextArea)
MainFrame()->>MainFrame(): Create buttons (JButton)
MainFrame()->>MainFrame(): Attach action listeners
MainFrame()->>MainFrame(): Set up layout (BorderLayout)
MainFrame()->>JNativeHook GlobalScreen: registerNativeHook()
MainFrame()->>JNativeHook GlobalScreen: addNativeKeyListener(GML)
MainFrame()->>JNativeHook GlobalScreen: addNativeMouseListener(GML)
MainFrame()->>JNativeHook GlobalScreen: addNativeMouseWheelListener(GML)
MainFrame()->>JNativeHook GlobalScreen: addNativeMouseMotionListener(GML)
MainFrame()->>ComponentUtil: setMode(getContentPane(), theme)
MainFrame()->>ComponentUtil: applyWindowSizeCache(this, "title", 430, 330)
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L39-L148](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L39-L148)
### Button State Management
The MainFrame implements guard conditions to prevent invalid state transitions:
**Recording Guards:**
| Button | Condition | Action | Guard Logic |
| --- | --- | --- | --- |
| `startBtn` | `!MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | Start recording | [MainFrame.java L118](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L118-L118) |
| `stopBtn` | `MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | Stop recording | [MainFrame.java L119](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L119-L119) |
| `playBtn` | `!MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | Play macro | [MainFrame.java L120](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L120-L120) |
| `abortBtn` | `MacroManager.isPlaying() && !HotkeyDialog.inHotKeyDialog` | Abort playback | [MainFrame.java L121](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L121-L121) |
| `saveBtn` | `!MacroManager.isRecording()` | Save to file | [MainFrame.java L122](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L122-L122) |
| `loadBtn` | `!MacroManager.isRecording()` | Load from file | [MainFrame.java L123](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L123-L123) |
The `HotkeyDialog.inHotKeyDialog` flag prevents hotkey conflicts when the user is configuring hotkeys.
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L118-L123](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L118-L123)
---
## Cross-Cutting UI Concerns
### Localization Integration
All UI components support runtime language switching through the `Localizer` class.
**MainFrame Localization:**
```mermaid
flowchart TD
Localizer["Localizer.get(key)"]
Title["setTitle(Localizer.get('title'))"]
StartBtn["startBtn text with hotkey"]
StopBtn["stopBtn text with hotkey"]
PlayBtn["playBtn text with hotkey"]
AbortBtn["abortBtn text with hotkey"]
SaveBtn["saveBtn text"]
LoadBtn["loadBtn text"]
SettingsBtn["settingsBtn text"]
MacroBtn["macroSettingsBtn text"]
Localizer --> Title
Localizer --> StartBtn
Localizer --> StopBtn
Localizer --> PlayBtn
Localizer --> AbortBtn
Localizer --> SaveBtn
Localizer --> LoadBtn
Localizer --> SettingsBtn
Localizer --> MacroBtn
```
The `refreshMainFrameTexts()` method reapplies all localized strings after a language change:
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L152-L162](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L152-L162)
### Theming Integration
All UI components apply theming through `ComponentUtil.setMode()` which accepts a theme constant (`OtherConsts.DARK_MODE` or `OtherConsts.LIGHT_MODE`).
**Theming Application Points:**
| Component | Theme Application | Line Reference |
| --- | --- | --- |
| `MainFrame` | On construction | [MainFrame.java L142](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L142-L142) |
| `MainFrame` logArea scrollbar | On construction | [MainFrame.java L72-L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L72-L73) |
| `SettingsDialog` | On construction | [SettingsDialog.java L215](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L215-L215) |
| `SettingsDialog` | On save | [SettingsDialog.java L186-L187](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L186-L187) |
**Custom Components:**
* `CustomScrollBarUI`: Custom scrollbar rendering for themed appearance [MainFrame.java L72-L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L72-L73)
* Color scheme provided by `ColorConsts` class
For detailed theme implementation, see [Theming System](Custom-UI-Components).
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L142](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L142-L142), [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L186-L187](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L186-L187)
### Window Size Persistence
All dialogs and the main frame use `ComponentUtil.applyWindowSizeCache()` to remember and restore window dimensions across sessions.
**Cached Windows:**
| Window | Cache Key | Default Size (W×H) | Code Reference |
| --- | --- | --- | --- |
| `MainFrame` | `"title"` | 430×330 | [MainFrame.java L144](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/MainFrame.java#L144-L144) |
| `SettingsDialog` | `"settings"` | 521×359 | [SettingsDialog.java L216](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/SettingsDialog.java#L216-L216) |
Cache data is persisted via `CacheManager` to `cache.json`. For details, see [CacheManager](CacheManager).
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L144](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L144-L144), [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L216](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L216-L216)
---
## Window Lifecycle Management
### WindowClosingAdapter
The `WindowClosingAdapter` is attached to all top-level windows to ensure proper cleanup and state persistence on close.
```mermaid
flowchart TD
Window["Window (JFrame/JDialog)"]
Adapter["WindowClosingAdapter"]
WindowEvent["windowClosing(WindowEvent)"]
CacheManager["CacheManager"]
SizeCache["SizeCache.add(name, width, height)"]
SaveCache["CacheManager.saveCache()"]
Window --> Adapter
Adapter --> WindowEvent
WindowEvent --> SizeCache
SizeCache --> SaveCache
```
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L147](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L147-L147), [src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L218](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java#L218-L218)
### Dynamic Width Adjustment
`MainFrame` dynamically adjusts its width to accommodate button labels, which vary based on:
1. Selected language (text length varies)
2. Hotkey assignments (displayed in parentheses)
**Adjustment Logic:**
```mermaid
flowchart TD
RefreshTexts["refreshMainFrameTexts()"]
UpdateLabels["Update button texts with hotkeys"]
AdjustWidth["ComponentUtil.adjustFrameWidth(...)"]
Pack["MAIN_FRAME.pack()"]
Resize["setSize(width, scaled_height)"]
RefreshTexts --> UpdateLabels
UpdateLabels --> AdjustWidth
AdjustWidth --> Pack
Pack --> Resize
```
The `adjustFrameWidth()` method measures button preferred sizes and ensures all buttons fit horizontally.
**Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L161-L179](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L161-L179)
---
## Summary
The MouseMacros UI architecture follows these key patterns:
1. **Single Main Window:** `MainFrame` is the persistent primary window
2. **Modal Dialogs:** Configuration via modal `JDialog` subclasses
3. **Centralized Theming:** All components styled via `ComponentUtil.setMode()`
4. **Runtime Localization:** Language switching without restart via `Localizer`
5. **State Persistence:** Window sizes and directory paths cached via `CacheManager`
6. **Guard Conditions:** Button handlers check state before executing actions
7. **Event-Driven Updates:** Configuration changes propagate via explicit refresh methods
For implementation details of specific dialogs, see the sub-pages listed at the beginning of this document.