# Com / Github / Blaxk3 / Ui

## Overview

The `com.github.blaxk3.ui` package appears to provide the Swing user interface for a currency converter application. It owns the main window, wires together the input/output controls, and bridges user actions to the currency-rate API in `com.github.blaxk3.api`.

This module is responsible for three main concerns: rendering the converter window, validating numeric input, and loading currency codes asynchronously into the currency selectors. The result is a self-contained desktop UI that keeps API calls and input handling out of the rest of the application.

## Key Classes and Interfaces

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

`UI` is the main `JFrame` for the application and the entry point for the converter window. Its constructor builds the full interface, configures the frame, and immediately shows it.

Key responsibilities:

- Builds the screen layout with an input field, two currency selectors, a result label, and three action buttons.
- Coordinates conversion, swapping currencies, and clearing the form.
- Exposes a few getters and setters so the inner action handlers can read and update controls.

Important methods:

- [UI.UI()](src/main/java/com/github/blaxk3/ui/UI.java:58) sets up the frame title, icon, size, layout, and visibility.
- [UI.panel()](src/main/java/com/github/blaxk3/ui/UI.java:70) assembles the two stacked panels that make up the content area.
- [UI.comboBox1()](src/main/java/com/github/blaxk3/ui/UI.java:95) and [UI.comboBox2()](src/main/java/com/github/blaxk3/ui/UI.java:103) create the source/target currency selectors and kick off asynchronous loading of currency codes.
- [UI.button()](src/main/java/com/github/blaxk3/ui/UI.java:111) creates the Convert, Swap, and Clear buttons and attaches their event handlers.
- [UI.textField()](src/main/java/com/github/blaxk3/ui/UI.java:149) creates the numeric input field and applies the input filter.
- [UI.label()](src/main/java/com/github/blaxk3/ui/UI.java:158) creates the result display label.
- [UI.getComboBox1()](src/main/java/com/github/blaxk3/ui/UI.java:38), [UI.getComboBox2()](src/main/java/com/github/blaxk3/ui/UI.java:42), and [UI.getTextField()](src/main/java/com/github/blaxk3/ui/UI.java:46) are used by the button handlers.
- [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) update the visible form state.

Design notes:

- The frame uses `GridLayout(1, 2)` but only adds a single panel, so the visible layout is effectively controlled by the panel hierarchy inside [UI.panel()](src/main/java/com/github/blaxk3/ui/UI.java:70).
- The class holds component references as fields rather than using local variables, because the button actions need access to the same widgets later.
- API interaction is done directly from the UI class through `CurrencyRateAPI`, so this package is tightly coupled to the API layer.

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

`NumericFilter` is a `DocumentFilter` that restricts the text field to numeric input with at most one decimal point. It is attached to the amount field in [UI.textField()](src/main/java/com/github/blaxk3/ui/UI.java:149).

Purpose:

- Prevents invalid characters from entering the amount field.
- Allows empty input, digits, and a single decimal separator.

Important methods:

- [UI.insertString(FilterBypass fb, int offset, String string, AttributeSet attr)](src/main/java/com/github/blaxk3/ui/UI.java:169) simulates the insertion and only allows it if the resulting text is valid.
- [UI.replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)](src/main/java/com/github/blaxk3/ui/UI.java:182) applies the same validation logic for replacements.
- [UI.isValid(String text)](src/main/java/com/github/blaxk3/ui/UI.java:195) checks that the string is empty, digits-only, or digits plus a single dot.

The validation logic is intentionally simple: it does not accept signs, grouping separators, or scientific notation. That keeps the input aligned with the conversion flow, which parses the text directly as a `double`.

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

`CurrencyCode` is a `SwingWorker<String[], Void>` used to fetch and populate the currency lists without blocking the Swing event thread. Each combo box gets its own worker instance when it is created.

Purpose:

- Loads currency codes asynchronously so the UI can appear immediately.
- Sorts the returned codes before adding them to the dropdown.
- Keeps network or API latency out of the constructor path.

Important methods:

- [UI.CurrencyCode(JComboBox<String> comboBox)](src/main/java/com/github/blaxk3/ui/UI.java:217) stores the target combo box that will receive the loaded codes.
- [UI.doInBackground()](src/main/java/com/github/blaxk3/ui/UI.java:221) calls `new CurrencyRateAPI().getCurrencyCode()`.
- [UI.done()](src/main/java/com/github/blaxk3/ui/UI.java:227) reads the result from `get()`, sorts the array, and appends each currency code to the combo box.

This worker reports failures through SLF4J logging rather than UI dialogs, so failures are visible in logs but not directly surfaced to users.

## How It Works

### Window initialization

1. The `UI` constructor sets the window icon, title, size, layout, and exit behavior.
2. It builds the form by calling [UI.panel()](src/main/java/com/github/blaxk3/ui/UI.java:70).
3. The frame is centered and shown immediately with `setVisible(true)`.

### Building the form

[UI.panel()](src/main/java/com/github/blaxk3/ui/UI.java:70) creates two vertically stacked sub-panels:

- The first contains the amount input and the source currency selector.
- The second contains the result label, the target selector, and the action buttons.

The component factory methods create and store the widgets on the `UI` instance so later event handlers can access them.

### Currency loading

Both [UI.comboBox1()](src/main/java/com/github/blaxk3/ui/UI.java:95) and [UI.comboBox2()](src/main/java/com/github/blaxk3/ui/UI.java:103) create empty `JComboBox<String>` instances and immediately start a `CurrencyCode` worker. The worker fetches codes from `CurrencyRateAPI`, sorts them, and inserts them into the combo box after the background task completes.

### Conversion flow

The Convert button handler in [UI.button()](src/main/java/com/github/blaxk3/ui/UI.java:111) follows this sequence:

1. Read the current amount from the text field.
2. Reject empty input or a single `.` and show an error dialog.
3. Read the selected source and target currency codes.
4. Parse the text field as a `double`, wrap it as `BigDecimal`, and call `CurrencyRateAPI.convert(...)`.
5. Format the result with `DecimalFormat("#,###.###")` and show it in the label.

If the API call fails with `MalformedURLException` or `URISyntaxException`, the handler rethrows the problem as a `RuntimeException`.

### Swap and clear behavior

The other two buttons are simple UI actions:

- **Swap** exchanges the selected items of the two combo boxes.
- **Clear** empties both the input field and the result label.

## Data Model

This package does not define domain entities or DTOs of its own. The main data it handles is UI state:

- A numeric amount in the text field.
- Two selected currency codes from the combo boxes.
- A formatted conversion result in the label.
- A `String[]` of currency codes returned by the API worker.

The actual currency data model lives outside this package in `CurrencyRateAPI`, which is referenced but not defined here.

## Mermaid Relationship Diagram

```mermaid
flowchart TD
UIClass["UI"] --> PanelMethod["panel()"]
UIClass --> TextFieldMethod["textField()"]
UIClass --> LabelMethod["label()"]
UIClass --> ComboBox1Method["comboBox1()"]
UIClass --> ComboBox2Method["comboBox2()"]
UIClass --> ButtonMethod["button()"]
UIClass --> NumericFilterClass["NumericFilter"]
UIClass --> CurrencyCodeClass["CurrencyCode"]
CurrencyCodeClass --> CurrencyRateAPIClass["CurrencyRateAPI"]
ButtonMethod --> CurrencyRateAPIClass["CurrencyRateAPI"]
```

## Dependencies and Integration

### Internal dependency

- [com.github.blaxk3.api](com/github/blaxk3/api.md) — the UI depends on `CurrencyRateAPI` for both currency code loading and conversion.

### External libraries and platform APIs

- **Swing / AWT**: `JFrame`, `JPanel`, `JButton`, `JComboBox`, `JLabel`, `JTextField`, `SwingWorker`, layout managers, and `DocumentFilter` provide the desktop UI framework.
- **SLF4J**: used for error logging in `CurrencyCode.done()`.
- **Java text and math utilities**: `DecimalFormat` formats the converted amount, and `BigDecimal` is passed to the API conversion call.

### Runtime integration pattern

The package integrates directly with the API layer rather than through a separate service abstraction. That makes the UI straightforward, but it also means API changes are likely to affect this class directly.

## Notes for Developers

- **Input validation is minimal by design.** `NumericFilter` allows only digits and one decimal point. If you need support for negative values, localized decimals, or formatted numbers, this filter will need to change.
- **Conversion happens on the event thread.** The button handler calls `CurrencyRateAPI.convert(...)` directly. If conversion becomes slow, this could freeze the UI and should be moved to a background worker.
- **Currency loading is already asynchronous.** The dropdown population uses `SwingWorker`, which is the right pattern for avoiding startup lag.
- **The combo box workers add items only after completion.** If you reuse the same `JComboBox` instance across refreshes, you may need to clear existing entries before repopulating it.
- **Error handling is uneven.** The load worker logs failures, while the convert button throws a runtime exception. That suggests the user experience for API failures is not fully standardized yet.
- **The UI is tightly coupled to component fields.** Any new actions should probably follow the existing pattern of storing widget references on the `UI` instance so they can be reused by listeners.
