-
Notifications
You must be signed in to change notification settings - Fork 0
User Interface Components
Relevant source files
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
- Macro-specific settings: Macro Settings Dialog
- Hotkey configuration interface: Hotkey Dialog
- Information dialogs: About and Update Dialogs
- Theme and styling system: Theming System
For information about the main application window's integration with macro recording and playback, see Main Window (MainFrame)).
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.
flowchart TD
JFrame["JFrame"]
JDialog["JDialog"]
MainFrame["MainFrame<br>(Primary Application Window)"]
SettingsDialog["SettingsDialog<br>(Application Settings)"]
MacroSettingsDialog["MacroSettingsDialog<br>(Macro Configuration)"]
HotkeyDialog["HotkeyDialog<br>(Hotkey Capture)"]
AboutDialog["AboutDialog<br>(Author Information)"]
UpdateInfoDialog["UpdateInfoDialog<br>(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, src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L1-L220
The MainFrame class is the primary application window and contains the main UI elements for macro operations.
| 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 |
flowchart TD
Row1["row1: FlowLayout<br>startBtn | stopBtn | playBtn"]
Row2["row2: FlowLayout<br>abortBtn | saveBtn | loadBtn | settingsBtn | macroSettingsBtn"]
Separator["JSeparator (Horizontal)"]
Center["Center: BorderLayout.CENTER<br>JScrollPane containing logArea"]
South["South: BorderLayout.SOUTH<br>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
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
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.
All dialogs follow a consistent pattern:
- Dialog is instantiated when user clicks a button
- Dialog constructor initializes UI components and applies current configuration
- Dialog is displayed modally (
setModal(true)) - User interactions update local state
- "Save" button persists changes via
ConfigManager.saveConfig() - Dialog closes and main window refreshes if needed
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, src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L124-L125
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<String> |
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
|
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
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
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
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 |
stopBtn |
MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog |
Stop recording | MainFrame.java L119 |
playBtn |
!MacroManager.isRecording() && !HotkeyDialog.inHotKeyDialog |
Play macro | MainFrame.java L120 |
abortBtn |
MacroManager.isPlaying() && !HotkeyDialog.inHotKeyDialog |
Abort playback | MainFrame.java L121 |
saveBtn |
!MacroManager.isRecording() |
Save to file | MainFrame.java L122 |
loadBtn |
!MacroManager.isRecording() |
Load from file | MainFrame.java 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
All UI components support runtime language switching through the Localizer class.
MainFrame Localization:
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
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 |
MainFrame logArea scrollbar |
On construction | MainFrame.java L72-L73 |
SettingsDialog |
On construction | SettingsDialog.java L215 |
SettingsDialog |
On save | SettingsDialog.java L186-L187 |
Custom Components:
-
CustomScrollBarUI: Custom scrollbar rendering for themed appearance MainFrame.java L72-L73 - Color scheme provided by
ColorConstsclass
For detailed theme implementation, see Theming System.
Sources: src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L142, src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L186-L187
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 |
SettingsDialog |
"settings" |
521×359 | SettingsDialog.java L216 |
Cache data is persisted via CacheManager to cache.json. For details, see CacheManager.
Sources: src/io/github/samera2022/mouse_macros/ui/frame/MainFrame.java L144, src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L216
The WindowClosingAdapter is attached to all top-level windows to ensure proper cleanup and state persistence on close.
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, src/io/github/samera2022/mouse_macros/ui/frame/SettingsDialog.java L218
MainFrame dynamically adjusts its width to accommodate button labels, which vary based on:
- Selected language (text length varies)
- Hotkey assignments (displayed in parentheses)
Adjustment Logic:
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
The MouseMacros UI architecture follows these key patterns:
-
Single Main Window:
MainFrameis the persistent primary window -
Modal Dialogs: Configuration via modal
JDialogsubclasses -
Centralized Theming: All components styled via
ComponentUtil.setMode() -
Runtime Localization: Language switching without restart via
Localizer -
State Persistence: Window sizes and directory paths cached via
CacheManager - Guard Conditions: Button handlers check state before executing actions
- 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.