# 通知設計書 19-ImGuiPopupFlags_NoReopen

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける`ImGuiPopupFlags_NoReopen`フラグの設計仕様を記載する。このフラグは、既に開いているポップアップを再オープンしないことを指定する。

### 本通知の処理概要

`ImGuiPopupFlags_NoReopen`は、OpenPopup系関数およびBeginPopupContext系関数で使用され、同じポップアップが既に開いている場合に再オープン処理を抑制する。これにより、ポップアップの位置変更やナビゲーション初期化を防ぐことができる。

**業務上の目的・背景**：ポップアップを繰り返し開く操作において、位置のリセットやフォーカス状態の初期化を避けたい場合がある。例えば、メニューバーのメニューを切り替える際に、既に開いているメニューの位置を維持したい場合などに使用される。このフラグは、そのようなユースケースに対応するための手段を提供する。

**通知の送信タイミング**：このフラグ自体は送信を行わない。OpenPopupEx関数内で、同じIDのポップアップが前フレームで開かれている場合に、フレームカウントの更新のみを行い、完全な再オープン処理をスキップする。

**通知の受信者**：OpenPopupEx関数内のポップアップ再オープン判定ロジック。

**通知内容の概要**：同一ポップアップが開いている場合は再オープン処理を省略する指示。

**期待されるアクション**：ポップアップの位置と状態が維持され、ちらつきのない動作になる。

## 通知種別

フラグ定数 / ポップアップ動作オプション

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| フラグ値 | 1 << 5 = 32 |
| カテゴリ | 再オープン制御 |
| 排他性 | なし（他のフラグと併用可能） |

### フラグ処理ロジック

OpenPopupEx関数内で以下の条件で再オープンがスキップされる：
1. 同じIDのポップアップが既にOpenPopupStackにある
2. そのポップアップが前フレーム（g.FrameCount - 1）で開かれた、またはNoReopenフラグが設定されている
3. この場合、OpenFrameCountのみ更新し、位置やナビゲーション初期化はスキップ

## 通知テンプレート

### フラグ定義

| 項目 | 内容 |
|-----|------|
| フラグ名 | ImGuiPopupFlags_NoReopen |
| 値 | 1 << 5 (= 32) |
| 定義場所 | imgui.h:1343 |

### 使用例

```cpp
// NoReopenで位置を維持
if (ImGui::BeginMenu("File"))
{
    if (ImGui::MenuItem("New")) { /* 処理 */ }
    if (ImGui::MenuItem("Open")) { /* 処理 */ }
    ImGui::EndMenu();
}

// 明示的にNoReopenを指定
ImGui::OpenPopup("settings_popup", ImGuiPopupFlags_NoReopen);
if (ImGui::BeginPopup("settings_popup"))
{
    ImGui::Text("Settings");
    ImGui::EndPopup();
}

// BeginPopupContext系でも使用可能
if (ImGui::BeginPopupContextItem("context", ImGuiPopupFlags_MouseButtonRight | ImGuiPopupFlags_NoReopen))
{
    ImGui::MenuItem("Option");
    ImGui::EndPopup();
}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | フラグ定義のため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| N/A | N/A | N/A | フラグ定義のため変数なし |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | OpenPopup/OpenPopupEx | 同一IDポップアップが開いている | 再オープンスキップ判定 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 前フレームでなく開かれた | OpenFrameCount != g.FrameCount - 1 |

## 処理フロー

### フラグ処理フロー

```mermaid
flowchart TD
    A[OpenPopupEx呼び出し] --> B{既にスタックに同一ID?}
    B -->|No| C[新規ポップアップ追加]
    B -->|Yes| D{前フレームで開かれた OR NoReopen?}
    D -->|Yes| E[OpenFrameCountのみ更新]
    D -->|No| F[ClosePopupToLevel実行]
    F --> G[新規ポップアップ追加]
    E --> H[再オープンスキップ]
    C --> I[終了]
    G --> I
    H --> I
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| g.OpenPopupStack | 既存ポップアップ確認 | 同一ID検索 |
| g.FrameCount | フレームカウント | 前フレーム判定 |

### テーブル別参照項目詳細

#### g.OpenPopupStack

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| PopupId | 同一ID確認 | current_stack_sizeインデックス |
| OpenFrameCount | 前フレーム判定 | g.FrameCount - 1 との比較 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| g.OpenPopupStack | UPDATE | OpenFrameCountの更新 |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| UPDATE | OpenFrameCount | g.FrameCount | 再オープンスキップ時 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 特になし | N/A | フラグ使用にエラーケースなし |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | N/A |
| 1日あたり上限 | N/A |

### 配信時間帯

フラグ定義のため配信概念なし。

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

フラグ定義であり、セキュリティ上のリスクは存在しない。

## 備考

- ImGuiは内部的に連続フレームでのOpenPopup呼び出しを検出し、暗黙的にNoReopen動作を行う
- これは誤ってOpenPopupを毎フレーム呼び出す開発者向けの保護機能
- メニューシステム（BeginMenu）では、内部でNoReopenが使用されている（imgui_widgets.cpp:9368）
- コメントにある「won't reposition, won't reinitialize navigation」が主な効果

---

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

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

### 推奨読解順序

#### Step 1: フラグ定義を理解する

ImGuiPopupFlags_列挙型の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiPopupFlags_NoReopen定義（1343行目） |
| 1-2 | imgui.h | `imgui.h` | コメント「don't reopen same popup if already open」 |

**読解のコツ**: NoReopen = 1 << 5 = 32。コメントに動作が明記されている。

#### Step 2: OpenPopupExでの処理を理解する

OpenPopupEx関数内でのNoReopenフラグ処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | OpenPopupEx関数（12172行目） |
| 2-2 | imgui.cpp | `imgui.cpp` | 再オープンスキップ処理（12196-12210行） |

**主要処理フロー**:
1. **12203-12205行**: 同一IDポップアップが存在し、前フレームで開かれた or NoReopenフラグ
2. **12206-12210行**: keep_existing = true → OpenFrameCountのみ更新
3. **12211-12216行**: keep_existing = false → ClosePopupToLevel + 新規追加

#### Step 3: メニューでの使用例を確認する

BeginMenu内でのNoReopen使用を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | BeginMenu内での使用（9368行目） |

**使用コンテキスト**:
- メニューが既に開いている場合に再初期化を防ぐ

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

```
OpenPopup() / BeginPopupContext*()
    |
    +-- OpenPopupEx(id, popup_flags)  [imgui.cpp:12172]
            |
            +-- 現在のスタックサイズ確認
            |
            +-- {スタックサイズ > current_stack_size + 1?}
            |       |
            |       +-- Yes: 既存エントリ確認
            |               |
            |               +-- {同一PopupId?}
            |                       |
            |                       +-- {前フレーム or NoReopen?}
            |                               |
            |                               +-- Yes: keep_existing = true
            |                               |       → OpenFrameCountのみ更新
            |                               |
            |                               +-- No: ClosePopupToLevel
            |                                       → 新規追加
            |
            +-- No: 新規ポップアップ追加
```

### データフロー図

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

popup_flags (NoReopen含む)
        |
        +──▶ OpenPopupEx
                |
                +──▶ g.OpenPopupStack[current_stack_size] 確認
                |           |
                |           +──▶ PopupId == id ?
                |           |
                |           +──▶ OpenFrameCount == g.FrameCount - 1 ?
                |           |
                |           +──▶ popup_flags & NoReopen ?
                |
                +──▶ keep_existing判定
                        |
                        +──▶ true: OpenFrameCount更新のみ
                        |
                        +──▶ false: 完全再オープン
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | ImGuiPopupFlags_NoReopen定義（1343行目） |
| imgui.cpp | `imgui.cpp` | ソース | OpenPopupEx実装（12172行目） |
| imgui.cpp | `imgui.cpp` | ソース | 再オープンスキップ処理（12201-12210行） |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | BeginMenu内での使用（9368行目） |
| imgui.cpp | `imgui.cpp` | ソース | API BREAKING CHANGESコメント（415行） |
