# Com / Github / Blaxk3 / Ui

## Overview

The `com.github.blaxk3.ui` package appears to provide the desktop user interface for a currency converter application. It builds a Swing-based window, wires in currency selection controls, accepts numeric input, and triggers conversion through `com.github.blaxk3.api.CurrencyRateAPI`.

The package also contains two small helper classes inside `UI.java`: one enforces numeric-only input in the amount field, and the other loads currency codes asynchronously so the combo boxes can be populated without blocking the UI thread.

## Key Classes and Interfaces

### [UI](src/main/java/com/github/blaxk3/ui/UI.java:30)

`UI` is the main window class and extends `javax.swing.JFrame`. It is responsible for assembling the full converter screen, exposing a few getters/setters for the controls, and attaching the button actions that drive the conversion flow.

#### Role in the design

This class acts as the composition root for the UI. It creates the text field, labels, combo boxes, and buttons, then binds them together into a single frame. It also owns the interaction with the API layer through `CurrencyRateAPI`.

#### Key methods

- [UI.UI()](src/main/java/com/github/blaxk3/ui/UI.java:58) builds and displays the window.
  - Sets the application icon from `/icon/image/icon.png`.
  - Adds the main panel to the frame.
  - Configures title, size, layout, close behavior, resizing, centering, and visibility.
- [UI.panel()](src/main/java/com/github/blaxk3/ui/UI.java:70) assembles the top-level container.
  - Creates two stacked subpanels.
  - Places the input field and source currency selector in the first row.
  - Places the result label, target currency selector, and action buttons in the second row.
- [UI.comboBox1()](src/main/java/com/github/blaxk3/ui/UI.java:95) creates the first currency selector.
  - Initializes the combo box with a fixed preferred size.
  - Starts a background [CurrencyCode](src/main/java/com/github/blaxk3/ui/UI.java:217) worker to load currency options.
- [UI.comboBox2()](src/main/java/com/github/blaxk3/ui/UI.java:103) creates the second currency selector.
  - Same behavior as `comboBox1()`, but used as the destination currency selector.
- [UI.button()](src/main/java/com/github/blaxk3/ui/UI.java:111) creates and wires the three action buttons.
  - **Convert** reads the amount and selected currencies, calls `CurrencyRateAPI.convert(...)`, formats the result, and writes it into the label.
  - **Swap** exchanges the selected source and destination currencies.
  - **Clear** clears both the amount field and the result label.
- [UI.textField()](src/main/java/com/github/blaxk3/ui/UI.java:149) creates the amount input field.
  - Applies the `NumericFilter` document filter so users can only enter valid numeric text.
- [UI.label()](src/main/java/com/github/blaxk3/ui/UI.java:158) creates the result display.
  - Configures a large white label area intended to show the converted amount.
- [UI.getComboBox1()](src/main/java/com/github/blaxk3/ui/UI.java:38), [UI.getComboBox2()](src/main/java/com/github/blaxk3/ui/UI.java:42), [UI.getTextField()](src/main/java/com/github/blaxk3/ui/UI.java:46)
  - Simple accessors used by the button handlers and helper logic.
- [UI.setTextField(String msg)](src/main/java/com/github/blaxk3/ui/UI.java:50) and [UI.setLabel(String textField)](src/main/java/com/github/blaxk3/ui/UI.java:54)
  - Convenience mutators used by the clear and convert actions.

#### Why it exists

`UI` centralizes the Swing-specific implementation details so the rest of the application can focus on exchange-rate retrieval and conversion logic. The class provides the visible user workflow: enter an amount, choose currencies, convert, optionally swap, and clear.

### [NumericFilter](src/main/java/com/github/blaxk3/ui/UI.java:167)

`NumericFilter` is a `DocumentFilter` that protects the amount field from invalid input. It allows only digits and at most one decimal point, which makes the field suitable for currency amounts.

#### Key methods

- [UI.insertString(FilterBypass fb, int offset, String string, AttributeSet attr)](src/main/java/com/github/blaxk3/ui/UI.java:169)
  - Simulates the resulting text after insertion.
  - Delegates to `super.insertString(...)` only if the new text passes validation.
- [UI.replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)](src/main/java/com/github/blaxk3/ui/UI.java:182)
  - Simulates the result of a replacement and only applies it when valid.
- [UI.isValid(String text)](src/main/java/com/github/blaxk3/ui/UI.java:195)
  - Returns `true` for an empty string, digits, and one decimal separator.
  - Rejects any other characters.

#### Why it exists

The filter reduces input errors before conversion logic runs. That means the convert button can assume the field contains a parseable numeric value in normal use, instead of having to sanitize arbitrary text.

### [CurrencyCode](src/main/java/com/github/blaxk3/ui/UI.java:214)

`CurrencyCode` is a `SwingWorker<String[], Void>` that loads currency codes in the background and populates a combo box when the work completes.

#### Key methods

- [UI.CurrencyCode(JComboBox < String > comboBox)](src/main/java/com/github/blaxk3/ui/UI.java:217)
  - Stores the combo box that should receive the loaded values.
- [UI.doInBackground()](src/main/java/com/github/blaxk3/ui/UI.java:221)
  - Calls `new CurrencyRateAPI().getCurrencyCode()` to fetch the available codes.
- [UI.done()](src/main/java/com/github/blaxk3/ui/UI.java:227)
  - Reads the fetched array from `get()`.
  - Sorts the codes alphabetically.
  - Adds each code to the combo box.
  - Logs errors if the worker is interrupted or fails.

#### Why it exists

This class keeps the UI responsive while currency metadata is fetched. Loading codes on the event dispatch thread would freeze the interface until the API call returned, so `SwingWorker` is used to move the retrieval off-thread.

## How It Works

1. The `UI` constructor creates the window and immediately builds the main panel.
2. `panel()` creates two stacked rows:
   - the input row with the amount field and source currency combo box,
   - the output row with the result label, destination combo box, and buttons.
3. Each combo box starts a `CurrencyCode` worker, which fetches currency codes from `CurrencyRateAPI` in the background and adds them once available.
4. The amount field is protected by `NumericFilter`, which blocks invalid input as the user types.
5. When the user clicks **Convert**:
   - the code checks that the field is not empty and not just `.`,
   - it reads both selected currency codes,
   - it converts the text field value to `double` and then `BigDecimal`,
   - it calls `CurrencyRateAPI.convert(...)`,
   - it formats the returned number with `DecimalFormat("#,###.###")`,
   - it writes the formatted value into the result label.
6. **Swap** exchanges the selected combo box values so the user can reverse the conversion direction quickly.
7. **Clear** resets both the input and the result display.

### Relationship diagram

```mermaid
flowchart TD
UIClass["UI"] --> PanelBuilder["panel()"]
UIClass --> ComboBox1Builder["comboBox1()"]
UIClass --> ComboBox2Builder["comboBox2()"]
UIClass --> ButtonBuilder["button()"]
UIClass --> TextFieldBuilder["textField()"]
UIClass --> LabelBuilder["label()"]
UIClass --> NumericFilterClass["NumericFilter"]
UIClass --> CurrencyCodeClass["CurrencyCode"]
CurrencyCodeClass --> CurrencyRateAPIClass["CurrencyRateAPI"]
```

## Data Model

This package does not define a domain entity model in the usual sense. Instead, it works with a small set of UI state objects and values:

- `JTextField` for the entered amount
- `JLabel` for the converted result
- `JComboBox<String>` for the source and target currency codes
- `String[]` as the payload returned by `CurrencyCode.doInBackground()`
- `BigDecimal` and `double` as the numeric values passed into and returned from conversion logic

The package is therefore more about presentation state than persistent data modeling.

## Dependencies and Integration

### External Swing and JDK APIs

The module depends heavily on Swing and AWT:

- `javax.swing.JFrame`, `JPanel`, `JButton`, `JComboBox`, `JLabel`, `JTextField`, `SwingWorker`
- `java.awt` layout and component classes such as `FlowLayout`, `GridLayout`, `BoxLayout`, `Color`, `Dimension`, and `Font`
- `javax.swing.text.DocumentFilter` to constrain input

### Application dependency

The main integration point is [com.github.blaxk3.api.CurrencyRateAPI](src/main/java/com/github/blaxk3/api/CurrencyRateAPI.java:1), which is used in two places:

- `CurrencyCode.doInBackground()` fetches available currency codes.
- The Convert button handler calls `rate.convert(...)` to compute the converted amount.

### Logging

The package uses SLF4J for error reporting inside `CurrencyCode.done()`.

## Notes for Developers

- The `UI` constructor calls `setVisible(true)` immediately, so creating an instance has side effects. Be careful when instantiating it in tests or background code.
- `button()` creates a new `CurrencyRateAPI` instance once and closes over it in the Convert action listener.
- The Convert path assumes the text field contains a parseable numeric value. The `NumericFilter` prevents most invalid input, but the code still checks for empty input and a lone decimal point before converting.
- `CurrencyCode.done()` sorts the returned currency list before populating the combo box, so the display order is alphabetical rather than API-defined.
- Both combo boxes are populated independently by their own workers, so they may complete at slightly different times.
- `panel()` currently calls `button()` once and reuses all three returned buttons. That is important because calling `button()` again would create a fresh set of buttons and new listeners.
- The module does not currently expose any domain objects of its own; if additional UI state is introduced later, this package is the natural place for new Swing helper classes or display-specific formatting logic.
