# 機能設計書 145-BeginListBox

## 概要

本ドキュメントは、Dear ImGuiライブラリにおけるBeginListBox関数の機能設計を記述する。BeginListBoxはフレーム付きのスクロール可能なリスト領域を開始する関数である。

### 本機能の処理概要

BeginListBox関数は、フレームスタイルの子ウィンドウを作成し、その中にSelectable等のアイテムを配置できるリストボックス領域を開始する。内部的にはBeginChild with ImGuiChildFlags_FrameStyleのラッパーとして機能する。

**業務上の目的・背景**：リストボックスは、複数の選択肢から1つまたは複数を選択するUIパターンとして広く使用される。BeginListBoxは、スクロール可能なフレーム付き領域を簡単に作成し、カスタムコンテンツを配置できる柔軟な基盤を提供する。

**機能の利用シーン**：
- ファイル選択ダイアログのファイル一覧
- 設定画面のオプション選択
- プロパティエディタの値選択
- ログビューアのフィルタ選択
- カスタムリストコンポーネントの作成

**主要な処理内容**：
1. ラベルサイズの計算とレイアウト
2. フレームサイズの決定（デフォルトは約7.25アイテム分の高さ）
3. 表示判定と早期リターン
4. グループの開始とラベルの描画
5. 子ウィンドウ（BeginChild with FrameStyle）の開始

**関連システム・外部連携**：
- EndListBoxとペアで使用
- 内部でSelectable等のウィジェットを配置
- ListBoxヘルパー関数から呼び出される

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | Widgets | 補助機能 | リストボックスのデモ |

## 機能種別

スコープ開始 / 子ウィンドウ作成 / レイアウト

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | リストボックスのラベル。##で非表示ラベル指定可能 | NULL不可 |
| size | ImVec2 | No | サイズ指定。詳細は下記 | - |

### サイズ指定の詳細

| size.x | 動作 |
|--------|------|
| > 0.0f | カスタム幅 |
| < 0.0f または -FLT_MIN | 右揃え |
| = 0.0f（デフォルト） | 現在のItemWidthを使用 |

| size.y | 動作 |
|--------|------|
| > 0.0f | カスタム高さ |
| < 0.0f または -FLT_MIN | 下揃え |
| = 0.0f（デフォルト） | 約7アイテム分の高さ |

### 入力データソース

- 呼び出し元からの直接パラメータ指定
- グローバルコンテキスト（GImGui）からのスタイル設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | trueの場合のみEndListBoxを呼び出す必要がある |

### 出力先

- 画面描画（フレーム付き子ウィンドウ）
- 内部状態（子ウィンドウのプッシュ）

## 処理フロー

### 処理シーケンス

```
1. ウィンドウのスキップ確認
   └─ window->SkipItemsがtrueなら早期リターン

2. ラベルサイズの計算
   └─ CalcTextSizeでラベルサイズを取得

3. フレームサイズの計算
   └─ デフォルトで約7.25アイテム分の高さ
   └─ CalcItemSizeで最終サイズを決定

4. 表示判定
   └─ IsRectVisibleで表示領域判定
   └─ 非表示ならItemSize/ItemAddのみ実行してfalseを返す

5. グループの開始
   └─ BeginGroupでレイアウトグループを開始

6. ラベルの描画
   └─ ラベルがある場合はRenderTextで描画

7. 子ウィンドウの開始
   └─ BeginChild with ImGuiChildFlags_FrameStyle
   └─ trueを返す
```

### フローチャート

```mermaid
flowchart TD
    A[BeginListBox開始] --> B{SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D[ラベルサイズ計算]
    D --> E[フレームサイズ計算]
    E --> F[バウンディングボックス計算]
    F --> G{IsRectVisible?}
    G -->|No| H[ItemSize/ItemAdd]
    H --> I[NextWindowData.ClearFlags]
    I --> C
    G -->|Yes| J[BeginGroup]
    J --> K{ラベルあり?}
    K -->|Yes| L[RenderText]
    K -->|No| M[BeginChild FrameStyle]
    L --> M
    M --> N[return true]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-145-01 | ペア呼び出し | trueを返した場合のみEndListBoxを呼び出す | 常時 |
| BR-145-02 | 非表示ラベル | ##で非表示ラベルを使用すると全幅のリストボックスが作成可能 | 全幅表示時 |
| BR-145-03 | スクロール対応 | 内部は自動スクロール対応の子ウィンドウ | 常時 |
| BR-145-04 | デフォルト高さ | 約7.25アイテム分の高さがデフォルト | size.y = 0.0f時 |

### 計算ロジック

デフォルトサイズ計算:
```cpp
size = ImTrunc(CalcItemSize(size_arg, CalcItemWidth(),
    GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f));
```

7.25の端数は、スクロールが可能であることを視覚的に示すため。

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

該当なし（ImGuiはインメモリUIライブラリ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション | BeginListBox/EndListBoxの不一致 | trueを返した場合のみEndListBoxを呼び出す |

### リトライ仕様

該当なし

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

BeginListBoxとEndListBoxで囲まれたスコープ内でリストアイテムを追加する。

## パフォーマンス要件

- 非表示時は早期リターンで最適化
- ImGuiListClipperと組み合わせて大量アイテムの効率的な描画が可能

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

特になし。

## 備考

- ラベル不要な場合はBeginChild with ImGuiChildFlags_FrameStyleを直接使用可能
- size.x = -FLT_MINで全幅のリストボックスを作成可能
- 10.5f * item_heightのような端数指定でスクロール可能であることを示唆可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | BeginListBox関数宣言（785-786行目）とコメントを確認 |

**読解のコツ**: コメントにサイズ指定の詳細な説明がある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | BeginListBox実装（8630-8669行目） |

**主要処理フロー**:
1. **8634-8635行目**: ウィンドウスキップ判定
2. **8639行目**: ラベルサイズ計算
3. **8643行目**: フレームサイズ計算（デフォルト7.25アイテム分）
4. **8649-8655行目**: 非表示時の早期リターン処理
5. **8658行目**: BeginGroupの呼び出し
6. **8659-8665行目**: ラベルの描画
7. **8667行目**: BeginChild with FrameStyle

#### Step 3: EndListBoxを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | EndListBox実装（8671-8680行目） |

**主要処理フロー**:
- **8675行目**: 子ウィンドウ確認のアサーション
- **8678行目**: EndChildの呼び出し
- **8679行目**: EndGroupの呼び出し

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

```
BeginListBox(label, size)
    │
    ├─ GetCurrentWindow()
    │
    ├─ CalcTextSize(label)
    │
    ├─ CalcItemSize(size_arg, ...)
    │
    ├─ IsRectVisible(bb.Min, bb.Max)
    │
    ├─ [if not visible] ItemSize() / ItemAdd() → return false
    │
    ├─ BeginGroup()
    │
    ├─ [if label] RenderText(label_pos, label)
    │
    └─ BeginChild(id, size, ImGuiChildFlags_FrameStyle)
          └─ return true
```

### データフロー図

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

label ─────────────────────┐
                           │
size ──────────────────────┼──▶ BeginListBox() ──────────────▶ bool (success)
                           │           │
                           │           ├──▶ 子ウィンドウ作成
g.Style ───────────────────┘           │    (フレームスタイル)
                                       │
                                       └──▶ ラベル描画
                                            (右側に表示)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | BeginListBox/EndListBox実装 |
