# 機能設計書 156-MenuItem

## 概要

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

### 本機能の処理概要

MenuItemは、メニュー内に選択可能なアイテム（メニュー項目）を作成するための関数である。クリックまたはキーボード選択によりアクティベートされ、アクションを実行できる。ショートカットキーの表示や、チェックマーク表示による選択状態の視覚化にも対応している。

**業務上の目的・背景**：メニューシステムにおいて、「開く」「保存」「終了」などの実際のアクションを実行するための項目が必要である。MenuItemは、これらのアクション項目を作成し、ユーザーがクリックまたはキーボードで選択した際にアプリケーションが応答できるようにする。ショートカットキーの表示機能により、ユーザーにキーボードショートカットを案内できる。

**機能の利用シーン**：メニューバーやサブメニュー内で、実際のアクションを実行する項目を作成する際に使用。例えば「ファイル」メニュー内の「新規作成」「開く」「保存」など。Main Menu Bar画面やDemo Windowなどで使用される。

**主要な処理内容**：
1. ラベルサイズを計算する
2. レイアウト（水平/垂直）に応じた描画を行う
3. Selectableを使用してインタラクションを処理する
4. ショートカットテキストを描画する（垂直レイアウト時）
5. 選択状態の場合はチェックマークを描画する
6. クリック時にtrueを返し、p_selectedがあれば値を反転する

**関連システム・外部連携**：Selectable、RenderText、RenderCheckMark等の描画関数を使用。

**権限による制御**：enabledパラメータによりアイテムの有効/無効を制御可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | Main Menu Bar | 主機能 | メニューアイテムの作成 |
| 21 | Documents | 補助機能 | メニューアイテムの作成 |

## 機能種別

ウィジェット / インタラクション

## 入力仕様

### 入力パラメータ

#### オーバーロード1（選択状態をboolで受け取る）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | アイテムのラベルテキスト | NULL終端文字列 |
| shortcut | const char* | No | ショートカットキーの表示文字列（デフォルト: NULL） | NULL終端文字列 |
| selected | bool | No | 選択状態（チェックマーク表示）（デフォルト: false） | - |
| enabled | bool | No | アイテムが有効かどうか（デフォルト: true） | - |

#### オーバーロード2（選択状態をポインタで受け取る）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | アイテムのラベルテキスト | NULL終端文字列 |
| shortcut | const char* | No | ショートカットキーの表示文字列 | NULL終端文字列 |
| p_selected | bool* | No | 選択状態へのポインタ（クリック時に反転） | NULLまたは有効なポインタ |
| enabled | bool | No | アイテムが有効かどうか（デフォルト: true） | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | アイテムがアクティベートされた場合true |

### 出力先

- 描画リスト（メニューアイテムの描画）
- p_selected（オーバーロード2の場合、クリック時に反転）

## 処理フロー

### 処理シーケンス

```
1. 初期化とサイズ計算
   └─ ウィンドウ取得とSkipItemsチェック
   └─ ラベルサイズをCalcTextSizeで計算

2. menuset_is_openの判定
   └─ IsRootOfOpenMenuSet()でメニューセットのルートか判定
   └─ trueならNoWindowHoverableCheckフラグをプッシュ

3. レイアウトに応じた描画
   └─ 水平レイアウト（メニューバー内）:
      └─ Selectableを使用
      └─ 選択状態はハイライトで表示
   └─ 垂直レイアウト（メニュー内）:
      └─ MenuColumnsでアイコン/ラベル/ショートカット/チェックマークの幅を管理
      └─ Selectableを使用
      └─ ショートカットテキストを灰色で描画
      └─ 選択状態はチェックマークで表示

4. インタラクション処理
   └─ Selectableがtrueを返したらアクティベート

5. クリーンアップ
   └─ PopID()
   └─ PopItemFlag() [menuset_is_openの場合]

6. 戻り値の返却
   └─ オーバーロード1: pressedを返す
   └─ オーバーロード2: pressedがtrueならp_selectedを反転し、trueを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: MenuItem] --> B{SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D[ラベルサイズ計算]
    D --> E[menuset_is_open判定]
    E --> F[PushID]
    F --> G{enabled?}
    G -->|No| H[BeginDisabled]
    G -->|Yes| I{水平レイアウト?}
    H --> I
    I -->|Yes| J[水平メニュー項目描画]
    I -->|No| K[垂直メニュー項目描画<br/>ショートカット+チェックマーク]
    J --> L[Selectable]
    K --> L
    L --> M{enabled?}
    M -->|No| N[EndDisabled]
    M -->|Yes| O[PopID]
    N --> O
    O --> P{menuset_is_open?}
    P -->|Yes| Q[PopItemFlag]
    P -->|No| R{pressed?}
    Q --> R
    R -->|Yes| S{p_selected != NULL?}
    R -->|No| T[return false]
    S -->|Yes| U[*p_selected = !*p_selected<br/>return true]
    S -->|No| V[return true]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-156-01 | ショートカット表示 | ショートカットは表示のみで処理はしない | 常時 |
| BR-156-02 | チェックマーク | selected=trueの場合はチェックマークを表示 | 垂直レイアウト時 |
| BR-156-03 | 自動ポップアップ閉鎖 | アクティベート時に親ポップアップを閉じる | ImGuiItemFlags_AutoClosePopups |
| BR-156-04 | トグル動作 | p_selectedバージョンはクリック時に値を反転 | p_selected != NULL |

### 計算ロジック

- MenuColumnsによる幅計算:
  - icon_w: アイコンの幅（0またはアイコンテキストサイズ）
  - label_size.x: ラベルの幅
  - shortcut_w: ショートカットテキストの幅
  - checkmark_w: `IM_TRUNC(g.FontSize * 1.20f)`

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

データベース操作なし（UI描画のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 早期リターン | window->SkipItems == true | falseを返す |

### リトライ仕様

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

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

トランザクション管理なし（即時描画）

## パフォーマンス要件

- 単一フレーム内で複数回呼び出し可能
- 通常のウィジェットと同程度の処理コスト

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

- 特になし

## 備考

- MenuItemEx()という拡張版があり、アイコン表示にも対応
- ショートカットキーは表示されるだけで、実際のキー処理はアプリケーション側で実装する必要がある
- 水平レイアウト（メニューバー内）ではショートカットは表示されない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 815-816行目: MenuItem API宣言（2つのオーバーロード）を確認 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiMenuColumnsの定義を確認 |

**読解のコツ**: MenuItemには2つのオーバーロードがあり、どちらも内部でMenuItemExを呼び出す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9505-9508行目: MenuItem（オーバーロード1） |
| 2-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9510-9519行目: MenuItem（オーバーロード2） |
| 2-3 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9427-9503行目: MenuItemEx関数の実装 |

**主要処理フロー**:
1. **9429-9436行目**: ウィンドウ取得、SkipItemsチェック、サイズ計算
2. **9438-9441行目**: menuset_is_open判定とフラグプッシュ
3. **9446-9466行目**: 水平レイアウトの処理
4. **9467-9494行目**: 垂直レイアウトの処理
5. **9496-9502行目**: クリーンアップと戻り値

#### Step 3: 描画処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9477-9493行目: 垂直レイアウトでの描画 |

**主要処理フロー**:
- **9481行目**: ラベルテキストの描画
- **9482-9483行目**: アイコンの描画（存在する場合）
- **9484-9490行目**: ショートカットテキストの描画
- **9491-9492行目**: チェックマークの描画

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

```
ImGui::MenuItem(label, shortcut, selected, enabled)
    │
    └─ MenuItemEx(label, NULL, shortcut, selected, enabled)
           │
           ├─ GetCurrentWindow()
           ├─ CalcTextSize(label)
           │
           ├─ IsRootOfOpenMenuSet()
           │      └─ メニューセットのルートか判定
           │
           ├─ PushItemFlag() [条件付き]
           ├─ PushID(label)
           ├─ BeginDisabled() [enabledがfalseの場合]
           │
           ├─ window->DC.MenuColumns.DeclColumns()
           │      └─ 列幅を計算・記録
           │
           ├─ Selectable()
           │      └─ クリック/キーボード選択を検出
           │
           ├─ RenderText()
           │      └─ ラベル、ショートカット、アイコンを描画
           │
           ├─ RenderCheckMark() [selected時]
           │      └─ チェックマークを描画
           │
           ├─ EndDisabled() [enabledがfalseの場合]
           └─ PopID()

ImGui::MenuItem(label, shortcut, p_selected, enabled)
    │
    └─ MenuItemEx(label, NULL, shortcut, *p_selected, enabled)
           │
           └─ [上記と同様]
                  │
                  └─ [pressed時] *p_selected = !*p_selected
```

### データフロー図

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

label ────────────────────> CalcTextSize ───────────────> label_size
shortcut ─────────────────> CalcTextSize ───────────────> shortcut_w
                                  │
window->DC.LayoutType ────> レイアウト判定
                                  │
                                  ├── [水平] ────────────────> Selectable + RenderText
                                  │
                                  └── [垂直] ────────────────> MenuColumns.DeclColumns
                                           │                   Selectable + RenderText
                                           │                   RenderCheckMark [条件]
                                           │
selected ─────────────────────────────────> チェックマーク判定
                                           │
Selectable() ─────────────────────────────> pressed
                                           │
p_selected ───────────────────────────────> [pressed時] 値反転
                                           │
                                           └──────────────────> return pressed
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | MenuItem APIの宣言（2つのオーバーロード） |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiMenuColumns等の内部定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | MenuItem実装（9505-9519行目）、MenuItemEx実装（9427-9503行目） |
| imgui.cpp | `imgui.cpp` | ソース | RenderCheckMark等の描画関数 |
