# 機能設計書 155-EndMenu

## 概要

本ドキュメントはImGuiのEndMenu機能について、その処理内容、入出力仕様、実装詳細を記述した機能設計書である。

### 本機能の処理概要

EndMenuは、BeginMenu()で開始されたサブメニューを終了するための関数である。メニューポップアップを閉じ、キーボードナビゲーションによる左移動でのメニュー閉鎖を処理する。

**業務上の目的・背景**：BeginMenu()で開始した階層メニューを正しく終了させるために必要な関数である。ImGuiのBegin/Endパターンに従い、BeginMenuがtrueを返した場合は必ずEndMenuを呼び出す必要がある。また、キーボード/ゲームパッドナビゲーションでの「左」キー押下によるメニュー閉鎖処理を行う。

**機能の利用シーン**：BeginMenu()がtrueを返した後、メニュー項目を配置した後に呼び出す。Main Menu Bar画面などで使用される。

**主要な処理内容**：
1. ウィンドウフラグのアサーション検証を行う
2. キーボードナビゲーションでの左移動要求を処理する
3. EndPopup()を呼び出してポップアップを終了する

**関連システム・外部連携**：ImGuiのナビゲーションシステム、ポップアップシステムと連携。

**権限による制御**：特になし。BeginMenu()がtrueを返していない状態での呼び出しはアサーションエラーとなる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | Main Menu Bar | 主機能 | サブメニューの終了 |

## 機能種別

レイアウト処理 / 状態管理

## 入力仕様

### 入力パラメータ

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

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

- ポップアップスタックの状態更新

## 処理フロー

### 処理シーケンス

```
1. コンテキストとウィンドウの取得
   └─ GImGuiからコンテキストを取得
   └─ CurrentWindowからウィンドウを取得

2. アサーション検証
   └─ ウィンドウがPopupかつChildMenuフラグを持つことを確認
   └─ 持っていない場合はユーザーエラーとしてリターン

3. ナビゲーション処理（左移動によるメニュー閉鎖）
   └─ BeginCount == BeginCountPreviousFrameを確認（初回フレーム）
   └─ NavMoveDir == ImGuiDir_Leftかつ未処理の要求を検出
   └─ NavWindowのRootWindowForNav == windowを確認
   └─ 親ウィンドウが垂直レイアウトであることを確認
   └─ ClosePopupToLevelでポップアップを閉じる
   └─ NavMoveRequestCancelでナビゲーション要求をキャンセル

4. ポップアップの終了
   └─ EndPopup()を呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[開始: EndMenu] --> B{ウィンドウが<br/>Popup|ChildMenu?}
    B -->|No| C[ユーザーエラー<br/>return]
    B -->|Yes| D{BeginCount ==<br/>BeginCountPreviousFrame?}
    D -->|No| E[EndPopup]
    D -->|Yes| F{NavMoveDir == Left<br/>かつ未処理要求?}
    F -->|No| E
    F -->|Yes| G{NavWindow.RootWindowForNav<br/>== window?}
    G -->|No| E
    G -->|Yes| H{親ウィンドウが<br/>垂直レイアウト?}
    H -->|No| E
    H -->|Yes| I[ClosePopupToLevel<br/>BeginPopupStack.Size-1]
    I --> J[NavMoveRequestCancel]
    J --> E
    E --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-155-01 | ペア呼び出し | BeginMenu()がtrueを返した場合のみ呼び出す | 常時 |
| BR-155-02 | 左移動で閉鎖 | キーボード/ゲームパッドの左移動で親メニューに戻る | 垂直レイアウト時 |
| BR-155-03 | 初回フレームのみ | ナビゲーション処理は初回フレームでのみ実行 | 常時 |

### 計算ロジック

- 閉じるポップアップレベル: `g.BeginPopupStack.Size - 1`

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

データベース操作なし（UI状態管理のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ユーザーエラー | ウィンドウがPopup|ChildMenuでない | アサーションメッセージを表示してリターン |

### リトライ仕様

リトライ不要（フレームごとに再実行）

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

トランザクション管理なし（即時状態更新）

## パフォーマンス要件

- 単一フレーム内で開いているメニューごとに1回呼び出し
- 状態チェックとポップアップ終了のみのため軽量

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

- 特になし

## 備考

- BeginMenu()とEndMenu()は必ずペアで使用する
- BeginMenu()がfalseを返した場合はEndMenu()を呼び出してはならない
- EndMenu()は内部でEndPopup()を呼び出す

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 814行目: EndMenu API宣言を確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiWindowFlags_ChildMenu、ImGuiWindowFlags_Popupを確認 |

**読解のコツ**: EndMenuは比較的シンプルな関数だが、キーボードナビゲーションの左移動処理が重要なポイント。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9408-9425行目: EndMenu関数の実装 |

**主要処理フロー**:
1. **9411-9413行目**: コンテキストとウィンドウの取得、アサーション検証
2. **9415-9422行目**: キーボードナビゲーションの左移動処理
3. **9424行目**: EndPopup()呼び出し

#### Step 3: ポップアップ閉鎖処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | ClosePopupToLevel関数の実装 |

**主要処理フロー**:
- 指定レベルまでポップアップを閉じる
- OpenPopupStackをリサイズ

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

```
ImGui::EndMenu()
    │
    ├─ IM_ASSERT_USER_ERROR_RET()
    │      └─ ウィンドウフラグを検証
    │
    ├─ [条件付き: 左ナビゲーション処理]
    │      ├─ NavMoveRequestButNoResultYet()
    │      │      └─ 未処理のナビゲーション要求を確認
    │      │
    │      ├─ ClosePopupToLevel()
    │      │      └─ ポップアップを指定レベルまで閉じる
    │      │
    │      └─ NavMoveRequestCancel()
    │             └─ ナビゲーション要求をキャンセル
    │
    └─ EndPopup()
           └─ ポップアップウィンドウを終了
```

### データフロー図

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

g.CurrentWindow ──────────> フラグ検証 ─────────────────────> エラーまたは続行
 - Flags (Popup|ChildMenu)
                                  │
g.NavMoveDir ─────────────────> 左ナビゲーション判定
g.NavWindow                       │
                                  ├──────────────────────────> ClosePopupToLevel
                                  │
parent_window->DC.LayoutType ────>│
                                  │
                                  └──────────────────────────> EndPopup
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | EndMenu APIの宣言 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | 内部データ構造の定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | EndMenu実装（9408-9425行目） |
| imgui.cpp | `imgui.cpp` | ソース | EndPopup、ClosePopupToLevel等のポップアップ関数 |
