# 機能設計書 169-BeginPopupContextWindow

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける `BeginPopupContextWindow` 関数の機能設計書である。この関数は、現在のウィンドウに対するコンテキストメニュー（右クリックメニュー）を簡単に実装するためのヘルパー関数である。

### 本機能の処理概要

`BeginPopupContextWindow`は、現在のウィンドウ領域がクリック（デフォルト: 右クリック）されたときにポップアップを開き、開いている場合はポップアップウィンドウを開始するヘルパー関数である。`BeginPopupContextItem`がアイテム単位であるのに対し、この関数はウィンドウ全体を対象とする。

**業務上の目的・背景**：GUIアプリケーションにおいて、ウィンドウの空白領域を右クリックしてコンテキストメニューを表示するパターンは一般的である。ウィンドウに対する操作（表示オプションの変更、新規アイテムの追加等）を提供する場面で使用される。`BeginPopupContextWindow`は、このパターンを最小限のコードで実装することを可能にする。

**機能の利用シーン**：
- ウィンドウ空白領域の右クリックメニュー
- リストビューへの「新規追加」メニュー
- カンバスやエディタ領域のコンテキストメニュー
- ウィンドウ表示オプションの設定メニュー
- デバッグ/開発者向けメニュー

**主要な処理内容**：
1. ポップアップIDを決定（str_idまたは"window_context"）
2. 指定されたマウスボタンがリリースされ、ウィンドウがホバーされている場合を検出
3. `NoOpenOverItems`フラグによりアイテム上では開かないオプションを提供
4. OpenPopupExを呼び出してポップアップを開く
5. BeginPopupExを呼び出してポップアップを開始

**関連システム・外部連携**：
- `OpenPopupEx`: ポップアップを開く内部関数
- `BeginPopupEx`: ポップアップウィンドウを開始する内部関数
- `IsWindowHovered`: ウィンドウのホバー判定
- `IsAnyItemHovered`: アイテムホバー判定（NoOpenOverItemsフラグ用）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | Popups | 補助機能 | ウィンドウコンテキストメニュー |

## 機能種別

UI制御機能（ウィンドウコンテキストメニューヘルパー）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str_id | const char* | No | ポップアップの識別子文字列（デフォルト: NULL = "window_context"） | NULL許容 |
| popup_flags | ImGuiPopupFlags | No | ポップアップフラグ（デフォルト: 0 = 右クリック） | 有効なImGuiPopupFlagsの組み合わせ |

### 入力データソース

- 呼び出し元コードから提供される識別子（オプション）
- 内部的に現在のウィンドウ情報（`g.CurrentWindow`）を参照
- マウス入力状態

## 出力仕様

### 出力データ

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

### 出力先

- 画面上にコンテキストメニューウィンドウとして表示
- `g.OpenPopupStack`/`g.BeginPopupStack`に情報追加

## 処理フロー

### 処理シーケンス

```
1. ポップアップID決定
   └─ str_id != NULL: str_idを使用
   └─ str_id == NULL: "window_context"をデフォルトとして使用
2. ID計算
   └─ window->GetID(str_id)
3. マウスボタン種類取得
   └─ GetMouseButtonFromPopupFlags(popup_flags)
4. ポップアップオープン判定
   └─ IsMouseReleased(mouse_button)
   └─ IsWindowHovered(AllowWhenBlockedByPopup)
   └─ NoOpenOverItemsフラグ: !IsAnyItemHovered()も確認
5. OpenPopupEx呼び出し（条件付き）
6. BeginPopupEx呼び出し
   └─ AlwaysAutoResize | NoTitleBar | NoSavedSettingsフラグ付き
```

### フローチャート

```mermaid
flowchart TD
    A[BeginPopupContextWindow開始] --> B{str_id != NULL?}
    B -->|Yes| C[str_idを使用]
    B -->|No| D[str_id = window_context]
    C --> E[id = GetID str_id]
    D --> E
    E --> F[マウスボタン種類取得]
    F --> G{IsMouseReleased && IsWindowHovered?}
    G -->|No| H[BeginPopupEx id]
    G -->|Yes| I{NoOpenOverItemsフラグあり?}
    I -->|Yes| J{IsAnyItemHovered?}
    I -->|No| K[OpenPopupEx id]
    J -->|Yes| H
    J -->|No| K
    K --> H
    H --> L{ポップアップが開いている?}
    L -->|Yes| M[return true]
    L -->|No| N[return false]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-169-01 | デフォルトID | str_id = NULLの場合、"window_context"がIDとして使用される | str_id未指定時 |
| BR-169-02 | デフォルト右クリック | popup_flags = 0の場合、右クリックがトリガー | フラグ未指定時 |
| BR-169-03 | NoOpenOverItems | ImGuiPopupFlags_NoOpenOverItemsでアイテム上では開かない | フラグ指定時 |
| BR-169-04 | ウィンドウホバー | 現在のウィンドウがホバーされている場合のみトリガー | 常時 |
| BR-169-05 | ポップアップブロック無視 | 既存ポップアップでブロックされていてもホバー判定される | 常時 |

### 計算ロジック

- ポップアップID: `window->GetID(str_id)`で計算
- デフォルトstr_id: "window_context"

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 特になし | - | - |

### リトライ仕様

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

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

該当なし。

## パフォーマンス要件

- 処理時間: 即時
- 毎フレーム呼び出されるが、ホバー/クリック状態の確認は軽量

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

特になし。

## 備考

- trueを返した場合は必ず`EndPopup`を呼び出す
- `BeginPopupContextItem`との違い: アイテム単位ではなくウィンドウ単位
- `BeginPopupContextVoid`との違い: この関数は現在のウィンドウ、VoidはすべてのウィンドウがないV空白領域
- `ImGuiPopupFlags_NoOpenOverItems`で空白領域のみに限定可能

---

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

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

### 推奨読解順序

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

ポップアップフラグを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiPopupFlags_NoOpenOverItems定義（1346行目） |

**読解のコツ**: `NoOpenOverItems`フラグが、空白領域のみでポップアップを開くオプションを提供する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | BeginPopupContextWindow実装（12511-12523行目） |

**主要処理フロー**:
1. **12515-12516行目**: str_id = NULLなら"window_context"を使用
2. **12517行目**: ID計算
3. **12518行目**: マウスボタン種類取得
4. **12519-12521行目**: マウスリリース && ウィンドウホバー && (NoOpenOverItemsなし or アイテム未ホバー) でOpenPopupEx
5. **12522行目**: BeginPopupExを呼び出して結果を返す

#### Step 3: ウィンドウホバー判定を理解する

`IsWindowHovered`の動作を確認する。

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

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

```
BeginPopupContextWindow(str_id, popup_flags)
    │
    ├─ デフォルトID設定
    │      └─ str_id = str_id ? str_id : "window_context"
    │
    ├─ window->GetID(str_id)
    │      └─ ポップアップID計算
    │
    ├─ GetMouseButtonFromPopupFlags(popup_flags)
    │      └─ マウスボタン種類を計算
    │
    ├─ 条件判定
    │      ├─ IsMouseReleased(mouse_button)
    │      ├─ IsWindowHovered(AllowWhenBlockedByPopup)
    │      └─ !IsAnyItemHovered()  [NoOpenOverItemsの場合]
    │
    ├─ OpenPopupEx(id, popup_flags)  [条件付き]
    │
    └─ BeginPopupEx(id, flags)
           └─ AlwaysAutoResize | NoTitleBar | NoSavedSettings
```

### データフロー図

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

str_id (文字列/NULL) ─▶ BeginPopupContextWindow() ─▶ bool (開いているか)
popup_flags            │
                       ├─ ID決定
                       │   └─ GetID()
                       │
                       ├─ ホバー判定
                       │   ├─ IsWindowHovered
                       │   └─ IsAnyItemHovered（オプション）
                       │
                       └─ ポップアップ処理
                           ├─ OpenPopupEx()
                           └─ BeginPopupEx()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダ | 関数宣言（871行目）、ImGuiPopupFlags定義 |
| imgui.cpp | `imgui.cpp` | ソース | BeginPopupContextWindow実装（12511-12523行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダ | 内部データ構造 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例 |
