# 機能設計書 164-EndPopup

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける `EndPopup` 関数の機能設計書である。この関数は、`BeginPopup`または`BeginPopupModal`で開始されたポップアップウィンドウを終了する。

### 本機能の処理概要

`EndPopup`は、ポップアップウィンドウのコンテンツ追加を終了し、内部的な状態管理（スタックのポップ等）を行う関数である。`BeginPopup`/`BeginPopupModal`/`BeginPopupContextXXX`がtrueを返した場合に、必ず呼び出す必要がある。

**業務上の目的・背景**：ImGuiのポップアップシステムは、Begin/Endの対称的なAPI設計に基づいている。これにより、ポップアップのスコープが明確になり、リソース管理やスタック処理が確実に行われる。`EndPopup`を正しく呼び出すことで、ポップアップスタックの整合性が保たれ、後続のUI描画が正しく動作する。

**機能の利用シーン**：
- `BeginPopup`がtrueを返した後のポップアップ終了
- `BeginPopupModal`がtrueを返した後のモーダル終了
- `BeginPopupContextItem/Window/Void`がtrueを返した後のコンテキストメニュー終了
- ネストされたポップアップの各レベルでの終了処理

**主要な処理内容**：
1. 現在のウィンドウがポップアップであることを検証
2. ナビゲーションラッピングの設定（メニューやポップアップ内での循環移動）
3. 子ウィンドウの場合の特別処理
4. End()関数の呼び出し（通常のウィンドウ終了処理）
5. BeginPopupStackからのポップ

**関連システム・外部連携**：
- `BeginPopup`/`BeginPopupModal`: ポップアップの開始（EndPopupとペアで使用）
- `End`: 内部的に呼び出されるウィンドウ終了関数
- `g.BeginPopupStack`: ポップアップスタックの管理

**権限による制御**：なし。すべてのコンテキストで使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | Popups | 主機能 | ポップアップの終了 |

## 機能種別

UI制御機能（ポップアップウィンドウ管理）

## 入力仕様

### 入力パラメータ

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

### 入力データソース

- 内部的に`g.CurrentWindow`（現在のウィンドウ）を参照
- 内部的に`g.BeginPopupStack`を参照

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (戻り値なし) | void | この関数は戻り値を持たない |

### 出力先

- `g.BeginPopupStack`からポップアップ情報をポップ
- 描画データをファイナライズ

## 処理フロー

### 処理シーケンス

```
1. ポップアップ検証
   └─ 現在のウィンドウがPopupフラグを持っているか確認
   └─ BeginPopupStack.Size > 0 か確認
2. ナビゲーションラッピング設定
   └─ NavWindowが現在のウィンドウの場合
   └─ NavMoveRequestTryWrapping(ImGuiNavMoveFlags_LoopY)
3. 子ウィンドウ処理
   └─ ChildWindowフラグを持っている場合
   └─ WithinEndChildIDにウィンドウIDを設定
4. End()呼び出し
   └─ 通常のウィンドウ終了処理
5. WithinEndChildIDを復元
```

### フローチャート

```mermaid
flowchart TD
    A[EndPopup開始] --> B{Popupフラグあり && BeginPopupStack > 0?}
    B -->|No| C[アサーション失敗]
    B -->|Yes| D{NavWindow == CurrentWindow?}
    D -->|Yes| E[NavMoveRequestTryWrapping LoopY]
    D -->|No| F[WithinEndChildID処理]
    E --> F
    F --> G{ChildWindowフラグあり?}
    G -->|Yes| H[WithinEndChildID = window->ID]
    G -->|No| I[End呼び出し]
    H --> I
    I --> J[WithinEndChildIDを復元]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-164-01 | Begin/Endペア | BeginPopupがtrueを返した場合のみEndPopupを呼び出す | 常時 |
| BR-164-02 | スタック整合性 | EndPopupは対応するBeginPopupと同じフレーム内で呼び出す | 常時 |
| BR-164-03 | ネスト順序 | ネストされたポップアップは逆順でEndPopupを呼び出す | ネスト使用時 |
| BR-164-04 | ナビゲーションラップ | ポップアップ内でのキーボードナビゲーションは縦方向にループする | ナビゲーション使用時 |

### 計算ロジック

特になし。

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション失敗 | ポップアップ外でEndPopupを呼び出した | BeginPopupがtrueの場合のみ呼び出す |
| - | アサーション失敗 | BeginPopupStack.Size == 0 | ポップアップスタックの不整合 |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

- 処理時間: 即時
- End()関数の呼び出しを含むが、軽量な処理

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

特になし。

## 備考

- EndPopupは必ずBeginPopupがtrueを返した場合のみ呼び出す
- 通常のif文パターン: `if (BeginPopup(...)) { ... EndPopup(); }`
- ImGuiNavMoveFlags_LoopYによりポップアップ内のナビゲーションが循環する

---

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

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

### 推奨読解順序

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

ポップアップスタックとウィンドウフラグを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | BeginPopupStack定義（2309行目） |
| 1-2 | imgui.h | `imgui.h` | ImGuiWindowFlags_Popup定義（1192行目） |

**読解のコツ**: `BeginPopupStack`は現在のフレームで処理中のポップアップを追跡する。ウィンドウのPopupフラグでポップアップかどうかを識別。

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

`EndPopup`関数の実装を確認する。

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

**主要処理フロー**:
1. **12439行目**: Popupフラグ検証とスタックサイズ確認のアサーション
2. **12441-12443行目**: ナビゲーションラッピングの設定（LoopY）
3. **12445-12448行目**: 子ウィンドウの場合のWithinEndChildID設定
4. **12449行目**: End()関数呼び出し
5. **12450行目**: WithinEndChildIDの復元

#### Step 3: End関数との関係を理解する

内部的に呼び出されるEnd関数の処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | End関数内のBeginPopupStack.pop_back()（8195行目付近） |

**主要処理フロー**:
- End関数がBeginPopupStackからのポップを行う

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

```
EndPopup()
    │
    ├─ IM_ASSERT_USER_ERROR_RET(...)
    │      └─ Popupフラグとスタック検証
    │
    ├─ NavMoveRequestTryWrapping(ImGuiNavMoveFlags_LoopY)
    │      └─ ナビゲーション循環設定（条件付き）
    │
    ├─ g.WithinEndChildID設定
    │      └─ 子ウィンドウの場合のみ
    │
    └─ End()
           │
           ├─ ウィンドウ終了処理
           │
           └─ g.BeginPopupStack.pop_back()
```

### データフロー図

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

(なし)          ───▶ EndPopup()          ───▶ (なし)
                     │
                     ├─ ポップアップ検証
                     │   └─ g.CurrentWindow->Flags
                     │
                     ├─ ナビゲーション設定
                     │   └─ g.NavWindow
                     │
                     └─ End()
                         └─ g.BeginPopupStack
                             └─ pop_back()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダ | 関数宣言（847行目） |
| imgui.cpp | `imgui.cpp` | ソース | EndPopup実装（12435-12451行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダ | BeginPopupStack定義 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（多数：5271行目、5311行目等） |
