# (DD01) UI — Class Detailed Design [91 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `com.github.blaxk3.ui.UI` |
| Layer | UI / Presentation |
| Module | `com.github.blaxk3.ui` |

## Class Overview

`UI` is the Swing-based presentation class for a currency converter application. It builds the main window, arranges the input and output widgets, and wires user actions to conversion, swap, and clear behavior. The class also contains two nested helper types that handle numeric-only text entry and asynchronous loading of currency codes, which keeps the user interface responsive while remote data is loaded.

---

## Method: button()

### 1. Role
Creates the three action buttons used by the converter screen and attaches all UI behavior for conversion, swapping selected currencies, and clearing the form. This method is the primary interaction point between the view and the currency-rate service.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["button() starts"]
    CreateButtons["Create Convert, Swap, and Clear buttons"]
    SizeButtons["Apply preferred size 200 x 35 to each button"]
    CreateRate["Instantiate CurrencyRateAPI"]
    AttachConvert["Attach Convert action listener"]
    AttachSwap["Attach Swap action listener"]
    AttachClear["Attach Clear action listener"]
    ReturnButtons["Return JButton array"]

    Start --> CreateButtons
    CreateButtons --> SizeButtons
    SizeButtons --> CreateRate
    CreateRate --> AttachConvert
    AttachConvert --> AttachSwap
    AttachSwap --> AttachClear
    AttachClear --> ReturnButtons
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | It relies on UI fields created by `textField()`, `label()`, `comboBox1()`, and `comboBox2()`. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JButton[]` | Allocates the three action buttons. |
| Read | `textField`, `comboBox1`, `comboBox2` | Reads user amount and selected currency codes. |
| Update | `label`, `comboBox1`, `comboBox2`, `textField` | Updates the output label, swaps selections, or clears fields. |
| Called Service | `CurrencyRateAPI.convert(...)` | Converts an amount between two currency codes. |
| Called Service | `JOptionPane.showMessageDialog(...)` | Displays validation errors for empty or invalid input. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `CurrencyRateAPI` | External API client | Used in the Convert action to fetch the converted value. |
| `getTextField()` / `textField` | UI dependency | Provides the amount entered by the user. |
| `getComboBox1()` | UI dependency | Supplies the source currency selection. |
| `getComboBox2()` | UI dependency | Supplies the target currency selection. |
| `setLabel(String)` | Internal mutator | Stores the conversion result in the output label. |
| `setTextField(String)` | Internal mutator | Clears the amount field when Clear is pressed. |
| `DecimalFormat` | Formatting helper | Formats conversion output with grouped thousands and up to three decimals. |

### 6. Per-Branch Detail Blocks

- **Common setup branch**: three buttons are created with the captions `Convert`, `Swap`, and `Clear`, then each button receives the same preferred size. This establishes a consistent layout for the action area.
- **Convert branch**: when the first button is clicked, the method checks whether the text field is non-empty and not equal to a single dot. If the input passes validation, it parses the amount as `double`, converts it to `BigDecimal`, calls `CurrencyRateAPI.convert(...)`, formats the result with `DecimalFormat("#,###.###")`, and writes the formatted value into the label.
- **Convert error branch**: if the field is empty or contains only `.`, a modal error dialog is shown with the message `Please enter the amount you need`. If the remote conversion call fails with `MalformedURLException` or `URISyntaxException`, the listener rethrows the problem as a runtime exception.
- **Swap branch**: when the second button is clicked, the current source currency is stored in a local variable, the first combo box is set to the target selection, and the second combo box is set to the saved source selection. This effectively swaps both selected currencies.
- **Clear branch**: when the third button is clicked, the amount field is cleared and the result label is reset to an empty string.
- **Return branch**: the method returns the button array so the caller can add the components into the panel layout.

---

## Method: panel()

### 1. Role
Builds the complete container hierarchy for the main window and places the input row, output row, and all widgets into a vertical arrangement. This method assembles the screen but does not own any business rules.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["panel() starts"]
    CreateRoot["Create root JPanel"]
    SetRootLayout["Set BoxLayout Y_AXIS on root panel"]
    CreateInputRow["Create first child panel"]
    ConfigureInputRow["Set dark gray background and FlowLayout CENTER"]
    AddInputWidgets["Add textField() and comboBox1()"]
    CreateOutputRow["Create second child panel"]
    ConfigureOutputRow["Set FlowLayout CENTER and dark gray background"]
    AddOutputWidgets["Add label(), comboBox2(), and three buttons"]
    AssembleRoot["Add both child panels to root"]
    ReturnPanel["Return root panel"]

    Start --> CreateRoot
    CreateRoot --> SetRootLayout
    SetRootLayout --> CreateInputRow
    CreateInputRow --> ConfigureInputRow
    ConfigureInputRow --> AddInputWidgets
    AddInputWidgets --> CreateOutputRow
    CreateOutputRow --> ConfigureOutputRow
    ConfigureOutputRow --> AddOutputWidgets
    AddOutputWidgets --> AssembleRoot
    AssembleRoot --> ReturnPanel
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | It constructs the layout from helper methods and the class fields they initialize. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JPanel` instances | Builds the root panel and two nested panels. |
| Read | Helper methods | Calls `textField()`, `comboBox1()`, `label()`, `comboBox2()`, and `button()`. |
| Update | Panel layout and styling | Sets layouts, background colors, and child component placement. |
| Called Service | `BoxLayout`, `FlowLayout` | Provides the Swing layout strategy. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `textField()` | Internal factory | Supplies the amount entry component. |
| `comboBox1()` | Internal factory | Supplies the source currency selector. |
| `label()` | Internal factory | Supplies the conversion result display. |
| `comboBox2()` | Internal factory | Supplies the target currency selector. |
| `button()` | Internal factory | Supplies the action buttons. |
| `Color.DARK_GRAY` | Swing styling constant | Used for both child panels' background styling. |

### 6. Per-Branch Detail Blocks

- **Root panel branch**: the method creates a new `JPanel` and switches it to a vertical `BoxLayout`, which means its child panels are stacked top-to-bottom.
- **Input row branch**: the first child panel receives a dark gray background and centered flow layout, then the amount field and first currency combo box are added in that order.
- **Output row branch**: the second child panel receives centered flow layout and dark gray background, then the result label, second combo box, and all three buttons are added.
- **Assembly branch**: both child panels are inserted into the root panel in sequence, producing the final composite container returned to the frame.

---

## Method: comboBox1()

### 1. Role
Creates and initializes the first currency selector used as the source currency in a conversion. It also starts background loading of currency codes so the UI can populate the list asynchronously.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["comboBox1() starts"]
    CreateCombo["Create empty JComboBox<String>"]
    SetSize["Set preferred size 300 x 30"]
    StartWorker["Start CurrencyCode SwingWorker"]
    ExecuteWorker["Execute worker in background"]
    ReturnCombo["Return combo box"]

    Start --> CreateCombo
    CreateCombo --> SetSize
    SetSize --> StartWorker
    StartWorker --> ExecuteWorker
    ExecuteWorker --> ReturnCombo
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | The combo box is stored in the instance field `comboBox1`. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JComboBox<String>` | Allocates the source currency selector. |
| Update | `comboBox1` field | Assigns the newly created component to the class field. |
| Called Service | `new CurrencyCode(comboBox1).execute()` | Starts asynchronous population of currency codes. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `CurrencyCode` | Nested worker class | Loads currency codes in the background. |
| `comboBox1` field | Internal state | Stores the created selector for later reads and updates. |

### 6. Per-Branch Detail Blocks

- **Initialization branch**: a blank combo box is created and stored in the `comboBox1` field.
- **Sizing branch**: the method applies a 300 x 30 preferred size so the selector aligns with the other form elements.
- **Asynchronous loading branch**: `CurrencyCode` is instantiated with the combo box and executed. The worker is responsible for fetching codes and adding them later.
- **Return branch**: the method returns the combo box as a generic `Component`.

---

## Method: comboBox2()

### 1. Role
Creates and initializes the second currency selector used as the target currency in a conversion. Like the first selector, it populates its options asynchronously.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["comboBox2() starts"]
    CreateCombo["Create empty JComboBox<String>"]
    SetSize["Set preferred size 300 x 30"]
    StartWorker["Start CurrencyCode SwingWorker"]
    ExecuteWorker["Execute worker in background"]
    ReturnCombo["Return combo box"]

    Start --> CreateCombo
    CreateCombo --> SetSize
    SetSize --> StartWorker
    StartWorker --> ExecuteWorker
    ExecuteWorker --> ReturnCombo
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | The combo box is stored in the instance field `comboBox2`. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JComboBox<String>` | Allocates the target currency selector. |
| Update | `comboBox2` field | Assigns the newly created component to the class field. |
| Called Service | `new CurrencyCode(comboBox2).execute()` | Starts asynchronous population of currency codes. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `CurrencyCode` | Nested worker class | Loads currency codes in the background. |
| `comboBox2` field | Internal state | Stores the created selector for later reads and updates. |

### 6. Per-Branch Detail Blocks

- **Initialization branch**: a blank combo box is created and stored in the `comboBox2` field.
- **Sizing branch**: the method applies a 300 x 30 preferred size so the selector aligns with the other form elements.
- **Asynchronous loading branch**: `CurrencyCode` is instantiated with the combo box and executed. The worker is responsible for fetching codes and adding them later.
- **Return branch**: the method returns the combo box as a generic `Component`.

---

## Method: textField()

### 1. Role
Creates the amount entry field used by the converter and installs a numeric-only document filter. This prevents invalid text input from reaching the conversion workflow.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["textField() starts"]
    CreateField["Create JTextField"]
    SetFont["Set Arial bold 24 font"]
    SetSize["Set preferred size 300 x 100"]
    InstallFilter["Install NumericFilter on PlainDocument"]
    ReturnField["Return text field"]

    Start --> CreateField
    CreateField --> SetFont
    SetFont --> SetSize
    SetSize --> InstallFilter
    InstallFilter --> ReturnField
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | The created field is stored in the instance field `textField`. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JTextField` | Allocates the amount entry component. |
| Update | `textField` field | Stores the created field in the instance field. |
| Called Service | `NumericFilter` | Restricts input to digits and at most one decimal point. |
| Called Service | `PlainDocument.setDocumentFilter(...)` | Installs the document-level validator. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `NumericFilter` | Nested filter class | Enforces numeric input rules. |
| `textField` field | Internal state | Used later by `button()` and external getters/setters. |

### 6. Per-Branch Detail Blocks

- **Initialization branch**: a fresh text field is allocated and captured in the `textField` instance field.
- **Presentation branch**: the field is styled with Arial bold size 24 and sized at 300 x 100.
- **Validation branch**: the underlying `Document` is cast to `PlainDocument`, and a `NumericFilter` is attached so only valid numeric content can be typed or pasted.
- **Return branch**: the field is returned to the caller as a `Component`.

---

## Method: label()

### 1. Role
Creates the output label used to display the converted amount. It is styled as a prominent read-only result area with a white background.

### 2. Processing Pattern
```mermaid
flowchart TD
    Start["label() starts"]
    CreateLabel["Create JLabel"]
    SetFont["Set Arial bold 24 font"]
    SetSize["Set preferred size 300 x 100"]
    MakeOpaque["Set label opaque"]
    SetBackground["Set background to white"]
    ReturnLabel["Return label"]

    Start --> CreateLabel
    CreateLabel --> SetFont
    SetFont --> SetSize
    SetSize --> MakeOpaque
    MakeOpaque --> SetBackground
    SetBackground --> ReturnLabel
```

### 3. Parameter Analysis

| Parameter | Type | Meaning | Notes |
|----------|------|---------|-------|
| None | - | This method takes no arguments. | The created label is stored in the instance field `label`. |

### 4. CRUD Operations / Called Services

| Operation | Target | Details |
|-----------|--------|---------|
| Create | `JLabel` | Allocates the conversion result display component. |
| Update | `label` field | Stores the created label in the instance field. |
| Called Service | Swing styling setters | Applies font, size, opacity, and background color. |

### 5. Dependency Trace

| Dependency | Type | Evidence / Role |
|------------|------|-----------------|
| `label` field | Internal state | Updated by this method and later written by `button()`. |
| `Color.WHITE` | Styling constant | Gives the result area a clear display background. |

### 6. Per-Branch Detail Blocks

- **Initialization branch**: a new label is created and stored in the class field `label`.
- **Presentation branch**: the label receives the same font and sizing treatment as the text field so the form remains visually consistent.
- **Visibility branch**: `setOpaque(true)` is applied so the background color will render.
- **Styling branch**: the background is set to white to distinguish the output area from the dark gray input panels.
- **Return branch**: the label is returned as a `Component`.
