# 機能設計書 50-SetScrollHereY

## 概要

本ドキュメントは、ImGuiライブラリにおける `SetScrollHereY` 関数の機能設計を記述する。この関数は、現在のカーソル位置（直前のアイテム）が表示されるように垂直スクロール量を調整するために使用される。

### 本機能の処理概要

**業務上の目的・背景**：ウィンドウ内で特定のアイテムが見えるようにスクロールを調整する必要がある場面は多い。`SetScrollHereY` は直前に描画されたアイテムの垂直位置が表示されるようにスクロールを調整する関数である。`center_y_ratio` パラメータにより、アイテムを上端、中央、下端など任意の位置に配置できる。この関数は最も頻繁に使用されるスクロール調整関数の一つであり、リスト表示、ログ表示、チャットなど多くの場面で活用される。

**機能の利用シーン**：
- リスト表示で選択されたアイテムが見えるようにスクロールする場合
- ログウィンドウやコンソールで最新メッセージを表示する場合（center_y_ratio = 1.0f）
- 検索結果をハイライトしてユーザーに見せる場合
- キーボードナビゲーションで現在の選択を追従する場合
- デフォルト/現在のアイテムを可視化する場合（SetItemDefaultFocus の代替）

**主要な処理内容**：
1. 直前の行の位置（`DC.CursorPosPrevLine`）を取得
2. `center_y_ratio` に基づいてターゲット位置を計算
3. `SetScrollFromPosY` を呼び出してスクロールターゲットを設定
4. エッジスナップ距離を設定して、端に近いアイテムはスナップする

**関連システム・外部連携**：本機能はImGuiの内部システムのみで完結し、外部システムとの連携はない。

**権限による制御**：権限制御は存在しない。すべてのコンテキストで同様に動作する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

スクロール / 位置調整

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| center_y_ratio | float | No（デフォルト: 0.5f） | 垂直配置比率（0.0f: 上端、0.5f: 中央、1.0f: 下端） | 0.0f〜1.0f の範囲推奨 |

### 入力データソース

- パラメータ: プログラムコード内で直接指定
- アイテム位置: window->DC.CursorPosPrevLine と PrevLineSize から取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| なし | void | 戻り値なし（状態設定のみ） |

### 出力先

ImGuiWindow の ScrollTarget.y、ScrollTargetCenterRatio.y、ScrollTargetEdgeSnapDist.y に格納

## 処理フロー

### 処理シーケンス

```
1. SetScrollHereY(center_y_ratio) 呼び出し
   └─ 引数: center_y_ratio (デフォルト 0.5f)
2. コンテキストとウィンドウの取得
   └─ ImGuiContext g と CurrentWindow の取得
3. スペーシングの計算
   └─ spacing_y = max(WindowPadding.y, ItemSpacing.y)
4. ターゲット位置の計算
   └─ target_pos_y = ImLerp(DC.CursorPosPrevLine.y - spacing_y,
                            DC.CursorPosPrevLine.y + PrevLineSize.y + spacing_y,
                            center_y_ratio)
5. SetScrollFromPosY の呼び出し
   └─ ローカル座標に変換してスクロールターゲットを設定
6. エッジスナップ距離の設定
   └─ ScrollTargetEdgeSnapDist.y = max(0.0f, WindowPadding.y - spacing_y)
```

### フローチャート

```mermaid
flowchart TD
    A[SetScrollHereY 呼び出し] --> B[Context/Window 取得]
    B --> C[spacing_y を計算]
    C --> D[ターゲット位置を計算]
    D --> E[SetScrollFromPosY を呼び出し]
    E --> F[エッジスナップ距離を設定]
    F --> G[関数終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | 直前行参照 | 直前の行の位置（CursorPosPrevLine）を基準にスクロール | 常時 |
| BR-50-02 | センタリング比率 | 0.0f: 上端、0.5f: 中央、1.0f: 下端 | 常時 |
| BR-50-03 | エッジスナップ | 端に近いアイテムはエッジにスナップする | ScrollTargetEdgeSnapDist.y > 0 の場合 |
| BR-50-04 | 遅延適用 | スクロール変更は次のフレームで適用される | 常時 |
| BR-50-05 | 最下部追従 | center_y_ratio = 1.0f で最新アイテムを下端に配置（オートスクロール用） | 常時 |

### 計算ロジック

ターゲット位置の計算:
```cpp
float spacing_y = ImMax(window->WindowPadding.y, g.Style.ItemSpacing.y);
float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y,
                             window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y,
                             center_y_ratio);
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | - | 本関数はエラーを発生させない | - |

### リトライ仕様

リトライ不要

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

該当なし

## パフォーマンス要件

本関数は数値計算と値の設定のみを行い、O(1) の時間複雑度で完了する。

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

該当なし

## 備考

- SetScrollHereX と対で使用されることが多い
- デフォルト引数は 0.5f（中央配置）
- 歴史的に `SetScrollHere()` という名前だったが、1.66 で `SetScrollHereY()` にリネームされた
- オートスクロールの典型的パターン: `if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f);`
- デモコードでは4897行目などで使用されている
- SetItemDefaultFocus を使用する代わりに、デフォルト/現在のアイテムを可視化する目的でも使用できる

---

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

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

### 推奨読解順序

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

まず、スクロールターゲットとカーソル位置の構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiWindow 構造体の ScrollTarget フィールド（2668-2670行目） |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiWindowTempData 構造体の CursorPosPrevLine、PrevLineSize フィールド |

**読解のコツ**: DC.CursorPosPrevLine と DC.PrevLineSize には直前の行の位置とサイズが格納される。SetScrollHereX と異なり、LastItemData ではなくこれらを使用する点に注意。

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

SetScrollHereY 関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | SetScrollHereY 関数の実装（11936-11946行目） |

**主要処理フロー**:
1. **11938-11939行目**: ImGuiContext g と CurrentWindow の取得
2. **11940行目**: spacing_y の計算
3. **11941行目**: target_pos_y の計算（ImLerp を使用、CursorPosPrevLine と PrevLineSize を参照）
4. **11942行目**: SetScrollFromPosY の呼び出し
5. **11945行目**: ScrollTargetEdgeSnapDist.y の設定

#### Step 3: API宣言を理解する

公開APIとしての宣言を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.h | `imgui.h` | SetScrollHereY の宣言とコメント（501行目） |

**主要処理フロー**:
- **501行目**: `IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f);` - 0.0f: 上、0.5f: 中央、1.0f: 下

#### Step 4: 使用例を確認する

デモコードでの使用例を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_demo.cpp | `imgui_demo.cpp` | スクロールデモでの使用例（4897行目） |
| 4-2 | imgui_demo.cpp | `imgui_demo.cpp` | コンソールのオートスクロール（9019行目） |
| 4-3 | imgui.cpp | `imgui.cpp` | デバッグログウィンドウのオートスクロール（17747行目） |

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

```
ユーザーコード
    │
    └─ SetScrollHereY(center_y_ratio)
           │
           ├─ ImLerp() でターゲット位置を計算
           │      └─ DC.CursorPosPrevLine.y と DC.PrevLineSize.y を使用
           │
           └─ SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio)
                  └─ window->ScrollTarget.y = ...
                  └─ window->ScrollTargetCenterRatio.y = center_y_ratio
                  └─ window->ScrollTargetEdgeSnapDist.y = 0.0f
           │
           └─ window->ScrollTargetEdgeSnapDist.y = max(0.0f, WindowPadding.y - spacing_y)
```

### データフロー図

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

center_y_ratio ────┐
                   │
DC.CursorPosPrevLine ─┼──▶ SetScrollHereY() ──▶ window->ScrollTarget.y
DC.PrevLineSize    │                            window->ScrollTargetCenterRatio.y
                   │                            window->ScrollTargetEdgeSnapDist.y
WindowPadding ─────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言 |
| imgui.cpp | `imgui.cpp` | ソース | SetScrollHereY の実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiWindow、ImGuiWindowTempData 構造体定義 |
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | 使用例 |
