# 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.