# 機能設計書 162-BeginPopup

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける `BeginPopup` 関数の機能設計書である。この関数は、ポップアップウィンドウの開始処理を行い、ポップアップが開いている場合にコンテンツの追加を可能にする。

### 本機能の処理概要

`BeginPopup`は、ImGuiのポップアップシステムにおける基本的なBegin関数であり、`OpenPopup`で開かれたポップアップウィンドウの内容を定義するために使用される。ポップアップが開いている場合のみtrueを返し、その後にウィジェットを追加できる。

**業務上の目的・背景**：GUIアプリケーションにおいて、ポップアップウィンドウは一時的な操作や選択肢の提示に広く使用される。コンテキストメニュー、ドロップダウンリスト、簡易ダイアログなど、メインUIを遮らずに追加情報や選択肢を提供する必要がある場面で不可欠である。`BeginPopup`は、このようなポップアップUIの実装を簡潔かつ一貫した方法で実現する。

**機能の利用シーン**：
- 右クリックコンテキストメニューの実装
- ドロップダウン選択リストの表示
- 簡易的な確認ダイアログの表示
- カラーピッカーやファイル選択などのモーダル風UI
- ネストされたサブメニューの実装

**主要な処理内容**：
1. ポップアップIDを使用して、ポップアップが現在開いているかを確認
2. 開いていない場合はfalseを返し、NextWindowDataをクリア
3. 開いている場合は、自動リサイズ・タイトルバーなし・設定保存なしのフラグを付与してBeginPopupExを呼び出し
4. ポップアップウィンドウの内容追加を開始

**関連システム・外部連携**：
- `OpenPopup`: ポップアップを開く関数（BeginPopupの前に呼び出す必要がある）
- `EndPopup`: ポップアップを終了する関数（BeginPopupがtrueを返した場合に必ず呼び出す）
- ポップアップスタック: `g.OpenPopupStack`と`g.BeginPopupStack`で状態管理

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str_id | const char* | Yes | ポップアップの識別子文字列 | NULLポインタ禁止 |
| flags | ImGuiWindowFlags | No | ウィンドウフラグ（デフォルト: 0） | 有効なImGuiWindowFlagsの組み合わせ |

### 入力データソース

- 呼び出し元コードから提供される識別子文字列
- 内部的に`g.OpenPopupStack`（開いているポップアップのスタック）を参照

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | ポップアップが開いていてコンテンツを追加できる場合はtrue |

### 出力先

- 画面上にポップアップウィンドウとして表示
- `g.BeginPopupStack`にポップアップ情報をプッシュ

## 処理フロー

### 処理シーケンス

```
1. 早期リターン判定
   └─ g.OpenPopupStack.Size <= g.BeginPopupStack.Size の場合
   └─ NextWindowDataをクリアしてfalseを返す
2. ウィンドウフラグの設定
   └─ AlwaysAutoResize | NoTitleBar | NoSavedSettings を追加
3. ポップアップIDの計算
   └─ CurrentWindow->GetID(str_id) でIDを生成
4. BeginPopupExの呼び出し
   └─ IDとフラグを渡してポップアップを開始
5. 結果の返却
   └─ ポップアップが開いていればtrue、そうでなければfalse
```

### フローチャート

```mermaid
flowchart TD
    A[BeginPopup開始] --> B{OpenPopupStack.Size > BeginPopupStack.Size?}
    B -->|No| C[NextWindowData.ClearFlags]
    C --> D[return false]
    B -->|Yes| E[フラグ追加: AutoResize等]
    E --> F[ID = GetID str_id]
    F --> G[BeginPopupEx id, flags]
    G --> H{ポップアップが開いている?}
    H -->|Yes| I[return true]
    H -->|No| J[return false]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-162-01 | ID一致要件 | OpenPopupとBeginPopupは同じIDスタックレベルで呼び出す必要がある | 常時 |
| BR-162-02 | EndPopup必須 | BeginPopupがtrueを返した場合、必ずEndPopupを呼び出す | BeginPopup成功時 |
| BR-162-03 | 外部クリック閉じ | ポップアップ外をクリックすると自動的に閉じる | 非モーダルポップアップ |
| BR-162-04 | ESC閉じ | ESCキーでポップアップを閉じることができる | 非モーダルポップアップ |

### 計算ロジック

- ポップアップID: `CurrentWindow->IDStack`に基づいてstr_idからハッシュ計算

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 未定義動作 | str_idがNULL | NULLを渡さない |
| - | 論理エラー | OpenPopupを呼ばずにBeginPopup | OpenPopupを先に呼び出す |
| - | アサーション失敗 | EndPopupの呼び忘れ | デバッグビルドで検出 |

### リトライ仕様

リトライ不要（毎フレーム呼び出し）。

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

該当なし。

## パフォーマンス要件

- 処理時間: 即時（ポップアップが閉じている場合は早期リターン）
- 早期リターン最適化によりOpenPopupStack.Sizeのチェックのみで判定可能

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

- ポップアップIDは推測可能であるため、セキュリティ上重要な操作には追加の認証が必要
- ポップアップの自動閉じ動作を悪用されないよう注意

## 備考

- `BeginPopupModal`との違い: BeginPopupは外部クリックで閉じ、モーダルは閉じない
- ImGuiWindowFlags_AlwaysAutoResizeが自動付与されるため、ポップアップサイズはコンテンツに応じて調整される
- ImGuiWindowFlags_NoTitleBarが付与されるため、タイトルバーは表示されない

---

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

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

### 推奨読解順序

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

ポップアップ管理に使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiPopupData構造体（1471-1483行目） |
| 1-2 | imgui_internal.h | `imgui_internal.h` | OpenPopupStack, BeginPopupStackの定義（2308-2309行目） |

**読解のコツ**: `ImGuiPopupData`がポップアップの状態（ID、ウィンドウ、開いたフレームなど）を保持する。OpenPopupStackは開いているポップアップ、BeginPopupStackは現在処理中のポップアップを管理。

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

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

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

**主要処理フロー**:
1. **12387-12391行目**: 早期リターン最適化（OpenPopupStack.Size <= BeginPopupStack.Sizeの場合）
2. **12392行目**: 自動リサイズ・タイトルバーなし・設定保存なしフラグを追加
3. **12393行目**: str_idからポップアップIDを計算
4. **12394行目**: BeginPopupExを呼び出し

#### Step 3: 内部実装を理解する

`BeginPopupEx`の詳細な実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | BeginPopupEx関数の実装（12345-12363行目） |

**主要処理フロー**:
- **12348-12352行目**: IsPopupOpenでポップアップが開いているか確認
- **12354-12356行目**: ポップアップウィンドウ名の生成（"##Popup_XXXXXXXX"形式）
- **12358-12362行目**: Begin関数を呼び出してウィンドウを開始

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

```
BeginPopup(str_id, flags)
    │
    ├─ 早期リターン判定
    │      └─ g.OpenPopupStack.Size <= g.BeginPopupStack.Size
    │
    ├─ CurrentWindow->GetID(str_id)
    │      └─ IDスタックからハッシュ計算
    │
    └─ BeginPopupEx(id, flags)
           │
           ├─ IsPopupOpen(id, ImGuiPopupFlags_None)
           │      └─ ポップアップスタックを検索
           │
           ├─ ImFormatString(name, ...)
           │      └─ "##Popup_XXXXXXXX"形式の名前生成
           │
           └─ Begin(name, NULL, flags | ImGuiWindowFlags_Popup)
                  └─ 通常のウィンドウ処理を実行
```

### データフロー図

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

str_id (文字列) ───▶ BeginPopup()        ───▶ bool (開いているか)
flags (フラグ)       │                         │
                     ├─ ID計算                 └─▶ ポップアップウィンドウ
                     │   └─ GetID()                 （画面上に描画）
                     │
                     ├─ ポップアップ状態確認
                     │   └─ g.OpenPopupStack
                     │
                     └─ ウィンドウ開始
                         └─ g.BeginPopupStack
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダ | 関数宣言（845行目） |
| imgui.cpp | `imgui.cpp` | ソース | BeginPopup実装（12384-12395行目）、BeginPopupEx実装（12345-12363行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダ | ImGuiPopupData構造体、ポップアップスタック定義 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（5265行目、5277行目等） |
