# 機能設計書 27-EndChild

## 概要

本ドキュメントは、Dear ImGuiライブラリにおけるEndChild機能の設計仕様を記述する。この機能は、BeginChild関数で開始した子ウィンドウを終了し、親ウィンドウに制御を戻すための関数である。

### 本機能の処理概要

**業務上の目的・背景**：BeginChild関数とペアで使用され、子ウィンドウのライフサイクルを完結させる。子ウィンドウの終了処理を行い、子ウィンドウのサイズをアイテムとして親ウィンドウに登録する。これにより、子ウィンドウが親ウィンドウのレイアウトに正しく組み込まれる。

**機能の利用シーン**：
- BeginChild関数で開始した子ウィンドウを終了する場合
- 子ウィンドウ内のウィジェット追加が完了した後
- BeginChild関数の戻り値に関わらず、必ず呼び出す必要がある

**主要な処理内容**：
1. 現在のウィンドウが子ウィンドウであることを検証する
2. 内部でEnd関数を呼び出して子ウィンドウを終了する
3. 子ウィンドウのサイズを親ウィンドウのアイテムとして登録する
4. ナビゲーションカーソルの描画を行う（必要な場合）
5. ホバー状態の更新を行う

**関連システム・外部連携**：ImGuiのウィンドウ管理システム、レイアウトシステム、ナビゲーションシステムと連携する。

**権限による制御**：特になし。すべてのユーザーが任意のタイミングで呼び出し可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | Debug Log Window | 補助機能 | 子ウィンドウの終了 |
| 10 | Console | 主機能 | 子ウィンドウの終了 |
| 11 | Log | 主機能 | 子ウィンドウの終了 |
| 12 | Simple Layout | 主機能 | 子ウィンドウの終了 |
| 22 | Assets Browser | 主機能 | 子ウィンドウの終了 |

## 機能種別

ウィンドウ管理 / UI構造制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (なし) | - | - | 引数なし | - |

### 入力データソース

- グローバルコンテキストの現在のウィンドウ（g.CurrentWindow）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (なし) | void | 戻り値なし |

### 出力先

- グローバルコンテキスト（ウィンドウスタックの更新、現在のウィンドウの復元）
- 親ウィンドウのレイアウト情報

## 処理フロー

### 処理シーケンス

```
1. 子ウィンドウの検証
   └─ 現在のウィンドウがChildWindowフラグを持つことを確認
2. WithinEndChildIDの設定
   └─ IsItemHovered()等の呼び出しのためにIDを一時保存
3. 子ウィンドウのサイズを取得
   └─ 終了前にchild_window->Sizeを保存
4. End関数の呼び出し
   └─ 内部でEnd()を呼び出して子ウィンドウを終了
5. アイテムとして登録（初回のみ）
   └─ ItemSize()とItemAdd()で親ウィンドウにアイテムを追加
6. ナビゲーションカーソルの描画
   └─ 必要に応じてRenderNavCursor()を呼び出し
7. ホバー状態の更新
   └─ HoveredWindowの場合はステータスフラグを更新
```

### フローチャート

```mermaid
flowchart TD
    A[EndChild開始] --> B{子ウィンドウ?}
    B -->|No| C[アサーション失敗]
    B -->|Yes| D[WithinEndChildIDを設定]
    D --> E[子ウィンドウサイズを取得]
    E --> F[End を呼び出し]
    F --> G{初回呼び出し?}
    G -->|Yes| H[ItemSize で親にサイズを登録]
    G -->|No| I[SetLastItemData を呼び出し]
    H --> J{ナビゲーション対象?}
    I --> J
    J -->|Yes| K[ItemAdd で親にアイテム登録]
    J -->|No| L[ItemAdd でNav無効で登録]
    K --> M[RenderNavCursor]
    L --> M
    M --> N{ホバー中?}
    N -->|Yes| O[ステータスフラグを更新]
    N -->|No| P[WithinEndChildIDを復元]
    O --> P
    P --> Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | BeginChild/EndChildペア | すべてのBeginChild()呼び出しに対してEndChild()を呼び出す | 常時 |
| BR-002 | 子ウィンドウ専用 | 通常のウィンドウに対してはEnd()を使用し、EndChild()は使用しない | 非子ウィンドウの場合 |
| BR-003 | アイテム登録 | 初回のEndChild()呼び出し時のみアイテムとして親ウィンドウに登録 | 常時 |

### 計算ロジック

- 子ウィンドウの境界ボックス（bb）は親ウィンドウのカーソル位置とサイズから計算
- NavFlattened時は親ウィンドウのナビゲーションレイヤーマスクに追加

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

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

なし（本機能はメモリ内のデータ構造のみを操作する）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション失敗 | 子ウィンドウでないウィンドウに対してEndChild()を呼び出した場合 | End()を使用する |

### リトライ仕様

なし

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

なし

## パフォーマンス要件

- 処理時間: 数マイクロ秒程度
- メモリ使用: スタック操作のみ

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

なし

## 備考

- BeginChild/EndChildはBegin/Endと同様に、戻り値に関わらずEndChildを呼び出す必要がある
- WithinEndChildIDはIsItemHovered()等の関数が正しく動作するために必要

---

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

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

### 推奨読解順序

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

ImGuiWindow構造体の子ウィンドウ関連フィールドを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiWindow::ChildId、ChildFlags |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiContext::WithinEndChildID |

**読解のコツ**: WithinEndChildIDはEndChild内でのみ設定され、End()内でのエラーチェックに使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | EndChild関数宣言（458行目） |
| 2-2 | imgui.cpp | `imgui.cpp` | EndChild関数実装（6494-6543行目） |

**主要処理フロー**:
1. **6494-6500行目**: 関数開始、子ウィンドウの検証
2. **6502行目**: WithinEndChildIDの設定
3. **6503-6504行目**: サイズ取得とEnd()呼び出し
4. **6505-6535行目**: アイテム登録とナビゲーション処理
5. **6541行目**: WithinEndChildIDの復元

#### Step 3: アイテム登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | ItemSize/ItemAdd呼び出し（6508-6525行目） |

**主要処理フロー**:
- **6508行目**: 境界ボックスの計算
- **6509行目**: ItemSize()で親にサイズを登録
- **6513-6525行目**: ItemAdd()でアイテムを登録

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

```
EndChild()
    │
    ├─ End() [子ウィンドウを終了]
    │
    ├─ ItemSize(child_size)
    │
    ├─ ItemAdd(bb, child_window->ChildId, ...)
    │
    ├─ RenderNavCursor() [必要な場合]
    │
    └─ SetLastItemDataForChildWindowItem() [2回目以降]
```

### データフロー図

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

g.CurrentWindow ──────────▶
(子ウィンドウ)                EndChild()              ──▶ スタック更新
                                │
                                ▼
                          End() 呼び出し
                                │
                                ▼
                          アイテム登録 ──────────────▶ 親ウィンドウのレイアウト
                                │
                                ▼
                          g.CurrentWindow 復元 ─────▶ 親ウィンドウ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダ | API宣言 |
| imgui.cpp | `imgui.cpp` | ソース | EndChild関数の実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダ | WithinEndChildID定義 |
