# 機能設計書 166-OpenPopupOnItemClick

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける `OpenPopupOnItemClick` 関数の機能設計書である。この関数は、直前のアイテムがクリックされたときにポップアップを開くヘルパー関数である。

### 本機能の処理概要

`OpenPopupOnItemClick`は、直前に描画されたアイテムがマウスでクリック（正確にはマウスボタンリリース）されたときに、指定されたポップアップを開くためのヘルパー関数である。`BeginPopupContextItem`と似ているが、`BeginPopup`の呼び出しは含まれないため、ポップアップの開閉とコンテンツ定義をより柔軟に分離できる。

**業務上の目的・背景**：GUIアプリケーションにおいて、アイテムのクリック（特に右クリック）でコンテキストメニューを開くパターンは非常に一般的である。`OpenPopupOnItemClick`は、このパターンを簡潔に実装するためのヘルパーであり、`IsItemHovered`や`IsMouseReleased`を組み合わせる代わりに、1行でポップアップを開くロジックを記述できる。

**機能の利用シーン**：
- アイテムの右クリックでコンテキストメニューを表示
- 特定のマウスボタンでアクションメニューを表示
- `BeginPopup`と組み合わせた柔軟なポップアップ制御
- 複数の場所から同じポップアップを開く場合のトリガー

**主要な処理内容**：
1. マウスボタンの種類を`ImGuiPopupFlags`から取得（デフォルト: 右ボタン）
2. 指定されたマウスボタンがリリースされたかを確認
3. 直前のアイテムがホバーされているか（ポップアップでブロックされていても）を確認
4. 条件を満たせば`OpenPopupEx`を呼び出してポップアップを開く

**関連システム・外部連携**：
- `BeginPopup`: 開いたポップアップの表示に使用
- `IsMouseReleased`: マウスボタンのリリース判定
- `IsItemHovered`: アイテムのホバー判定
- `g.LastItemData`: 直前のアイテム情報

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | Popups | 補助機能 | アイテムクリックでポップアップを開く |

## 機能種別

UI制御機能（ポップアップトリガーヘルパー）

## 入力仕様

### 入力パラメータ

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

### 入力データソース

- 呼び出し元コードから提供される識別子（オプション）
- 内部的に`g.LastItemData`（直前のアイテム情報）を参照
- マウス入力状態（`g.IO.MouseReleased`）

## 出力仕様

### 出力データ

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

### 出力先

- 条件を満たした場合、`g.OpenPopupStack`にポップアップ情報を追加

## 処理フロー

### 処理シーケンス

```
1. マウスボタン種類の取得
   └─ GetMouseButtonFromPopupFlags(popup_flags)
   └─ デフォルトは右ボタン（ImGuiMouseButton_Right）
2. マウスリリース判定
   └─ IsMouseReleased(mouse_button)
3. アイテムホバー判定
   └─ IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)
4. ポップアップID決定
   └─ str_id != NULL: window->GetID(str_id)
   └─ str_id == NULL: g.LastItemData.ID
5. ポップアップを開く
   └─ OpenPopupEx(id, popup_flags)
```

### フローチャート

```mermaid
flowchart TD
    A[OpenPopupOnItemClick開始] --> B[マウスボタン種類取得]
    B --> C{IsMouseReleased?}
    C -->|No| D[return]
    C -->|Yes| E{IsItemHovered AllowWhenBlockedByPopup?}
    E -->|No| D
    E -->|Yes| F{str_id != NULL?}
    F -->|Yes| G[id = GetID str_id]
    F -->|No| H[id = LastItemData.ID]
    G --> I{id != 0?}
    H --> I
    I -->|No| J[アサーション失敗]
    I -->|Yes| K[OpenPopupEx id, popup_flags]
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-166-01 | リリースイベント | マウスボタンのリリース時にポップアップが開く（プレス時ではない） | 常時 |
| BR-166-02 | デフォルト右クリック | popup_flags = 0の場合、右クリックがトリガー | フラグ未指定時 |
| BR-166-03 | LastItemID使用 | str_id = NULLの場合、直前のアイテムのIDが使用される | str_id未指定時 |
| BR-166-04 | ID必須 | str_id = NULLで直前のアイテムにIDがない場合（例: Text()）はアサーション失敗 | str_id=NULL時 |
| BR-166-05 | ポップアップブロック無視 | 既存ポップアップでブロックされていてもホバー判定される | 常時 |

### 計算ロジック

- マウスボタン: `(popup_flags & ImGuiPopupFlags_MouseButtonMask_) >> ImGuiPopupFlags_MouseButtonShift_) - 1`
- デフォルトは`ImGuiMouseButton_Right`（右ボタン）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション失敗 | str_id = NULLで直前アイテムにIDがない | str_idを明示的に指定する |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

- 処理時間: 即時
- マウス状態とホバー状態のチェックのみ

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

特になし。

## 備考

- `BeginPopupContextItem`との違い: OpenPopupOnItemClickは`BeginPopup`を含まない
- バージョン1.92.6以前は`popup_flags = 1`がデフォルトだったが、現在は`= 0`（右クリック）
- Text()などIDを持たないアイテムに対して使用する場合は、str_idを明示的に指定する必要がある
- 使用パターン: `OpenPopupOnItemClick("my_popup"); if (BeginPopup("my_popup")) { ... EndPopup(); }`

---

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

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

### 推奨読解順序

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

ポップアップフラグとマウスボタン判定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiPopupFlags_MouseButton*定義（1340-1343行目） |
| 1-2 | imgui_internal.h | `imgui_internal.h` | LastItemData構造体 |

**読解のコツ**: `ImGuiPopupFlags_MouseButtonRight = 2 << 2 = 8`がデフォルト。マスクとシフトでマウスボタン番号を抽出する。

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

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

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

**主要処理フロー**:
1. **12472行目**: GetMouseButtonFromPopupFlagsでマウスボタン種類を取得
2. **12473行目**: IsMouseReleasedとIsItemHoveredの両方をチェック
3. **12475行目**: ID決定（str_idまたはLastItemData.ID）
4. **12476行目**: IDが0でないことをアサート
5. **12477行目**: OpenPopupExを呼び出し

#### Step 3: マウスボタン判定を理解する

`GetMouseButtonFromPopupFlags`の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | GetMouseButtonFromPopupFlags実装（12453-12464行目） |

**主要処理フロー**:
- **12461-12462行目**: マスクとシフトでマウスボタン番号を計算
- **12463行目**: デフォルトは右ボタン（ImGuiMouseButton_Right）

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

```
OpenPopupOnItemClick(str_id, popup_flags)
    │
    ├─ GetMouseButtonFromPopupFlags(popup_flags)
    │      └─ マウスボタン種類を計算
    │
    ├─ IsMouseReleased(mouse_button)
    │      └─ マウスリリース判定
    │
    ├─ IsItemHovered(AllowWhenBlockedByPopup)
    │      └─ アイテムホバー判定
    │
    ├─ ID決定
    │      ├─ window->GetID(str_id)  [str_id != NULL]
    │      └─ g.LastItemData.ID      [str_id == NULL]
    │
    └─ OpenPopupEx(id, popup_flags)
           └─ ポップアップを開く
```

### データフロー図

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

str_id (文字列/NULL) ─▶ OpenPopupOnItemClick() ─▶ (なし)
popup_flags            │
                       ├─ マウスボタン判定
                       │   └─ g.IO.MouseReleased
                       │
                       ├─ ホバー判定
                       │   └─ g.LastItemData
                       │
                       └─ OpenPopupEx()
                           └─ g.OpenPopupStack
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダ | 関数宣言（858行目）、ImGuiPopupFlags定義 |
| imgui.cpp | `imgui.cpp` | ソース | OpenPopupOnItemClick実装（12468-12478行目）、GetMouseButtonFromPopupFlags（12453-12464行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダ | LastItemData構造体 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（5397行目） |
