# Main Window (MainFrame) > **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) ## Purpose and Scope This document details the `MainFrame` class, which serves as the primary application window and main orchestrator for the MouseMacros application. The `MainFrame` is responsible for: * Constructing and managing the main UI layout with control buttons and status log area * Initializing and registering global input hooks via JNativeHook * Coordinating interactions between the macro system, configuration, localization, and theming subsystems * Handling user-triggered actions and hotkey management * Applying system-wide theme settings For information about the macro recording and playback functionality triggered by this window, see page 4 (Macro Recording and Playback System). For configuration management, see page 5.1 (ConfigManager). For theming implementation details, see page 7.5 (Theming System). **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L1-L193](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L1-L193) --- ## Class Structure and Singleton Pattern The `MainFrame` class follows a singleton-like pattern with a public static instance: ``` public static final MainFrame MAIN_FRAME = new MainFrame(); ``` ### Key Members | Member | Type | Purpose | | --- | --- | --- | | `logArea` | `static JTextArea` | Displays status messages throughout the application lifecycle | | `startBtn` | `JButton` | Initiates macro recording | | `stopBtn` | `JButton` | Stops macro recording | | `playBtn` | `JButton` | Executes recorded macro | | `abortBtn` | `JButton` | Aborts currently running macro playback | | `saveBtn` | `JButton` | Saves recorded macro to `.mmc` file | | `loadBtn` | `JButton` | Loads macro from `.mmc` file | | `settingsBtn` | `JButton` | Opens settings dialog | | `macroSettingsBtn` | `JButton` | Opens macro-specific settings dialog | | `GML` | `static GlobalMouseListener` | Singleton listener instance for global input events | | `keyRecord` | `static int` | Native key code for recording hotkey (default: F2) | | `keyStop` | `static int` | Native key code for stop hotkey (default: F3) | | `keyPlay` | `static int` | Native key code for playback hotkey (default: F4) | | `keyAbort` | `static int` | Native key code for abort hotkey (default: F5) | The static `logArea` and `MAIN_FRAME` allow other subsystems (particularly `LogManager`) to access the UI without complex dependency injection. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L28-L39](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L28-L39) --- ## Initialization Sequence The `MainFrame` constructor executes a specific initialization order critical for application functionality: ```mermaid sequenceDiagram participant Constructor participant ConfigManager participant SystemUtil participant Localizer participant UI Components participant GlobalScreen participant ComponentUtil note over Constructor: "Step 1: System Settings Sync" Constructor->>ConfigManager: "config.followSystemSettings?" loop ["followSystemSettings == true"] Constructor->>ConfigManager: "getAvailableLangs()" ConfigManager-->>Constructor: "availableLangs[]" Constructor->>SystemUtil: "getSystemLang(availableLangs)" SystemUtil-->>Constructor: "system language" Constructor->>SystemUtil: "isSystemDarkMode()" SystemUtil-->>Constructor: "dark mode boolean" Constructor->>ConfigManager: "Update config.lang, enableDarkMode" end note over Constructor: "Step 2: Localization" Constructor->>Localizer: "load(config.lang)" Constructor->>Localizer: "setRuntimeSwitch(true)" note over Constructor: "Step 3: Hotkey Configuration" Constructor->>ConfigManager: "Read config.keyMap" Constructor->>Constructor: "Set keyRecord, keyStop, keyPlay, keyAbort" note over Constructor: "Step 4: UI Construction" Constructor->>UI Components: "Create JTextArea logArea" Constructor->>UI Components: "Create JScrollPane with CustomScrollBarUI" Constructor->>UI Components: "Create 8 JButtons" Constructor->>UI Components: "Create GridLayout panels (2 rows)" Constructor->>UI Components: "Add action listeners to buttons" note over Constructor: "Step 5: Window Sizing" Constructor->>ComponentUtil: "adjustFrameWidth(this, buttons...)" note over Constructor: "Step 6: Global Hook Registration" Constructor->>GlobalScreen: "registerNativeHook()" Constructor->>GlobalScreen: "addNativeKeyListener(GML)" Constructor->>GlobalScreen: "addNativeMouseListener(GML)" Constructor->>GlobalScreen: "addNativeMouseWheelListener(GML)" Constructor->>GlobalScreen: "addNativeMouseMotionListener(GML)" note over Constructor: "Step 7: Theme Application" Constructor->>ComponentUtil: "setMode(contentPane, mode)" note over Constructor: "Step 8: Final Layout" Constructor->>Constructor: "pack()" Constructor->>Constructor: "setSize()" ``` ### Step 1: System Settings Synchronization [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L41-L45](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L41-L45) checks if `config.followSystemSettings` is enabled. If so, the system language and dark mode preference are automatically detected and synchronized: * Language detection uses `SystemUtil.getSystemLang(availableLangs)` to match the OS language against available translations * Dark mode detection uses `SystemUtil.isSystemDarkMode()` which queries Windows Registry on Windows systems ### Step 2: Localization Loading [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L47-L50](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L47-L50) initializes the localization system: ``` Localizer.load(config.lang); // Load language file Localizer.setRuntimeSwitch(enableLangSwitch); // Enable runtime language switching ``` ### Step 3: Hotkey Configuration [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L51-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L51-L60) loads custom hotkey mappings from `config.keyMap`. The default values (F2-F5) are overridden if the configuration contains: * `"start_macro"` → `keyRecord` * `"stop_record"` → `keyStop` * `"play_macro"` → `keyPlay` * `"abort_macro_operation"` → `keyAbort` ### Step 4: UI Component Construction [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L68-L112](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L68-L112) constructs the UI hierarchy with a `BorderLayout`: * **CENTER**: `JScrollPane` containing `logArea` with `CustomScrollBarUI` * **SOUTH**: Container with `JSeparator` and button panel ### Step 5: Global Hook Registration [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L132-L140](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L132-L140) registers the global input hook system: ``` GlobalScreen.registerNativeHook(); GlobalScreen.addNativeKeyListener(GML); GlobalScreen.addNativeMouseListener(GML); GlobalScreen.addNativeMouseWheelListener(GML); GlobalScreen.addNativeMouseMotionListener(GML); ``` This critical step enables OS-level input capture for macro recording and hotkey detection. JNativeHook logging is disabled [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L128-L130](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L128-L130) to prevent console spam. ### Step 6: Theme Application [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) applies the configured theme (dark or light mode) to the entire component tree via `ComponentUtil.setMode()`. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L39-L149](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L39-L149) --- ## UI Layout Architecture The main window uses a structured layout hierarchy: ```mermaid flowchart TD MF["MainFrame
(JFrame)"] BL["BorderLayout"] Center["CENTER
Region"] South["SOUTH
Region"] SP["JScrollPane"] LA["logArea
(JTextArea)"] SC["southContainer
(JPanel)"] Sep["JSeparator"] BP["panel
(GridLayout 2x1)"] R1["row1
(FlowLayout)"] R2["row2
(FlowLayout)"] StartBtn["startBtn"] StopBtn["stopBtn"] PlayBtn["playBtn"] AbortBtn["abortBtn"] SaveBtn["saveBtn"] LoadBtn["loadBtn"] SettingsBtn["settingsBtn"] MacroSettingsBtn["macroSettingsBtn"] MF --> BL BL --> Center BL --> South Center --> SP SP --> LA South --> SC SC --> Sep SC --> BP BP --> R1 BP --> R2 R1 --> StartBtn R1 --> StopBtn R1 --> PlayBtn R2 --> AbortBtn R2 --> SaveBtn R2 --> LoadBtn R2 --> SettingsBtn R2 --> MacroSettingsBtn ``` ### Layout Details | Component | Layout Manager | Purpose | | --- | --- | --- | | `MainFrame` | `BorderLayout` | Root container | | `panel` | `GridLayout(2, 1, 5, 5)` | Two-row button container with 5px gaps | | `row1` | `FlowLayout(CENTER, 10, 0)` | First button row with 10px horizontal gap | | `row2` | `FlowLayout(CENTER, 10, 0)` | Second button row with 10px horizontal gap | The button panel includes 5px border padding [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L83](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L83-L83) : ``` panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); // Top and bottom padding ``` ### Dynamic Width Adjustment [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L115](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L115-L115) calls `ComponentUtil.adjustFrameWidth()` to automatically size the window based on button widths: ``` ComponentUtil.adjustFrameWidth(this, startBtn, stopBtn, playBtn, saveBtn, loadBtn, settingsBtn); ``` **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L68-L115](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L68-L115) --- ## Event Handling and Action Listeners Each button connects to specific `MacroManager` operations with guard conditions: ```mermaid flowchart TD StartBtn["startBtn"] StopBtn["stopBtn"] PlayBtn["playBtn"] AbortBtn["abortBtn"] SaveBtn["saveBtn"] LoadBtn["loadBtn"] SettingsBtn["settingsBtn"] MacroSettingsBtn["macroSettingsBtn"] StartRecording["MacroManager
.startRecording()"] StopRecording["MacroManager
.stopRecording()"] Play["MacroManager
.play()"] Abort["MacroManager
.abort()"] SaveToFile["MacroManager
.saveToFile(this)"] LoadFromFile["MacroManager
.loadFromFile(this)"] OpenSettings["new SettingsDialog()
.setVisible(true)"] OpenMacroSettings["new MacroSettingsDialog()
.setVisible(true)"] StartBtn --> StartRecording StopBtn --> StopRecording PlayBtn --> Play AbortBtn --> Abort SaveBtn --> SaveToFile LoadBtn --> LoadFromFile SettingsBtn --> OpenSettings MacroSettingsBtn --> OpenMacroSettings ``` ### Action Listener Implementations [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) defines the action listeners: | Button | Guard Condition | Action | Notes | | --- | --- | --- | --- | | `startBtn` | `!MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | `MacroManager.startRecording()` | Prevents starting if already recording or configuring hotkeys | | `stopBtn` | `MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | `MacroManager.stopRecording()` | Logs error if not recording | | `playBtn` | `!MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog` | `MacroManager.play()` | Prevents playback during recording | | `abortBtn` | `MacroManager.isPlaying() && !HotkeyDialog.inHotKeyDialog` | `MacroManager.abort()` | Logs error if not playing | | `saveBtn` | `!MacroManager.isRecording()` | `MacroManager.saveToFile(this)` | Opens file chooser dialog | | `loadBtn` | `!MacroManager.isRecording()` | `MacroManager.loadFromFile(this)` | Opens file chooser dialog | | `settingsBtn` | None | `new SettingsDialog().setVisible(true)` | Uses `SwingUtilities.invokeLater()` | | `macroSettingsBtn` | None | `new MacroSettingsDialog().setVisible(true)` | Uses `SwingUtilities.invokeLater()` | ### HotkeyDialog Integration The `HotkeyDialog.inHotKeyDialog` flag prevents hotkey actions during hotkey configuration, avoiding conflicts when the user presses F2-F5 to set those keys as custom hotkeys. **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) --- ## Global Hook and Hotkey Management The `MainFrame` manages four customizable hotkeys through static fields: ```mermaid flowchart TD SF["Static Hotkey Fields"] CM["config.keyMap"] GML["GlobalMouseListener"] MM["MacroManager"] KR["keyRecord
=VC_F2"] KS["keyStop
=VC_F3"] KP["keyPlay
=VC_F4"] KA["keyAbort
=VC_F5"] Rec["Record"] Stp["Stop"] Ply["Play"] Abrt["Abort"] SF --> KR SF --> KS SF --> KP SF --> KA CM --> KR CM --> KS CM --> KP CM --> KA KR --> GML KS --> GML KP --> GML KA --> GML GML --> MM MM --> Rec MM --> Stp MM --> Ply MM --> Abrt ``` ### Hotkey Loading [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L51-L60](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L51-L60) loads hotkey mappings from `config.keyMap`: ``` if (config.keyMap != null) { if (config.keyMap.containsKey("start_macro")) { try { keyRecord = Integer.parseInt(config.keyMap.get("start_macro")); } catch (Exception ignored) {} } // ... similar for keyStop, keyPlay, keyAbort } ``` ### GlobalScreen Registration [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L132-L140](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L132-L140) registers the `GlobalMouseListener` instance with JNativeHook: ``` GlobalScreen.registerNativeHook(); GlobalScreen.addNativeKeyListener(GML); GlobalScreen.addNativeMouseListener(GML); GlobalScreen.addNativeMouseWheelListener(GML); GlobalScreen.addNativeMouseMotionListener(GML); ``` The `GlobalMouseListener` receives native events and compares them against `MainFrame.keyRecord`, `MainFrame.keyStop`, etc., to trigger macro operations. See page 4.2 (Global Input Capture) for details. ### Error Handling Hook registration failures are logged [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L132-L136](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L132-L136) : ``` try { GlobalScreen.registerNativeHook(); } catch (Exception e) { log(Localizer.get("hook_registration_failed") + e.getMessage()); } ``` **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L32-L35](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L32-L35), [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L62-L71](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L62-L71), [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L142-L150](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L142-L150) --- ## Localization Integration The `MainFrame` extensively uses `Localizer.get()` to retrieve translated strings for all UI text: ### Initial Text Assignment [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L87-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L87-L98) creates buttons with localized text: ``` startBtn = new JButton(getStartBtnText()); stopBtn = new JButton(getStopBtnText()); playBtn = new JButton(getPlayBtnText()); abortBtn = new JButton(getAbortBtnText()); saveBtn = new JButton(Localizer.get("save_macro")); loadBtn = new JButton(Localizer.get("load_macro")); settingsBtn = new JButton(Localizer.get("settings")); macroSettingsBtn = new JButton(Localizer.get("macro_settings")); ``` ### Dynamic Button Text with Hotkeys [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L171-L174](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L171-L174) defines helper methods that combine localized text with hotkey display: ```java private String getStartBtnText() { return Localizer.get("start_record") + " (" + OtherUtil.getNativeKeyDisplayText(keyRecord) + ")"; } ``` This produces button text like "Start Recording (F2)" with the current hotkey dynamically inserted. ### Runtime Language Switching [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) implements `refreshMainFrameTexts()` to update all UI text after language changes: ``` public void refreshMainFrameTexts() { setTitle(Localizer.get("title")); refreshSpecialTexts(); // Updates buttons with hotkey text saveBtn.setText(Localizer.get("save_macro")); loadBtn.setText(Localizer.get("load_macro")); settingsBtn.setText(Localizer.get("settings")); macroSettingsBtn.setText(Localizer.get("macro_settings")); ComponentUtil.adjustFrameWidth(this, startBtn, stopBtn, playBtn, saveBtn, loadBtn, settingsBtn, abortBtn, macroSettingsBtn); } ``` The final call to `adjustFrameWidth()` ensures the window resizes to accommodate the new text widths in different languages. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L87-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L87-L98), [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L152-L174](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L152-L174) --- ## Theme Application The `MainFrame` applies themes through `ComponentUtil.setMode()` which recursively styles all child components: ### Initial Theme Setup [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L72-L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L72-L73) applies `CustomScrollBarUI` to the log area's scrollbars: ``` scrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI(config.enableDarkMode? OtherConsts.DARK_MODE:OtherConsts.LIGHT_MODE)); scrollPane.getHorizontalScrollBar().setUI(new CustomScrollBarUI(config.enableDarkMode? OtherConsts.DARK_MODE:OtherConsts.LIGHT_MODE)); ``` [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) applies the theme to the entire content pane: ``` ComponentUtil.setMode(getContentPane(), config.enableDarkMode?OtherConsts.DARK_MODE:OtherConsts.LIGHT_MODE); ``` ### Theme Application Flow ```mermaid flowchart TD MFCtor["MainFrame
Constructor"] GCP["getContentPane()"] CU["ComponentUtil
.setMode()"] RS["Recursive
Styling"] Btns["JButtons"] TA["JTextArea
logArea"] Pnls["JPanels"] SBs["JScrollBars"] Sep["JSeparator"] MFCtor --> GCP GCP --> CU CU --> RS RS --> Btns RS --> TA RS --> Pnls RS --> SBs RS --> Sep ``` The `ComponentUtil.setMode()` method handles: * Background and foreground colors for all component types * Special handling for `JScrollPane`, `JPanel`, `JButton`, `JTextField`, `JTextArea`, `JComboBox`, etc. * Application of `CustomScrollBarUI` to scrollbars * Caret color for text components ### Runtime Theme Switching When the user changes the theme in `SettingsDialog`, `ComponentUtil.setMode()` is called again on the main frame, immediately updating all colors without requiring an application restart. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L72-L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L72-L73), [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) --- ## Logging System Integration The static `logArea` field enables system-wide logging through `LogManager`: ```mermaid flowchart TD MM["MacroManager"] GML["GlobalMouseListener"] CM["ConfigManager"] OC["Other
Components"] LM["LogManager
.log(msg)"] SU["SwingUtilities
.invokeLater()"] LA["MainFrame
.logArea"] TA["logArea.append
(msg+newline)"] MM --> LM GML --> LM CM --> LM OC --> LM LM --> SU SU --> LA LA --> TA ``` ### LogManager Implementation The `LogManager` class provides a static logging method: ``` public static void log(String msg) { SwingUtilities.invokeLater(() -> MainFrame.logArea.append(msg + "\n")); } ``` The use of `SwingUtilities.invokeLater()` ensures thread safety when non-EDT threads (like macro playback threads) write log messages. ### Usage Throughout Application Examples of logged messages: * `"Recording started"` when macro recording begins * `"Macro saved successfully"` after file save * `"Hook registration failed: ..."` on JNativeHook errors * `"Macro not recording"` when user clicks Stop without recording All messages are localized via `Localizer.get()` before logging. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L26](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L26-L26) --- ## Window Sizing and Scaling The `MainFrame` applies display scaling adjustments to ensure correct sizing across different DPI settings: ### Final Size Calculation [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) applies window size caching: ``` ComponentUtil.applyWindowSizeCache(this, "title", 430, 330); ``` This method retrieves cached window dimensions from `cache.json` if available, or uses the default dimensions of 430×330 pixels. ### Static Width Adjustment [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L176-L179](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L176-L179) provides a static method for external width adjustments: ``` public static void adjustFrameWidth(){ MAIN_FRAME.pack(); MAIN_FRAME.setSize(MAIN_FRAME.getWidth(), (int) (660/SystemUtil.getScale()[1])); } ``` This is called after language changes to resize the window based on new text widths. The height is dynamically calculated using `SystemUtil.getScale()[1]` to account for display scaling. **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/MainFrame.java L176-L179](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L176-L179) --- ## Dependencies and Subsystem Integration The `MainFrame` serves as the integration point for multiple subsystems: ```mermaid flowchart TD MF["MainFrame"] MM["MacroManager"] GML["GlobalMouseListener"] CM["ConfigManager"] Loc["Localizer"] CU["ComponentUtil"] SU["SystemUtil"] LM["LogManager"] SD["SettingsDialog"] MSD["MacroSettingsDialog"] HD["HotkeyDialog"] JNH["GlobalScreen"] MF --> MM MF --> GML MF --> CM MF --> Loc MF --> CU MF --> SU MF --> LM MF --> SD MF --> MSD MF --> JNH JNH --> GML GML --> MF SD --> HD HD --> MF ``` ### Import Analysis Key imports [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L3-L18](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L3-L18) : | Import | Purpose | | --- | --- | | `com.github.kwhat.jnativehook.*` | JNativeHook library for global input hooks | | `io.github.samera2022.mouse_macros.Localizer` | Translation system | | `io.github.samera2022.mouse_macros.constant.ColorConsts` | Color scheme definitions | | `io.github.samera2022.mouse_macros.constant.OtherConsts` | Mode constants (DARK_MODE, LIGHT_MODE) | | `io.github.samera2022.mouse_macros.listener.GlobalMouseListener` | Global input listener | | `io.github.samera2022.mouse_macros.manager.MacroManager` | Macro operations | | `io.github.samera2022.mouse_macros.manager.ConfigManager` | Configuration access | | `io.github.samera2022.mouse_macros.util.ComponentUtil` | UI theming utilities | | `io.github.samera2022.mouse_macros.util.SystemUtil` | System property detection | | `io.github.samera2022.mouse_macros.manager.LogManager` | Static logging via `log()` | **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L3-L18](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L3-L18) --- ## Key Design Patterns ### Static Singleton Access The `MAIN_FRAME` and `logArea` static fields enable global access without dependency injection: ``` public static final MainFrame MAIN_FRAME = new MainFrame(); public static JTextArea logArea; ``` This allows `LogManager.log()` to append to the log area from any thread. ### Guard Conditions on Actions Action listeners include state checks before executing operations: ``` startBtn.addActionListener(e -> { if ((!MacroManager.isRecording()) && (!HotkeyDialog.inHotKeyDialog)) MacroManager.startRecording(); }); ``` This prevents invalid state transitions and race conditions. ### Lazy Dialog Initialization Settings dialogs are created on-demand rather than during construction: ``` settingsBtn.addActionListener(e -> SwingUtilities.invokeLater(() -> new SettingsDialog().setVisible(true)) ); ``` This improves startup performance and ensures fresh dialog state. ### Recursive Component Theming The theme application uses recursive traversal of the component tree via `ComponentUtil.setMode()`, ensuring all nested components receive consistent styling. **Sources:** [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L28-L39](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L28-L39), [src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L128-L135](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java#L128-L135)