# FTRNumericUpDown – Customer Usage Guide

## Overview

`FTRNumericUpDown` is a Windows Forms numeric input control for entering and adjusting numeric values.

It provides:

* Numeric value input
* Increment and decrement buttons
* Minimum and maximum value limits
* Configurable increment steps
* Decimal value display
* Optional thousands separators
* Text alignment
* Read-only text editing
* Keyboard support
* Mouse-wheel support
* Press-and-hold auto-repeat for the increment/decrement buttons
* Custom button icons and images
* Appearance customization
* FTR theme support

The control is available in the `FTRControls` namespace and can be used from the **FTR Controls** toolbox.

The default event is `ValueChanged`.

---

## Basic Usage

After adding the FTR Controls assembly to your Windows Forms project, add `FTRNumericUpDown` to your form from the toolbox or create it programmatically.

### Example

```csharp
var quantity = new FTRNumericUpDown
{
    Minimum = 0,
    Maximum = 999,
    Value = 1,
    Increment = 1
};

quantity.ValueChanged += (sender, e) =>
{
    UpdateTotal(quantity.Value);
};
```

The control automatically keeps the value within the configured `Minimum` and `Maximum` range.

---

# Core Properties

## Value

Gets or sets the current numeric value.

```csharp
quantity.Value = 10;
decimal currentValue = quantity.Value;
```

The value is automatically constrained to the current `Minimum` and `Maximum`.

For example, if the maximum is `100` and you assign:

```csharp
quantity.Value = 150;
```

the resulting value will be `100`.

If the assigned value is below the minimum, it is similarly adjusted to the minimum.

Changing `Value` raises the `ValueChanged` event only when the actual value changes.

---

## Minimum

Defines the lowest value allowed by the control.

Default:

```text
0
```

Example:

```csharp
quantity.Minimum = 0;
```

If the current value is below the new minimum, the current value is automatically adjusted to the new minimum.

If `Minimum` is set higher than the current `Maximum`, the control automatically adjusts `Maximum` to the same value.

---

## Maximum

Defines the highest value allowed by the control.

Default:

```text
100
```

Example:

```csharp
quantity.Maximum = 1000;
```

If the current value is above the new maximum, the current value is automatically adjusted to the new maximum.

If `Maximum` is set lower than the current `Minimum`, the control automatically adjusts `Minimum` to the same value.

---

## Increment

Defines how much the value changes when the user increments or decrements it.

Default:

```text
1
```

Example:

```csharp
quantity.Increment = 0.5m;
```

With an increment of `0.5`:

* Pressing `+` increases the value by `0.5`
* Pressing `−` decreases the value by `0.5`
* Pressing the Up Arrow increases the value by `0.5`
* Pressing the Down Arrow decreases the value by `0.5`
* Using the mouse wheel changes the value by `0.5`

`Increment` must be greater than zero.

For example:

```csharp
quantity.Increment = 0;
```

is invalid and throws `ArgumentOutOfRangeException`.

---

# Display and Input Properties

## DecimalPlaces

Controls the number of decimal digits displayed.

Default:

```text
0
```

Example:

```csharp
price.DecimalPlaces = 2;
```

If the value is:

```text
12.5
```

the displayed value becomes:

```text
12.50
```

Values below zero are automatically treated as zero.

---

## ThousandsSeparator

Controls whether digit-grouping separators are displayed.

Default:

```text
false
```

Example:

```csharp
amount.ThousandsSeparator = true;
```

When enabled, the value is displayed using the thousands-separator rules of the current system culture.

For example, depending on the current culture, a value such as `1234567.89` may be displayed with digit grouping.

---

## TextAlign

Controls the horizontal alignment of the numeric text.

Available values are the standard Windows Forms `HorizontalAlignment` values:

```csharp
HorizontalAlignment.Left
HorizontalAlignment.Center
HorizontalAlignment.Right
```

Example:

```csharp
quantity.TextAlign = HorizontalAlignment.Right;
```

The default alignment is:

```text
Center
```

---

## ReadOnly

Controls whether the user can manually edit the numeric text.

Default:

```text
false
```

Example:

```csharp
quantity.ReadOnly = true;
```

When `ReadOnly` is `true`:

* Direct keyboard editing of the text is disabled.
* Up/Down keyboard value changes are disabled.
* Mouse-wheel value changes are disabled.
* Programmatic changes to `Value` are still allowed.
* The `+` and `−` buttons remain usable.

Therefore, `ReadOnly` should be considered **text-entry read-only**, rather than a complete interaction lock.

If the entire control must be disabled, use the standard Windows Forms `Enabled` property:

```csharp
quantity.Enabled = false;
```

---

# User Interaction

## Increment and Decrement Buttons

The control provides two buttons:

* `−` decreases the value by `Increment`
* `+` increases the value by `Increment`

Example:

```csharp
quantity.Increment = 1;
```

If the current value is `10`:

* Clicking `−` changes it to `9`
* Clicking `+` changes it to `11`

The value never exceeds `Maximum` or goes below `Minimum`.

---

## Press and Hold

The increment/decrement buttons support automatic repetition when held down.

The control initially waits approximately **400 milliseconds** before starting repeated changes. Once repetition starts, the value is changed approximately every **50 milliseconds** while the button remains pressed.

This is useful when the user needs to move through a large numeric range quickly.

---

## Keyboard Support

When the control is enabled and not read-only:

### Up Arrow

Increases the value by `Increment`.

```text
Up → Value + Increment
```

### Down Arrow

Decreases the value by `Increment`.

```text
Down → Value - Increment
```

### Enter

Commits the currently typed numeric value.

This is useful when the user manually enters a value and wants to confirm it immediately.

---

# Mouse Wheel Support

The control supports mouse-wheel value changes.

When enabled and not read-only:

* Scrolling upward increases the value by `Increment`.
* Scrolling downward decreases the value by `Increment`.

Example:

```csharp
quantity.Increment = 5;
```

Each applicable mouse-wheel action changes the value by `5`.

---

# Numeric Text Input

The text area accepts numeric input according to the current system culture.

The control uses `CultureInfo.CurrentCulture` for parsing and formatting.

This means the accepted decimal separator and displayed number format depend on the application's current culture.

For example, applications using cultures with a comma as the decimal separator can use the culture-specific decimal separator when entering decimal values.

If the entered text cannot be parsed as a valid number, the control restores the previous valid value.

---

# ValueChanged Event

`ValueChanged` is raised when the numeric value actually changes.

Example:

```csharp
quantity.ValueChanged += Quantity_ValueChanged;

private void Quantity_ValueChanged(
    object sender,
    FTRNumericValueChangedEventArgs e)
{
    Console.WriteLine($"Old: {e.OldValue}");
    Console.WriteLine($"New: {e.NewValue}");
}
```

The event arguments provide both values:

### OldValue

The value before the change.

### NewValue

The value after the change.

This makes it possible to determine exactly what changed without storing the previous value separately.

---

# Appearance Customization

The control supports several appearance-related properties.

Some appearance features are **Premium Features** and require an appropriate FTR Controls license.

If a premium property is used without the required license, the control requests activation and does not apply the requested property change.

---

## FillColor — Premium

Controls the background color of the editable value area.

Example:

```csharp
quantity.FillColor = Color.White;
```

When the control is read-only or disabled, the displayed background may use a system-defined color instead.

---

## BorderColor — Premium

Controls the color of the outer border.

Example:

```csharp
quantity.BorderColor = Color.Gray;
```

---

## ButtonsColor — Premium

Controls the normal background color of the increment/decrement buttons.

Example:

```csharp
quantity.ButtonsColor = Color.LightGray;
```

---

## IconColor — Premium

Controls the color used for text-based button icons.

Example:

```csharp
quantity.IconColor = Color.DarkGray;
```

This property applies to text-based icons. When a custom image is supplied, the image itself is rendered.

---

## ButtonWidth — Premium

Controls the width of the increment and decrement buttons.

Default:

```text
30
```

Example:

```csharp
quantity.ButtonWidth = 36;
```

The minimum supported value is `10`.

Changing this property also affects the minimum width required by the control.

---

## BorderRadius — Premium

Controls the corner radius of the control.

Default:

```text
6
```

Example:

```csharp
quantity.BorderRadius = 10;
```

A value below zero is automatically treated as zero.

The actual rendered radius is automatically constrained to fit the control's dimensions.

---

# Button Icons

The control supports both text-based icons and custom images.

## MinusIcon — Premium

Defines the text displayed on the decrement button when no custom decrement image is assigned.

Default:

```text
-
```

Example:

```csharp
quantity.MinusIcon = "−";
```

---

## PlusIcon — Premium

Defines the text displayed on the increment button when no custom increment image is assigned.

Default:

```text
+
```

Example:

```csharp
quantity.PlusIcon = "+";
```

---

## IconFont — Premium

Defines the font used to render text-based button icons.

This property is used when `MinusImage` and/or `PlusImage` are not assigned.

Example:

```csharp
quantity.IconFont = new Font("Segoe UI Symbol", 14);
```

The supplied font must not be `null`.

---

## MinusImage — Premium

Provides a custom image for the decrement button.

Example:

```csharp
quantity.MinusImage = minusImage;
```

When an image is assigned, it is rendered instead of the text defined by `MinusIcon`.

---

## PlusImage — Premium

Provides a custom image for the increment button.

Example:

```csharp
quantity.PlusImage = plusImage;
```

When an image is assigned, it is rendered instead of the text defined by `PlusIcon`.

---

## IconImageSize — Premium

Controls the rendering size of custom button images.

Default:

```text
16 × 16
```

Example:

```csharp
quantity.IconImageSize = new Size(20, 20);
```

The setting applies to both `MinusImage` and `PlusImage`.

---

# Themes

`FTRNumericUpDown` supports the FTR Controls global theme system.

When the control is created, it applies the currently active FTR theme.

The control supports the following theme modes provided by the FTR Controls theme system:

* Light
* Dark
* Color
* Duotone

The control's colors are automatically updated when the corresponding theme is applied.

If necessary, the control also exposes:

```csharp
quantity.ApplyTheme();
```

This can be used to reapply the current FTR theme to the control.

---

# Sizing and Layout

The control enforces minimum dimensions to ensure that the text area and both buttons remain usable.

The minimum height is:

```text
25 pixels
```

The minimum width is calculated as:

```text
(ButtonWidth × 2) + 30
```

With the default `ButtonWidth` of `30`, the minimum width is therefore:

```text
90 pixels
```

The default control size is approximately:

```text
120 × 35 pixels
```

If a smaller size is assigned, the control automatically adjusts itself to its supported minimum dimensions.

---

# Recommended Configuration Examples

## Integer Quantity

```csharp
var quantity = new FTRNumericUpDown
{
    Minimum = 0,
    Maximum = 100,
    Value = 1,
    Increment = 1,
    DecimalPlaces = 0
};
```

---

## Decimal Amount

```csharp
var amount = new FTRNumericUpDown
{
    Minimum = 0m,
    Maximum = 100000m,
    Value = 1250.50m,
    Increment = 0.50m,
    DecimalPlaces = 2,
    ThousandsSeparator = true,
    TextAlign = HorizontalAlignment.Right
};
```

---

## Read-Only Display with Button Adjustment

```csharp
var counter = new FTRNumericUpDown
{
    Minimum = 0,
    Maximum = 999,
    Value = 50,
    Increment = 5,
    ReadOnly = true
};
```

In this configuration, the user cannot type directly into the value field, but can still use the `+` and `−` buttons to change the value.

---

# Premium Features Summary

The following properties require the appropriate FTR Controls license:

| Property        | Purpose                          |
| --------------- | -------------------------------- |
| `BorderRadius`  | Rounded corners                  |
| `BorderColor`   | Control border color             |
| `FillColor`     | Value-area background color      |
| `ButtonsColor`  | Button background color          |
| `IconColor`     | Text icon color                  |
| `ButtonWidth`   | Increment/decrement button width |
| `MinusIcon`     | Custom decrement-button text     |
| `PlusIcon`      | Custom increment-button text     |
| `IconFont`      | Font for text-based icons        |
| `MinusImage`    | Custom decrement-button image    |
| `PlusImage`     | Custom increment-button image    |
| `IconImageSize` | Custom image rendering size      |

Core numeric functionality such as `Value`, `Minimum`, `Maximum`, `Increment`, `DecimalPlaces`, `ThousandsSeparator`, `TextAlign`, and `ReadOnly` is available without these premium appearance/icon features.

---

# Typical Customer Usage

A typical application can configure the control with the numeric range and step required by the business logic:

```csharp
var quantity = new FTRNumericUpDown
{
    Minimum = 1,
    Maximum = 999,
    Value = 10,
    Increment = 1,
    DecimalPlaces = 0,
    ThousandsSeparator = false
};

quantity.ValueChanged += (sender, e) =>
{
    // React to the new value.
    UpdateQuantity(e.NewValue);
};
```

The application does not need to manually enforce the configured numeric range. The control automatically keeps `Value` within `Minimum` and `Maximum`.

---

# Quick Reference

| Property / Event     | Type                  |         Default | Premium |
| -------------------- | --------------------- | --------------: | :-----: |
| `Value`              | `decimal`             |             `0` |    No   |
| `Minimum`            | `decimal`             |             `0` |    No   |
| `Maximum`            | `decimal`             |           `100` |    No   |
| `Increment`          | `decimal`             |             `1` |    No   |
| `DecimalPlaces`      | `int`                 |             `0` |    No   |
| `ThousandsSeparator` | `bool`                |         `false` |    No   |
| `TextAlign`          | `HorizontalAlignment` |        `Center` |    No   |
| `ReadOnly`           | `bool`                |         `false` |    No   |
| `FillColor`          | `Color`               | Theme-dependent |   Yes   |
| `BorderColor`        | `Color`               | Theme-dependent |   Yes   |
| `ButtonsColor`       | `Color`               | Theme-dependent |   Yes   |
| `IconColor`          | `Color`               | Theme-dependent |   Yes   |
| `ButtonWidth`        | `int`                 |            `30` |   Yes   |
| `BorderRadius`       | `int`                 |             `6` |   Yes   |
| `MinusIcon`          | `string`              |           `"-"` |   Yes   |
| `PlusIcon`           | `string`              |           `"+"` |   Yes   |
| `IconFont`           | `Font`                |  Segoe UI, 14pt |   Yes   |
| `MinusImage`         | `Image`               |          `null` |   Yes   |
| `PlusImage`          | `Image`               |          `null` |   Yes   |
| `IconImageSize`      | `Size`                |       `16 × 16` |   Yes   |
| `ValueChanged`       | Event                 |               — |    No   |

---

# Important Behavior Notes

1. `Value` is always constrained to the configured `Minimum` and `Maximum`.
2. `Increment` must be greater than zero.
3. Numeric parsing and formatting use the application's current culture.
4. Invalid manually entered numeric text is replaced with the last valid value.
5. `ReadOnly` disables direct text editing, keyboard adjustment, and mouse-wheel adjustment, but does not disable the `+` and `−` buttons.
6. Setting `Enabled` to `false` disables user interaction with the control.
7. Holding an increment/decrement button starts automatic repeated changes.
8. `ValueChanged` is raised only when the actual value changes.
9. `ValueChanged` provides both the previous and new values through `FTRNumericValueChangedEventArgs`.
10. Premium appearance and icon properties require the appropriate FTR Controls license.
11. Custom `Image` objects supplied through `MinusImage` and `PlusImage` are not owned or disposed by the control. The application is responsible for disposing them when they are no longer needed.
12. The control automatically maintains minimum dimensions required by its layout.
