# (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 building the main window, collecting user input, restricting numeric input, displaying the conversion result, and coordinating asynchronous loading of currency codes and conversion actions.

The module is centered around two classes:
- `UI`, which assembles the frame, widgets, and event handlers.
- `UI.NumericFilter`, which enforces valid numeric input in the amount field.

The overall design is presentation-focused. `UI` orchestrates layout and user actions, while delegating remote currency lookup and conversion work to `CurrencyRateAPI` and background loading through an inner `SwingWorker`.

---

## Class: UI

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

The `UI` class is the main application window. It constructs the frame, creates the input and output widgets, wires the conversion, swap, and clear actions, and initializes the currency-code combo boxes asynchronously.

### Method: panel()

#### 1. Role
This method builds the main container for the window. It creates two internal panels: one for amount entry and source currency selection, and one for the result display, target currency selection, and action buttons.

#### 2. Processing Pattern
```mermaid
flowchart TD
A["panel()"] --> B["Create root panel"]
B --> C["Create input subpanel"]
C --> D["Add textField()"]
D --> E["Add comboBox1()"]
E --> F["Create output subpanel"]
F --> G["Add label()"]
G --> H["Add comboBox2()"]
H --> I["Add button() components"]
I --> J["Return assembled panel"]
```

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `textField()` | C | Creates the amount input component |
| `comboBox1()` | C | Creates the source currency selector |
| `label()` | C | Creates the result display label |
| `comboBox2()` | C | Creates the target currency selector |
| `button()` | C | Creates the action buttons |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `UI()` constructor | Direct caller | The constructor adds this panel to the frame |
| `UI` window initialization | Composition root | The assembled panel becomes the main UI content |

#### 6. Per-Branch Detail Blocks
- Root panel creation
  - A vertical `BoxLayout` organizes the UI into two stacked subpanels.
- Input subpanel
  - Uses centered `FlowLayout` and dark background styling.
  - Hosts the amount field and the first combo box.
- Output subpanel
  - Uses centered `FlowLayout` and dark background styling.
  - Hosts the result label, second combo box, and buttons.

---

### Method: button()

#### 1. Role
This method creates the three action buttons used by the application: Convert, Swap, and Clear. It also attaches the event handlers that perform the currency conversion, swap the selected currencies, and reset the UI.

#### 2. Processing Pattern
```mermaid
flowchart TD
A["button()"] --> B["Create Convert Swap Clear buttons"]
B --> C["Set common button size"]
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 numeric result"]
J --> K["Update label"]
H --> L["Show error dialog"]
F --> M["Exchange combo box selections"]
G --> N["Clear text field and label"]
B --> O["Return button array"]
```

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `CurrencyRateAPI` | C | Created once to perform conversion requests |
| `CurrencyRateAPI.convert(...)` | R | Reads remote exchange-rate data and returns a converted amount |
| `JOptionPane.showMessageDialog(...)` | R | Displays validation errors to the user |
| `setLabel(...)` | U | Updates the result display |
| `setTextField(...)` | U | Clears the input field during reset |
| `getComboBox1()/getComboBox2()` | R/U | Reads and swaps selected currencies |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `panel()` | Direct caller | Adds the returned buttons to the frame layout |
| `UI` user interaction | Runtime entry | Button listeners execute in response to user clicks |

#### 6. Per-Branch Detail Blocks
- Convert branch
  - Checks that the amount field is not empty and not equal to a solitary decimal point.
  - Calls `CurrencyRateAPI.convert` using the selected source and target currencies.
  - Formats the returned numeric value using `DecimalFormat` before displaying it.
  - If validation fails, shows an error dialog.
  - If URL or URI resolution fails, throws a runtime exception.
- Swap branch
  - Reads the current source selection.
  - Swaps the selected values between the two combo boxes.
- Clear branch
  - Resets both the amount input and the result label to empty strings.

---

### Method: textField()

#### 1. Role
This method creates the amount input field used by the currency converter. It applies a numeric-only document filter so users can type only digits and a single decimal point.

#### 2. Processing Pattern
```mermaid
flowchart TD
A["textField()"] --> B["Create JTextField"]
B --> C["Set font and size"]
C --> D["Attach NumericFilter"]
D --> E["Return input field"]
```

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `NumericFilter` | C | Installs numeric validation on the document |
| `JTextField` configuration | U | Applies font and preferred size |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `panel()` | Direct caller | The created field is inserted into the input subpanel |

#### 6. Per-Branch Detail Blocks
- Component creation
  - Instantiates a text field and formats it for prominent numeric entry.
- Document filtering
  - The underlying `PlainDocument` receives a `NumericFilter` to prevent invalid content.

---

### Method: label()

#### 1. Role
This method creates the result label that displays the converted amount. It configures the label so the output is visually distinct and easy to read.

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `JLabel` configuration | C/U | Creates and styles the output display |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `panel()` | Direct caller | The label is placed in the output subpanel |

#### 1. Role
This method creates a blank output label and styles it with a large font, fixed size, white background, and opaque rendering. It is used as the primary destination for conversion results.

---

### Method: comboBox1()

#### 1. Role
This method creates the source-currency selection list. It initializes the combo box and triggers asynchronous loading of available currency codes.

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `CurrencyCode` | C | Starts a background task that loads currency codes |
| `JComboBox` configuration | C/U | Creates the selector and sets its size |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `panel()` | Direct caller | The created combo box is inserted into the input subpanel |

#### 6. Per-Branch Detail Blocks
- Initialization branch
  - Creates an empty combo box.
  - Applies a fixed preferred size.
- Background load branch
  - Invokes `CurrencyCode.execute()` to populate the list asynchronously.

---

### Method: comboBox2()

#### 1. Role
This method creates the target-currency selection list. Like the first combo box, it is initialized empty and populated asynchronously with currency codes.

#### 3. Parameter Analysis
This method has no parameters.

| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| N/A | N/A | N/A | N/A |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `CurrencyCode` | C | Starts a background task that loads currency codes |
| `JComboBox` configuration | C/U | Creates the selector and sets its size |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `panel()` | Direct caller | The created combo box is inserted into the output subpanel |

#### 6. Per-Branch Detail Blocks
- Initialization branch
  - Creates an empty combo box.
  - Applies a fixed preferred size.
- Background load branch
  - Invokes `CurrencyCode.execute()` to populate the list asynchronously.

---

## Class: NumericFilter

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

`NumericFilter` is a document filter that protects the amount field from invalid content. It allows empty input, digits, and a single decimal point, while rejecting any other character sequence.

### Method: isValid()

#### 1. Role
This helper validates the full text that would exist after an edit operation. It is the rule engine for the filter, ensuring the amount field remains numeric-friendly.

#### 3. Parameter Analysis
| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| `text` | `String` | Candidate content after an edit | Must be non-null by caller convention |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `Character.isDigit(...)` | R | Checks individual characters |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| `insertString()` | Direct caller | Validates proposed insertion content |
| `replace()` | Direct caller | Validates proposed replacement content |

#### 6. Per-Branch Detail Blocks
- Empty input branch
  - Returns `true` so the user can clear the field.
- Character scan branch
  - Allows one decimal point.
  - Rejects any non-digit character other than the permitted decimal point.

---

### Method: insertString()

#### 1. Role
This method intercepts text insertion into the amount field. It reconstructs the prospective document content, validates it, and only forwards the change when the content remains acceptable.

#### 3. Parameter Analysis
| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| `fb` | `FilterBypass` | Provides access to the underlying document | Supplied by Swing |
| `offset` | `int` | Insertion position | Supplied by Swing |
| `string` | `String` | Text to insert | May be null in Swing edge cases, but handled by upstream behavior |
| `attr` | `AttributeSet` | Text attributes | Passed through unchanged |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `fb.getDocument()` | R | Reads the current document state |
| `Document.getText(...)` | R | Captures existing content |
| `super.insertString(...)` | C | Applies the insertion when valid |
| `isValid(...)` | R | Validates the candidate text |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| Swing document editing | Framework entry | Invoked when the user types into the field |

#### 6. Per-Branch Detail Blocks
- Build candidate text
  - Copies the full current document into a buffer.
  - Inserts the new string at the requested offset.
- Validation branch
  - If the candidate text is valid, the edit is delegated to the superclass.
  - If invalid, the edit is silently ignored.

---

### Method: replace()

#### 1. Role
This method intercepts replacement edits in the amount field. It applies the same numeric validation rules as insertion, but it evaluates the post-edit document content after replacing the selected region.

#### 3. Parameter Analysis
| Parameter | Type | Purpose | Validation |
|----------|------|---------|------------|
| `fb` | `FilterBypass` | Provides access to the underlying document | Supplied by Swing |
| `offset` | `int` | Replacement start position | Supplied by Swing |
| `length` | `int` | Number of characters to replace | Supplied by Swing |
| `text` | `String` | Replacement text | May be null in Swing edge cases, but handled by upstream behavior |
| `attrs` | `AttributeSet` | Text attributes | Passed through unchanged |

#### 4. CRUD Operations / Called Services
| Called Element | Operation | Notes |
|---------------|-----------|-------|
| `fb.getDocument()` | R | Reads the current document state |
| `Document.getText(...)` | R | Captures existing content |
| `DocumentBuilder.replace(...)` | U | Rebuilds the candidate content in memory |
| `super.replace(...)` | C | Applies the replacement when valid |
| `isValid(...)` | R | Validates the candidate text |

#### 5. Dependency Trace
| Entry Point / Caller | Relation | Notes |
|----------------------|----------|-------|
| Swing document editing | Framework entry | Invoked when the user pastes or edits selected text |

#### 6. Per-Branch Detail Blocks
- Build candidate text
  - Copies the full current document into a buffer.
  - Replaces the selected range with the new text.
- Validation branch
  - If the candidate text is valid, the replacement is delegated to the superclass.
  - If invalid, the replacement is silently ignored.
