# 機能設計書 27-NumericUpDown

## 概要

本ドキュメントは、AvaloniaフレームワークにおけるNumericUpDownコントロールの機能設計を記載する。NumericUpDownは、数値を入力・増減するためのスピナー付きテキストボックスコントロールである。

### 本機能の処理概要

NumericUpDownは、数値入力用のテキストボックスにスピナーボタン（増減ボタン）を組み合わせたコントロールである。ユーザーはテキストボックスへの直接入力、スピナーボタンのクリック、またはマウスホイールで数値を変更できる。最小値・最大値の範囲制限、増減幅の指定、カスタム数値フォーマットをサポートする。

**業務上の目的・背景**：
業務アプリケーションにおいて数値入力は頻繁に発生する操作であり、数量、金額、年齢など様々な数値データを効率的に入力する手段が必要である。スピナーボタンにより微調整が可能で、範囲制限により入力ミスを防止できる。

**機能の利用シーン**：
- 数量・個数の入力
- 金額・価格の入力
- 年齢・年数の入力
- パーセンテージの入力
- 座標値・数値パラメータの入力

**主要な処理内容**：
1. テキストボックスへの数値入力と解析
2. スピナーボタンによる値の増減
3. マウスホイールによる値の増減
4. 最小値（Minimum）・最大値（Maximum）の範囲制限
5. 増減幅（Increment）の設定
6. 数値フォーマット（FormatString/NumberFormat）の適用
7. ValueChangedイベントの発行
8. TextConverterによるカスタム変換

**関連システム・外部連携**：
- ButtonSpinnerによるスピナーUI
- IValueConverterによるカスタム変換

**権限による制御**：
本コントロールには権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 45 | NumericUpDown | 主画面 | NumericUpDownコントロールのデモ |

## 機能種別

UI操作 / 入力コントロール / 数値入力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Value | decimal? | No | 現在の値 | Minimum〜Maximum内にクランプ |
| Minimum | decimal | No | 最小値 | デフォルト: decimal.MinValue |
| Maximum | decimal | No | 最大値 | デフォルト: decimal.MaxValue |
| Increment | decimal | No | 増減幅 | デフォルト: 1 |
| FormatString | string | No | 数値フォーマット文字列 | デフォルト: 空文字 |
| NumberFormat | NumberFormatInfo | No | 数値フォーマット情報 | デフォルト: CurrentInfo |
| ParsingNumberStyle | NumberStyles | No | 解析スタイル | デフォルト: NumberStyles.Any |
| TextConverter | IValueConverter | No | カスタムText-Value変換 | - |
| ClipValueToMinMax | bool | No | 範囲外の値をクリップ | デフォルト: false |
| AllowSpin | bool | No | スピン操作の許可 | デフォルト: true |
| ShowButtonSpinner | bool | No | スピナーボタン表示 | デフォルト: true |
| ButtonSpinnerLocation | Location | No | スピナー位置 | Left/Right |
| IsReadOnly | bool | No | 読み取り専用 | デフォルト: false |
| PlaceholderText | string | No | プレースホルダーテキスト | - |

### 入力データソース

- ユーザーによるテキスト直接入力
- スピナーボタンのクリック
- マウスホイールの回転
- キーボード（上矢印/下矢印）
- プログラムによるValue設定
- データバインディングによる数値制御

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Value | decimal? | 現在の値 |
| Text | string | フォーマットされたテキスト |

### 出力先

- UI表示（数値表示、スピナー状態）
- ValueChangedイベントの発行

## 処理フロー

### 処理シーケンス

```
1. 入力検出
   ├─ テキスト入力: TextBoxOnTextChanged
   ├─ スピナークリック: OnSpinnerSpin
   └─ マウスホイール: OnSpinnerSpin（UsingMouseWheel=true）
2. 値の変更
   ├─ 増加: DoIncrement → OnIncrement
   └─ 減少: DoDecrement → OnDecrement
3. 範囲チェック
   └─ OnCoerceValue → Minimum/Maximum範囲内に調整
4. 値の同期
   └─ SyncTextAndValueProperties
5. UI更新
   └─ テキスト表示とスピナー状態の更新
6. イベント発行
   └─ RaiseValueChangedEvent
```

### フローチャート

```mermaid
flowchart TD
    A[入力開始] --> B{入力タイプ}
    B -->|テキスト入力| C[ConvertTextToValue]
    B -->|スピン増加| D[DoIncrement]
    B -->|スピン減少| E[DoDecrement]
    C --> F{解析成功?}
    F -->|No| G[エラー/無視]
    F -->|Yes| H[OnCoerceValue]
    D --> I[Value + Increment]
    E --> J[Value - Increment]
    I --> H
    J --> H
    H --> K[Clamp to Min/Max]
    K --> L[SyncTextAndValueProperties]
    L --> M[SetValidSpinDirection]
    M --> N[UI更新]
    N --> O[RaiseValueChangedEvent]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 範囲制限 | Valueは常にMinimum〜Maximum範囲内にクランプ | 常時適用 |
| BR-002 | スピナー方向制御 | Value=Minimumの場合Decrease無効、Value=Maximumの場合Increase無効 | 常時適用 |
| BR-003 | ゼロ増分禁止 | Increment=0の場合スピン操作無効 | 常時適用 |
| BR-004 | 読み取り専用 | IsReadOnly=trueの場合スピン操作無効 | 読み取り専用時 |
| BR-005 | 双方向バインディング | Value/Textはデフォルトで TwoWayバインディング | 常時適用 |
| BR-006 | フォーカス時全選択 | フォーカス取得時にテキスト全体を選択 | フォーカス取得時 |

### 計算ロジック

値の増減：
```
// 増加
newValue = Value.HasValue ? Value.Value + Increment : (IsSet(MinimumProperty) ? Minimum : 0)
Value = Clamp(newValue, Minimum, Maximum)

// 減少
newValue = Value.HasValue ? Value.Value - Increment : (IsSet(MaximumProperty) ? Maximum : 0)
Value = Clamp(newValue, Minimum, Maximum)
```

有効スピン方向：
```
validDirections = None
if (Increment != 0 && !IsReadOnly) {
    if (Value < Maximum) validDirections |= Increase
    if (Value > Minimum) validDirections |= Decrease
}
```

## データベース操作仕様

本コントロールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無効な数値形式 | テキスト入力が数値として解析不可 | 例外を捕捉し、値を変更しない |
| - | 範囲外の値 | ClipValueToMinMax=falseで範囲外の値を入力 | ValidateMinMaxで例外スロー |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- スピン操作のレスポンスは即座に行われる必要がある
- テキスト入力時の数値解析は入力完了時（フォーカスロスト時）に実行

## セキュリティ考慮事項

本コントロールにはセキュリティ上の特別な考慮事項はない。

## 備考

- decimal型を使用しているため、財務計算などの精度が求められる用途に適している
- TextConverterを使用することで、16進数表示などのカスタムフォーマットが可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

NumericUpDown関連の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | プロパティ定義（1-170行目） |
| 1-2 | Spinner.cs | `src/Avalonia.Controls/ButtonSpinner/Spinner.cs` | スピナー基底クラス |
| 1-3 | ButtonSpinner.cs | `src/Avalonia.Controls/ButtonSpinner/ButtonSpinner.cs` | ボタンスピナーコントロール |

**読解のコツ**: NumericUpDownはTemplatedControlを継承し、内部でSpinner(ButtonSpinner)とTextBoxを使用している。

#### Step 2: エントリーポイントを理解する

NumericUpDownクラスの主要プロパティを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | プロパティ定義 |

**主要処理フロー**:
1. **21-23行目**: TemplatePart属性でPART_Spinner、PART_TextBoxを定義
2. **28-109行目**: AllowSpin、Increment、Minimum、Maximum、Value等のプロパティ定義
3. **424-440行目**: 静的コンストラクタでプロパティ変更ハンドラを設定

#### Step 3: テンプレート適用処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | OnApplyTemplate（458-487行目） |

**主要処理フロー**:
- **458-472行目**: TextBoxの取得とイベントハンドラ設定
- **474-487行目**: Spinnerの取得とイベントハンドラ設定

#### Step 4: 値の増減ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | OnIncrement/OnDecrement（751-787行目） |
| 4-2 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | SetValidSpinDirection（792-819行目） |

**主要処理フロー**:
- **751-766行目**: OnIncrementでValue + Incrementを計算、Clampして設定
- **771-787行目**: OnDecrementでValue - Incrementを計算、Clampして設定
- **792-819行目**: SetValidSpinDirectionでスピナーの有効方向を設定

#### Step 5: テキスト・値同期を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | SyncTextAndValueProperties（1073-1147行目） |

**主要処理フロー**:
- **1073-1076行目**: 再入防止フラグチェック
- **1084-1107行目**: テキストから値への変換と設定
- **1109-1126行目**: 値からテキストへの変換と設定

### プログラム呼び出し階層図

```
NumericUpDown
    │
    ├─ OnApplyTemplate
    │      ├─ TextBox取得・イベント登録
    │      └─ Spinner取得・イベント登録
    │
    ├─ OnSpinnerSpin
    │      ├─ DoIncrement
    │      │      └─ OnIncrement
    │      │             └─ SetCurrentValue(ValueProperty)
    │      └─ DoDecrement
    │             └─ OnDecrement
    │                    └─ SetCurrentValue(ValueProperty)
    │
    ├─ OnValueChanged
    │      ├─ SyncTextAndValueProperties
    │      ├─ SetValidSpinDirection
    │      └─ RaiseValueChangedEvent
    │
    └─ TextBoxOnTextChanged
           └─ SyncTextAndValueProperties
                  └─ ConvertTextToValue
```

### データフロー図

```
[入力]                    [処理]                         [出力]

スピナークリック ─────▶ OnSpinnerSpin
                            │
                            ├─▶ DoIncrement/DoDecrement
                            │         │
                            │    OnIncrement/OnDecrement
                            │         │
                            │    MathUtilities.Clamp
                            │         │
                            ▼         ▼
テキスト入力 ──────────▶ SyncTextAndValueProperties
                            │
                            ├─▶ ConvertTextToValue
                            │
                            ├─▶ SetValidSpinDirection ──▶ スピナー状態更新
                            │
                            └─▶ RaiseValueChangedEvent ──▶ ValueChangedイベント
                                     │
                                     ▼
                              UI更新（テキスト表示）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NumericUpDown.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs` | ソース | メインコントロールクラス |
| NumericUpDownValueChangedEventArgs.cs | `src/Avalonia.Controls/NumericUpDown/NumericUpDownValueChangedEventArgs.cs` | ソース | 値変更イベント引数 |
| Spinner.cs | `src/Avalonia.Controls/ButtonSpinner/Spinner.cs` | ソース | スピナー基底クラス |
| ButtonSpinner.cs | `src/Avalonia.Controls/ButtonSpinner/ButtonSpinner.cs` | ソース | ボタンスピナーコントロール |
| SpinEventArgs.cs | `src/Avalonia.Controls/ButtonSpinner/SpinEventArgs.cs` | ソース | スピンイベント引数 |
| NumericUpDown.xaml | `src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml` | テンプレート | Fluentテーマのテンプレート |
