# (DD01) Module: com.github.blaxk3.ui — Detailed Design [132 LOC]

## Module Overview
The `com.github.blaxk3.ui` module contains the Swing-based user interface for a currency converter application. It is responsible for assembling the main window, wiring user actions to currency conversion logic, and constraining numeric input so the amount field accepts only valid decimal values.

The module is centered around two classes:
- `UI`, which builds the frame, layouts, input controls, action buttons, and event handlers.
- `NumericFilter`, which guards the amount text field by validating insert and replace operations on the document.

Together, these classes provide the presentation layer and the first line of input validation before currency conversion is triggered.

---

## Class: UI

### Class Summary
| Field | Value |
|-------|-------|
| FQN | `com.github.blaxk3.ui.UI` |
| Layer | Presentation / Desktop UI |
| Methods | 6 |

`UI` is the main application window. It extends `JFrame`, creates the converter form, initializes the two currency selectors, and exposes basic getters and setters so event handlers can access and update the visible controls.

### Method: button()

#### 1. Role
This method creates the three action buttons used by the converter: Convert, Swap, and Clear. It also attaches the event handlers that connect the UI to the exchange-rate service and to local UI state changes.

The method is the primary interaction point in the module because it converts user input into service calls, handles invalid input, and updates the result label.

#### 2. Processing Pattern
```mermaid
flowchart TD
A["button()"] --> B["Create three JButton instances"]
B --> C["Apply preferred sizes"]
C --> D["Create CurrencyRateAPI instance"]
D --> E["Attach Convert listener"]
D --> F["Attach Swap listener"]
D --> G["Attach Clear listener"]
E --> H["Validate amount text"]
H --> I["Call CurrencyRateAPI.convert"]
I --> J["Format converted value"]
J --> K["Update label"]
F --> L["Swap selected currencies"]
G --> M["Clear text field and label"]
```

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method takes no parameters and returns an array of Swing components. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `CurrencyRateAPI` | C | Creates a service object for conversion requests. |
| `CurrencyRateAPI.convert(...)` | R | Fetches the converted amount from the rate service. |
| `JOptionPane` | R | Displays a validation error message when the amount is missing or invalid. |
| `JTextField` | U | Reads and clears the input field. |
| `JLabel` | U | Writes the conversion result or clears the output. |
| `JComboBox` | R/U | Reads selected currencies and swaps selections. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `panel()` | Adds the three button components to the lower control row. |
| `UI()` constructor | Indirectly triggers this method through `panel()` during frame construction. |
| User click on Convert | Activates conversion flow and service call. |
| User click on Swap | Swaps source and target currency selections. |
| User click on Clear | Resets the amount field and output label. |

#### 6. Per-Branch Detail Blocks
- Convert action
  - If the amount field is not empty and not a single dot, the handler proceeds.
  - Otherwise, a modal error dialog is shown and no conversion occurs.
  - When valid, the input text is parsed, passed to the API, formatted, and written to the label.
- Swap action
  - The currently selected source currency is stored temporarily.
  - The source selection is replaced with the target selection.
  - The saved value is then assigned to the target selection.
- Clear action
  - The input field is reset to an empty string.
  - The result label is cleared.

---

### Method: panel()

#### 1. Role
This method assembles the main content panel for the frame. It builds the two horizontal sub-panels, places the input controls and action controls into them, and returns the composed panel to the frame constructor.

The method establishes the visual structure of the UI and defines the parent-child relationships between the top-level frame and its child widgets.

#### 2. Processing Pattern
```mermaid
flowchart TD
A["panel()"] --> B["Create outer frame panel"]
B --> C["Create first inner panel"]
C --> D["Add textField()"]
C --> E["Add comboBox1()"]
B --> F["Create second inner panel"]
F --> G["Add label()"]
F --> H["Add comboBox2()"]
F --> I["Add button()[0]"]
F --> J["Add button()[1]"]
F --> K["Add button()[2]"]
B --> L["Return composed panel"]
```

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method is parameterless and returns the assembled container component. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `JPanel` | C | Creates the container hierarchy. |
| `FlowLayout` / `BoxLayout` | C | Defines the panel layout strategy. |
| `textField()` | R | Builds the amount input control. |
| `comboBox1()` | R | Builds the source currency selector. |
| `label()` | R | Builds the output display. |
| `comboBox2()` | R | Builds the target currency selector. |
| `button()` | R | Builds the action buttons. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `UI()` constructor | Directly calls `panel()` and adds its return value to the frame. |
| Application startup | The constructor path makes this the primary UI composition entry point. |

#### 6. Per-Branch Detail Blocks
- Panel composition
  - Outer panel uses a vertical box layout.
  - First inner panel holds the amount field and first combo box.
  - Second inner panel holds the result label, second combo box, and the three buttons.
- Styling branches
  - The first and second inner panels use dark backgrounds to visually group controls.
  - Layout alignment is centered through flow layouts for both rows.

---

### Method: comboBox1()

#### 1. Role
This method creates the first currency selector and starts an asynchronous load of available currency codes. It returns the configured combo box component so the caller can place it in the UI.

The method is responsible for initializing the source-currency selection control and ensuring its content is populated in the background.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method has no inputs. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `JComboBox` | C | Creates the selector component. |
| `CurrencyCode` | C | Creates the background worker that loads currency codes. |
| `CurrencyCode.execute()` | R | Starts asynchronous population of the combo box. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `panel()` | Adds the first combo box to the top input row. |
| `button()` | Reads the selected item during conversion and swap actions. |

#### 6. Per-Branch Detail Blocks
- Initialization path
  - A new empty combo box is instantiated.
  - The preferred size is set to fit the form.
  - A `CurrencyCode` worker is created and executed to populate items later.

---

### Method: comboBox2()

#### 1. Role
This method creates the second currency selector and starts the same asynchronous currency-code loading process as the first combo box. It returns the configured selector for the target currency.

The method mirrors `comboBox1()` so both selectors are initialized consistently and populated from the same source.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method has no inputs. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `JComboBox` | C | Creates the selector component. |
| `CurrencyCode` | C | Creates the background worker that loads currency codes. |
| `CurrencyCode.execute()` | R | Starts asynchronous population of the combo box. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `panel()` | Adds the second combo box to the lower control row. |
| `button()` | Reads the selected item during conversion and swap actions. |

#### 6. Per-Branch Detail Blocks
- Initialization path
  - A new empty combo box is instantiated.
  - The preferred size is set to fit the form.
  - A `CurrencyCode` worker is created and executed to populate items later.

---

### Method: textField()

#### 1. Role
This method creates the amount entry field used by the converter. It applies font and size settings and attaches the numeric document filter so only valid decimal input can be entered.

The method establishes the input constraint that protects the conversion flow from invalid text.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method has no inputs. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `JTextField` | C | Creates the input control. |
| `Font` | C | Configures text appearance. |
| `NumericFilter` | C | Creates the document filter used to validate numeric edits. |
| `PlainDocument.setDocumentFilter(...)` | U | Installs the input guard on the text field document. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `panel()` | Adds the amount field to the top input row. |
| `button()` | Reads the typed amount when conversion is requested. |

#### 6. Per-Branch Detail Blocks
- Initialization path
  - The text field is created.
  - Font and preferred size are applied.
  - The document is cast to `PlainDocument` and the `NumericFilter` is attached.

---

### Method: label()

#### 1. Role
This method creates the output label used to display the converted amount. It sets the font, size, and background appearance so the result is visible and visually separated from the input field.

The method does not contain branching logic, but it is essential because conversion results are written into this component by the button handler.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| None | - | The method has no inputs. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `JLabel` | C | Creates the output display component. |
| `Font` | C | Configures text appearance. |
| `setOpaque(true)` | U | Enables background painting. |
| `setBackground(Color.WHITE)` | U | Gives the result area a clear visual surface. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `panel()` | Adds the label to the lower control row. |
| `button()` | Updates the label after a successful conversion and clears it on reset. |

#### 6. Per-Branch Detail Blocks
- Initialization path
  - The label is created.
  - Font and preferred size are configured.
  - Opaqueness is enabled and the background is set to white.

---

## Class: NumericFilter

### Class Summary
| Field | Value |
|-------|-------|
| FQN | `com.github.blaxk3.ui.UI.NumericFilter` |
| Layer | Input validation / Swing document filtering |
| Methods | 3 |

`NumericFilter` is a nested document filter that restricts the text field to digits and a single decimal point. It validates proposed document changes before allowing them to be applied, which keeps the amount input compatible with downstream numeric parsing.

### Method: isValid()

#### 1. Role
This helper checks whether a candidate string is a valid decimal-like input for the amount field. It accepts empty content, digits, and at most one decimal point.

The method provides the core validation rule used by both insert and replace operations.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| `text` | `String` | The full proposed document content after the edit. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `String.isEmpty()` | R | Handles the empty-input case. |
| `Character.isDigit(...)` | R | Confirms that non-decimal characters are digits. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| `insertString()` | Called before allowing an insertion to proceed. |
| `replace()` | Called before allowing a replacement to proceed. |
|
| `textField()` | Indirectly depends on this validation through the installed filter. |

#### 6. Per-Branch Detail Blocks
- Empty text branch
  - Returns `true` immediately so the field can be cleared.
- Character scan branch
  - Uses a decimal counter to allow a single dot.
  - Accepts digits directly.
  - Rejects any other character.

---

### Method: insertString()

#### 1. Role
This override validates a proposed insertion into the document before letting Swing apply it. It reconstructs the post-edit text, validates it, and only forwards the insertion if the resulting content is acceptable.

The method prevents invalid characters from ever reaching the text field state.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| `fb` | `FilterBypass` | Provides access to the target document and the ability to delegate the edit. |
| `offset` | `int` | Insert position within the document. |
| `string` | `String` | The text being inserted. |
| `attr` | `AttributeSet` | Formatting attributes passed through by Swing. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `FilterBypass.getDocument()` | R | Retrieves the current document content. |
| `Document.getText(...)` | R | Reads the current text for validation. |
| `StringBuilder.insert(...)` | U | Simulates the edit. |
| `isValid(...)` | R | Determines whether the edit is allowed. |
| `super.insertString(...)` | U | Applies the change when validation succeeds. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| Swing text component editing | Invoked automatically when text is inserted into the amount field. |
| `textField()` | Installs this filter on the document, making the override active. |

#### 6. Per-Branch Detail Blocks
- Valid edit branch
  - Rebuilds the candidate document text.
  - If valid, delegates to the superclass to perform the insertion.
- Invalid edit branch
  - Silently blocks the insertion by doing nothing after validation fails.

---

### Method: replace()

#### 1. Role
This override validates a proposed replacement within the document before applying it. It follows the same validation logic as insertion, but it accounts for the range of characters being replaced.

The method is the second half of the document guard and is required for paste and overwrite operations.

#### 3. Parameter Analysis
| Parameter | Type | Role |
|-----------|------|------|
| `fb` | `FilterBypass` | Provides access to the target document and the ability to delegate the edit. |
| `offset` | `int` | Starting index of the replacement. |
| `length` | `int` | Number of characters to replace. |
| `text` | `String` | Replacement text. |
| `attrs` | `AttributeSet` | Formatting attributes passed through by Swing. |

#### 4. CRUD Operations / Called Services
| Dependency | Operation | Purpose |
|------------|-----------|---------|
| `FilterBypass.getDocument()` | R | Retrieves the current document content. |
| `Document.getText(...)` | R | Reads the current text for validation. |
| `StringBuilder.replace(...)` | U | Simulates the edit. |
| `isValid(...)` | R | Determines whether the edit is allowed. |
| `super.replace(...)` | U | Applies the change when validation succeeds. |

#### 5. Dependency Trace
| Entry Point / Caller | Trace |
|----------------------|-------|
| Swing text component editing | Invoked automatically when text is replaced in the amount field. |
| `textField()` | Installs this filter on the document, making the override active. |

#### 6. Per-Branch Detail Blocks
- Valid edit branch
  - Rebuilds the candidate document text with the replacement applied.
  - If valid, delegates to the superclass to perform the replacement.
- Invalid edit branch
  - Silently blocks the replacement by doing nothing after validation fails.
