# 機能設計書 14-Slider

## 概要

本ドキュメントは、Avalonia UIフレームワークにおけるSliderコントロールの機能設計を記述する。Sliderは指定範囲内の数値をドラッグ操作やキー操作で選択するためのコントロールである。

### 本機能の処理概要

Sliderは、Track上のThumbをドラッグすることで、MinimumからMaximumの範囲内の数値を選択できるコントロールである。水平・垂直両方の向きをサポートし、目盛り（Tick）表示やスナップ機能も備えている。

**業務上の目的・背景**：音量調整、明るさ調整、ズームレベル設定など、連続的な数値を直感的に調整したいシナリオは多い。Sliderはこれらのユースケースに対応し、テキスト入力より視覚的でインタラクティブな数値入力手段を提供する。

**機能の利用シーン**：
- メディアプレーヤーの音量・シーク調整
- 画像編集での明るさ・コントラスト調整
- 設定画面での数値パラメータ調整
- ズームレベルの制御

**主要な処理内容**：
1. Thumbのドラッグによる値の変更
2. トラッククリックによる値の設定
3. キーボード操作（矢印キー、PageUp/Down、Home/End）
4. 目盛り表示とスナップ機能
5. 水平・垂直の向き切り替え
6. 方向反転（IsDirectionReversed）

**関連システム・外部連携**：RangeBaseを継承し、Minimum/Maximum/Value/SmallChange/LargeChangeプロパティを持つ。TrackコントロールとThumbコントロールと連携して動作。

**権限による制御**：特になし。IsEnabledプロパティで有効/無効を制御可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 51 | Slider | 主画面 | Sliderコントロールのデモ。範囲指定と刻み幅設定 |
| 108 | Slider | テスト画面 | スライダーのテスト |

## 機能種別

入力コントロール / 数値範囲選択

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Minimum | double | No | 最小値 | デフォルト: 0、NaN/Infinity不可 |
| Maximum | double | No | 最大値 | デフォルト: 100、NaN/Infinity不可 |
| Value | double | No | 現在の値 | Minimum〜Maximumにクランプ |
| SmallChange | double | No | 矢印キーでの変化量 | デフォルト: 1 |
| LargeChange | double | No | PageUp/Downでの変化量 | デフォルト: 10 |
| Orientation | Orientation | No | 向き（Horizontal/Vertical） | デフォルト: Horizontal |
| IsDirectionReversed | bool | No | 方向反転 | デフォルト: false |
| IsSnapToTickEnabled | bool | No | 目盛りへのスナップ | デフォルト: false |
| TickFrequency | double | No | 目盛り間隔 | デフォルト: 0 |
| Ticks | AvaloniaList<double> | No | 目盛り位置のリスト | - |
| TickPlacement | TickPlacement | No | 目盛り表示位置 | None/TopLeft/BottomRight/Outside |

### 入力データソース

- Valueプロパティへのデータバインディング
- XAMLでのプロパティ設定
- マウス/タッチ操作
- キーボード操作

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Value | double | 現在の値 |

### 出力先

- ValueChangedイベントによる値変更通知
- プロパティバインディングによるViewModel更新

## 処理フロー

### 処理シーケンス

```
1. ユーザー操作
   └─ ドラッグ/クリック/キー入力
2. 値の計算
   └─ 位置から値への変換、またはSmallChange/LargeChange適用
3. スナップ処理
   └─ IsSnapToTickEnabled時は最寄りの目盛りにスナップ
4. 値のクランプ
   └─ Minimum〜Maximum範囲に制限
5. Value更新
   └─ プロパティ更新、ValueChangedイベント発火
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザー操作] --> B{操作種別}
    B -->|ドラッグ| C[位置から値計算]
    B -->|クリック| D[クリック位置から値計算]
    B -->|キー入力| E{キー種別}
    E -->|矢印| F[Value +/- SmallChange]
    E -->|PageUp/Down| G[Value +/- LargeChange]
    E -->|Home| H[Value = Minimum]
    E -->|End| I[Value = Maximum]
    C --> J{IsSnapToTick?}
    D --> J
    F --> J
    G --> J
    J -->|Yes| K[SnapToTick]
    J -->|No| L[値をクランプ]
    K --> L
    H --> L
    I --> L
    L --> M[Value更新]
    M --> N[ValueChanged発火]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 値のクランプ | ValueはMinimum以上Maximum以下に制限される | 常時 |
| BR-02 | スナップ | IsSnapToTickEnabled時、最寄りの目盛りに値を合わせる | スナップ有効時 |
| BR-03 | 方向反転 | IsDirectionReversed時、増減方向が逆転 | 方向反転有効時 |
| BR-04 | 増分計算 | 矢印キーはSmallChange、Page系キーはLargeChangeで増減 | キー操作時 |

### 計算ロジック

MoveToPoint()のロジック：
```csharp
var logicalPos = (trackPos - thumbLength * 0.5) / trackLength;
logicalPos = Clamp(logicalPos, 0.0, 1.0);
var invert = Orientation == Horizontal ?
    IsDirectionReversed ? 1 : 0 :
    IsDirectionReversed ? 0 : 1;
var calcVal = Math.Abs(invert - logicalPos);
var finalValue = calcVal * (Maximum - Minimum) + Minimum;
```

SnapToTick()のロジック：
```csharp
// Ticksコレクションがある場合、最寄りのTickを探す
// なければTickFrequencyから計算
previous = Minimum + Math.Round((value - Minimum) / TickFrequency) * TickFrequency;
// previousとnextの中間より後ろならnext、前ならpreviousを採用
```

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

### 操作別データベース影響一覧

該当なし（UIコントロール）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 値の無視 | NaN/Infinityを設定 | 前の有効な値を維持 |

### リトライ仕様

該当なし

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

該当なし（UIコントロール）

## パフォーマンス要件

- ドラッグ中の値計算はリアルタイムで行われるため、軽量な実装
- 許容誤差（Tolerance）は0.0001

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

特になし（UIコントロールとして汎用的に使用可能）

## 備考

- XYナビゲーションモード（ゲームパッド等）では、Enterキーでフォーカスを「エンゲージ」してから矢印キーで値を変更
- PseudoClasses: :horizontal, :vertical, :pressed

---

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

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

### 推奨読解順序

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

Sliderの基盤となるRangeBaseクラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RangeBase.cs | `src/Avalonia.Controls/Primitives/RangeBase.cs` | Minimum/Maximum/Value/SmallChange/LargeChangeプロパティ |

**読解のコツ**: RangeBaseはTemplatedControlを継承し、値の範囲管理と変更通知の基盤を提供する。CoerceValue()で値のクランプが行われる。

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

Sliderクラスの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Slider.cs | `src/Avalonia.Controls/Slider.cs` | 向き、目盛り、スナップ、キーボード操作 |

**主要処理フロー**:
1. **50行目**: RangeBaseを継承
2. **55-80行目**: 向き、目盛り関連プロパティ定義
3. **196-229行目**: OnApplyTemplate - Track、Increase/Decreaseボタンの取得
4. **232-286行目**: OnKeyDown - キーボードナビゲーション
5. **288-342行目**: MoveToNextTick - 目盛り間の移動
6. **372-394行目**: MoveToPoint - ポインター位置から値を計算
7. **434-476行目**: SnapToTick - 目盛りへのスナップ

#### Step 3: テンプレートパーツを理解する

Trackコントロールとの連携。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Track.cs | `src/Avalonia.Controls/Primitives/Track.cs` | Thumbの配置、ドラッグ処理 |

**主要処理フロー**:
- TrackはThumbを含み、Thumbのドラッグをハンドリング
- SliderはTrackのイベントを購読して値を更新

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

```
Slider
    │
    ├─ RangeBase (基底クラス)
    │      ├─ Minimum/Maximum/Value
    │      ├─ SmallChange/LargeChange
    │      └─ ValueChangedイベント
    │
    ├─ Track (テンプレートパーツ)
    │      └─ Thumb
    │             └─ ドラッグ処理
    │
    ├─ OnKeyDown()
    │      ├─ MoveToNextTick()
    │      └─ 矢印/Page/Home/End
    │
    ├─ MoveToPoint()
    │      └─ 位置から値を計算
    │
    └─ SnapToTick()
           └─ 目盛りへのスナップ
```

### データフロー図

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

ドラッグ ───▶ TrackPressed/TrackMoved ───▶ MoveToPoint()
                           │
キー入力 ───▶ OnKeyDown ───▶ MoveToNextTick()
                           │
                           ▼
                    SnapToTick()（オプション）
                           │
                           ▼
                    CoerceValue（クランプ）
                           │
                           ▼
                    Value更新 ───▶ ValueChanged
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Slider.cs | `src/Avalonia.Controls/Slider.cs` | ソース | Sliderコントロール本体 |
| RangeBase.cs | `src/Avalonia.Controls/Primitives/RangeBase.cs` | ソース | 基底クラス（範囲値管理） |
| Track.cs | `src/Avalonia.Controls/Primitives/Track.cs` | ソース | トラックコントロール |
| Thumb.cs | `src/Avalonia.Controls/Primitives/Thumb.cs` | ソース | ドラッグ可能なつまみ |
| TickBar.cs | `src/Avalonia.Controls/Primitives/TickBar.cs` | ソース | 目盛り表示 |
| SliderAutomationPeer.cs | `src/Avalonia.Controls/Automation/Peers/SliderAutomationPeer.cs` | ソース | UIオートメーション対応 |
