# 機能設計書 21-ScrollViewer

## 概要

本ドキュメントは、AvaloniaフレームワークにおけるScrollViewerコントロールの機能設計を記載する。ScrollViewerは、コンテンツがビューポートサイズを超える場合にスクロール機能を提供するコンテナコントロールである。

### 本機能の処理概要

ScrollViewerは、内部コンテンツが表示領域より大きい場合に、水平・垂直スクロールを提供するコンテナコントロールである。ListBox、TreeView、DataGridなど多くのUIコントロールの内部で使用され、大量データの効率的な表示を可能にする。

**業務上の目的・背景**：
アプリケーション開発において、画面サイズに収まらない大量のコンテンツを表示する必要がある場合が多々存在する。ScrollViewerは、限られた表示領域内でコンテンツ全体にアクセスする手段を提供し、ユーザーエクスペリエンスを向上させる基盤コンポーネントである。

**機能の利用シーン**：
- 長いフォームの表示（入力フィールドが多い場合）
- データグリッドでの大量レコード表示
- 画像ギャラリーでの水平スクロール
- ドキュメントビューアでのテキストスクロール
- ListBox/TreeViewでの項目一覧表示

**主要な処理内容**：
1. スクロールバーの表示・非表示制御（Auto/Visible/Hidden/Disabled）
2. コンテンツExtent（全体サイズ）とViewport（表示領域）の管理
3. スクロールオフセットの計算と更新
4. マウスホイール、キーボード、タッチによるスクロール操作
5. フォーカス変更時の自動スクロール（BringIntoView）
6. スナップポイントによるスクロール位置の調整
7. 慣性スクロール（IsScrollInertiaEnabled）
8. 遅延スクロール（IsDeferredScrollingEnabled）

**関連システム・外部連携**：
- ILogicalScrollable インターフェースを実装するコントロールとの連携
- IScrollAnchorProvider による仮想化リスト内のアンカー管理

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | DataGrid | 主画面 | 大量データのスクロール表示 |
| 48 | RefreshContainer | 主画面 | プルダウンリフレッシュ機能 |
| 50 | ScrollViewer | 主画面 | ScrollViewerコントロールのデモ |
| 52 | SplitView | 主画面 | 分割表示パネルでのスクロール |
| 97 | ScrollBar | 主画面 | ScrollBarのテスト |

## 機能種別

UI操作 / コンテナコントロール / スクロール管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Content | object | No | スクロール対象のコンテンツ | - |
| Offset | Vector | No | 現在のスクロール位置 | X/Yともに0以上、最大値以下にクランプ |
| HorizontalScrollBarVisibility | ScrollBarVisibility | No | 水平スクロールバーの表示状態 | Disabled/Auto/Visible/Hidden |
| VerticalScrollBarVisibility | ScrollBarVisibility | No | 垂直スクロールバーの表示状態 | Disabled/Auto/Visible/Hidden |
| HorizontalSnapPointsType | SnapPointsType | No | 水平スナップポイントの動作 | None/Mandatory/OptionalSingle |
| VerticalSnapPointsType | SnapPointsType | No | 垂直スナップポイントの動作 | None/Mandatory/OptionalSingle |
| AllowAutoHide | bool | No | スクロールバーの自動非表示 | デフォルト: true |
| IsScrollChainingEnabled | bool | No | スクロールチェーンの有効化 | デフォルト: true |
| IsScrollInertiaEnabled | bool | No | 慣性スクロールの有効化 | デフォルト: true |
| IsDeferredScrollingEnabled | bool | No | 遅延スクロールの有効化 | デフォルト: false |
| BringIntoViewOnFocusChange | bool | No | フォーカス時の自動スクロール | デフォルト: true |

### 入力データソース

- ユーザーによるマウスホイール操作
- スクロールバーのドラッグ操作
- キーボードのPageUp/PageDown操作
- タッチスクリーンでのスワイプ操作
- プログラムによるOffset設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Extent | Size | コンテンツの全体サイズ |
| Viewport | Size | 現在表示されている領域のサイズ |
| Offset | Vector | 現在のスクロール位置 |
| ScrollBarMaximum | Vector | スクロールバーの最大値 |
| LargeChange | Size | ページスクロール量 |
| SmallChange | Size | 行スクロール量（デフォルト16px） |
| IsExpanded | bool | スクロールバーが展開状態かどうか |

### 出力先

- UI表示（スクロール位置の視覚的反映）
- ScrollChangedイベントの発行

## 処理フロー

### 処理シーケンス

```
1. コンテンツ配置
   └─ 子要素のMeasure/Arrangeを実行
2. Extent/Viewport計算
   └─ コンテンツサイズと表示領域を算出
3. スクロール入力検出
   └─ マウスホイール/キーボード/タッチ/スクロールバー操作
4. オフセット更新
   └─ CoerceOffsetにより範囲内にクランプ
5. スクロールバー更新
   └─ スクロールバー位置の同期
6. ScrollChangedイベント発行
   └─ 変更通知
```

### フローチャート

```mermaid
flowchart TD
    A[スクロール入力] --> B{入力タイプ判定}
    B -->|マウスホイール| C[SmallChangeで増減]
    B -->|PageUp/Down| D[LargeChangeで増減]
    B -->|スクロールバードラッグ| E[直接オフセット設定]
    C --> F[CoerceOffset]
    D --> F
    E --> F
    F --> G{範囲内か?}
    G -->|Yes| H[オフセット更新]
    G -->|No| I[範囲内にクランプ]
    I --> H
    H --> J[UI更新]
    J --> K[ScrollChangedイベント発行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | オフセットクランプ | Offsetは常に0以上、ScrollBarMaximum以下に制限される | 常時適用 |
| BR-002 | スクロールバー自動表示 | ScrollBarVisibility=Autoの場合、コンテンツがViewportを超えた時のみ表示 | Auto設定時 |
| BR-003 | スクロールチェーン | 子要素のスクロール限界到達時に親ScrollViewerに伝播 | IsScrollChainingEnabled=true |
| BR-004 | フォーカス追従 | フォーカス変更時に要素が表示領域内に来るよう自動スクロール | BringIntoViewOnFocusChange=true |

### 計算ロジック

```
ScrollBarMaximum.X = Max(Extent.Width - Viewport.Width, 0)
ScrollBarMaximum.Y = Max(Extent.Height - Viewport.Height, 0)
LargeChange = Viewport（ILogicalScrollable未使用時）
SmallChange = 16px（デフォルト）または ILogicalScrollable.ScrollSize
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 範囲外オフセット | Offsetに範囲外の値が設定された | CoerceOffsetにより自動的に範囲内にクランプ |
| - | 無効なスクロールバー設定 | 無効なScrollBarVisibility値 | enum制約により発生しない |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- スクロール操作は60fps（16.67ms以内）でレンダリングする必要がある
- 大量データ表示時はVirtualizingStackPanelと組み合わせて使用すべき
- 慣性スクロール時も滑らかなアニメーションを維持

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

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

## 備考

- ILogicalScrollableを実装するコントロール（VirtualizingStackPanelなど）では、論理スクロールが使用される
- アンカー機能により、動的にコンテンツが変化してもスクロール位置を維持できる

---

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

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

### 推奨読解順序

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

スクロールに関連するインターフェースと型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IScrollable.cs | `src/Avalonia.Controls/IScrollable.cs` | スクロール可能なコントロールのインターフェース定義 |
| 1-2 | IScrollAnchorProvider.cs | `src/Avalonia.Controls/IScrollAnchorProvider.cs` | アンカー管理インターフェース |
| 1-3 | ScrollBarVisibility.cs | `src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs` | スクロールバー表示状態の列挙型 |

**読解のコツ**: Avaloniaでは、Attachedプロパティを多用してスクロール設定を子孫要素に伝播している。

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

ScrollViewerクラスの主要プロパティと初期化処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ScrollViewer.cs | `src/Avalonia.Controls/ScrollViewer.cs` | メインクラス定義、プロパティ宣言 |

**主要処理フロー**:
1. **17-18行目**: クラス宣言、ContentControlを継承しIScrollable, IScrollAnchorProviderを実装
2. **22-157行目**: 各種AttachedPropertyとDirectPropertyの定義
3. **176-179行目**: コンストラクタでLayoutUpdatedイベントハンドラを登録
4. **687-706行目**: CoerceOffset静的メソッドでオフセット値をクランプ

#### Step 3: スクロールバー連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ScrollViewer.cs | `src/Avalonia.Controls/ScrollViewer.cs` | OnApplyTemplate, SubscribeToScrollBars |

**主要処理フロー**:
- **805-812行目**: OnApplyTemplateでスクロールバーの購読を設定
- **819-851行目**: SubscribeToScrollBarsメソッドで水平・垂直スクロールバーの展開状態を監視

#### Step 4: スクロール操作処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ScrollViewer.cs | `src/Avalonia.Controls/ScrollViewer.cs` | スクロールメソッド群 |

**主要処理フロー**:
- **396-441行目**: LineUp/LineDown/LineLeft/LineRight/PageUp/PageDown/PageLeft/PageRight/ScrollToHome/ScrollToEndメソッド
- **777-789行目**: OnKeyDownでPageUp/PageDownキー処理

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

```
ScrollViewer
    │
    ├─ OnApplyTemplate
    │      └─ SubscribeToScrollBars
    │             └─ OnScrollBarExpandedChanged
    │
    ├─ OnPropertyChanged
    │      ├─ CalculatedPropertiesChanged
    │      │      └─ SetAndRaise (SmallChange/LargeChange)
    │      └─ CoerceValue(OffsetProperty)
    │
    ├─ OnGotFocus
    │      └─ BringIntoView
    │
    ├─ OnKeyDown
    │      ├─ PageUp
    │      └─ PageDown
    │
    └─ OnLayoutUpdated
           └─ RaiseScrollChanged
```

### データフロー図

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

マウスホイール  ───────┐
                      │
キーボード    ────────┼──▶ OnPropertyChanged ──▶ CoerceOffset
                      │         │
スクロールバー ───────┤         ▼
                      │    CalculatedPropertiesChanged
タッチスワイプ ───────┘         │
                               ▼
                      RaiseScrollChanged ──▶ ScrollChangedイベント
                               │
                               ▼
                         UI更新（表示位置変更）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ScrollViewer.cs | `src/Avalonia.Controls/ScrollViewer.cs` | ソース | メインコントロールクラス |
| ScrollBar.cs | `src/Avalonia.Controls/Primitives/ScrollBar.cs` | ソース | スクロールバーコントロール |
| ScrollContentPresenter.cs | `src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs` | ソース | コンテンツ表示プレゼンター |
| IScrollable.cs | `src/Avalonia.Controls/IScrollable.cs` | ソース | スクロールインターフェース |
| ILogicalScrollable.cs | `src/Avalonia.Controls/Primitives/ILogicalScrollable.cs` | ソース | 論理スクロールインターフェース |
| ScrollChangedEventArgs.cs | `src/Avalonia.Controls/ScrollChangedEventArgs.cs` | ソース | スクロール変更イベント引数 |
| ScrollViewer.xaml | `src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml` | テンプレート | Fluentテーマのテンプレート |
