# 機能設計書 142-BeginMultiSelect

## 概要

本ドキュメントは、Dear ImGuiライブラリにおけるBeginMultiSelect関数の機能設計を記述する。BeginMultiSelectはSelectable、Checkbox、TreeNode等のウィジェットに対する複数選択機能のスコープを開始する関数である。

### 本機能の処理概要

BeginMultiSelect関数は、マルチセレクション（複数選択）機能のスコープを開始し、Ctrl+クリック、Shift+クリック、ボックス選択などの標準的な複数選択操作を実現する基盤を提供する。

**業務上の目的・背景**：現代のGUIアプリケーションでは、ファイル管理、データ一括編集、項目の複数選択など、複数アイテムを同時に選択・操作する機能が必須である。BeginMultiSelectは、このような複雑な選択ロジックを抽象化し、クリッパー（仮想スクロール）と組み合わせた効率的な実装を可能にする。

**機能の利用シーン**：
- ファイルエクスプローラーでの複数ファイル選択
- データグリッドでの複数行選択
- アセット管理画面でのバッチ操作
- プレイリスト編集での複数曲選択
- メール一覧での複数メール選択

**主要な処理内容**：
1. マルチセレクトスコープの初期化とIDの生成
2. フォーカススコープのプッシュ
3. ボックス選択機能の初期化（有効時）
4. Ctrl+Aによる全選択、Escapeによる選択解除のショートカット処理
5. 選択リクエストの生成と管理
6. ImGuiMultiSelectIO構造体を通じた状態の返却

**関連システム・外部連携**：
- Selectable、TreeNode、Checkboxウィジェットと連携
- SetNextItemSelectionUserDataによるアイテム識別
- ImGuiListClipperによる仮想スクロールとの連携

**権限による制御**：フラグにより単一選択モード、選択解除の禁止、ボックス選択の有効/無効などを制御可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | Assets Browser | 主機能 | アセットの複数選択 |
| 23 | Widgets | 主機能 | マルチセレクトのデモ |

## 機能種別

スコープ開始 / 選択状態管理 / ユーザーインタラクション処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| flags | ImGuiMultiSelectFlags | Yes | マルチセレクトの動作フラグ | ImGuiMultiSelectFlags_列挙値 |
| selection_size | int | No | 現在の選択数（-1で不明） | >= -1 |
| items_count | int | No | 総アイテム数（-1で不明） | >= -1 |

### 入力データソース

- 呼び出し元からの直接パラメータ指定
- グローバルコンテキスト（GImGui）からのナビゲーション状態
- 永続化ストレージ（ImGuiMultiSelectState）からの前フレーム状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | ImGuiMultiSelectIO* | マルチセレクト操作のI/O構造体へのポインタ |
| Requests | ImVector<ImGuiSelectionRequest> | アプリケーションへの選択変更リクエスト |
| RangeSrcItem | ImGuiSelectionUserData | Shift選択の起点アイテム |
| NavIdItem | ImGuiSelectionUserData | ナビゲーション対象アイテム |

### 出力先

- ImGuiMultiSelectIO構造体（アプリケーションが読み取り・処理）
- 内部状態の更新（フォーカススコープ、ストレージ）

## 処理フロー

### 処理シーケンス

```
1. スタックへのプッシュ
   └─ MultiSelectTempDataのサイズ拡張と初期化

2. フラグの正規化
   └─ ScopeWindow/ScopeRectの自動設定
   └─ SingleSelect時のBoxSelect無効化

3. フォーカススコープの設定
   └─ PushFocusScopeでスコープをプッシュ

4. ストレージの取得/作成
   └─ MultiSelectStorage.GetOrAddByKeyで永続状態を取得

5. ボックス選択の初期化
   └─ BoxSelect1d/2dフラグ時にBeginBoxSelectを呼び出し

6. ショートカット処理
   └─ Escapeで選択クリア、Ctrl+Aで全選択

7. IOの初期化と返却
   └─ ImGuiMultiSelectIO構造体にデータを設定して返却
```

### フローチャート

```mermaid
flowchart TD
    A[BeginMultiSelect開始] --> B[TempDataスタック拡張]
    B --> C[フラグ正規化]
    C --> D{SingleSelect?}
    D -->|Yes| E[BoxSelect無効化]
    D -->|No| F[フラグ維持]
    E --> G[PushFocusScope]
    F --> G
    G --> H[ストレージ取得]
    H --> I{BoxSelect有効?}
    I -->|Yes| J[BeginBoxSelect]
    I -->|No| K[IOの初期化]
    J --> K
    K --> L{IsFocused?}
    L -->|Yes| M{Escape押下?}
    L -->|No| N[IO返却]
    M -->|Yes| O[選択クリアリクエスト]
    M -->|No| P{Ctrl+A押下?}
    O --> N
    P -->|Yes| Q[全選択リクエスト]
    P -->|No| N
    Q --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-142-01 | Shift選択 | Shift+クリックで範囲選択 | NoRangeSelectフラグなし |
| BR-142-02 | Ctrl選択 | Ctrl+クリックで個別追加/解除 | 常時 |
| BR-142-03 | 全選択 | Ctrl+Aで全アイテム選択 | NoSelectAllフラグなし、フォーカス時 |
| BR-142-04 | 選択解除 | Escapeで全選択解除 | ClearOnEscapeフラグあり、フォーカス時 |
| BR-142-05 | ボックス選択 | ドラッグで矩形選択 | BoxSelect1d/2dフラグあり |

### 計算ロジック

フラグの自動設定:
- ScopeWindow/ScopeRectが未指定の場合、ScopeWindowを自動設定
- SingleSelect時はBoxSelect1d/2dを自動無効化
- BoxSelect2d時はBoxSelect1dを自動無効化

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション | BeginMultiSelect/EndMultiSelectの不一致 | 必ずペアで呼び出す |
| - | アサーション | IsKeyboardSetRange時にRangeSrcItemが無効 | クリッパー使用時はRangeSrcItemをInclude |

### リトライ仕様

該当なし

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

BeginMultiSelectとEndMultiSelectで囲まれたスコープ内で選択状態の変更が行われる。スコープ外では選択リクエストの適用はアプリケーションの責務。

## パフォーマンス要件

- selection_sizeを正確に渡すことで、Escapeショートカットの最適なルーティングが可能
- items_countは内部処理には使用されず、ApplyRequestsハンドラへの便宜のために保持
- クリッパーとの併用により、表示外アイテムの処理をスキップ可能

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

内部状態はImGuiStorageで管理され、ウィンドウIDに基づいて分離される。

## 備考

- BETA機能として提供されており、APIは将来変更される可能性がある
- TreeNodeでの使用は複雑なため、高度なツリー実装が必要
- 詳細はDemo->Widgets->Selection State & Multi-Selectを参照

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiMultiSelectFlags_列挙型（3009-3031行目）でフラグオプションを理解 |
| 1-2 | imgui.h | `imgui.h` | ImGuiMultiSelectIO構造体（3038-3047行目）でI/Oデータ構造を理解 |
| 1-3 | imgui.h | `imgui.h` | ImGuiSelectionRequest構造体（3058-3066行目）で選択リクエスト形式を理解 |

**読解のコツ**: ImGuiMultiSelectIOの各フィールドにはBeginMultiSelect/EndMultiSelectでの読み書き方向がコメントで示されている（ms:w=multi-select書き込み、app:r=アプリ読み取り）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | BeginMultiSelect関数宣言（773行目） |
| 2-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | BeginMultiSelect実装（7890-8009行目） |

**主要処理フロー**:
1. **7895-7899行目**: TempDataスタックの拡張とクリア
2. **7900-7905行目**: フラグの正規化（Scope、BoxSelect関連）
3. **7914-7924行目**: フォーカススコープのプッシュとナビゲーションレイヤー設定
4. **7930-7936行目**: 永続ストレージの取得/作成
5. **7966-7972行目**: ボックス選択の初期化
6. **7976-7993行目**: Escape/Ctrl+Aショートカット処理
7. **7996-8002行目**: SetAllリクエストの生成

#### Step 3: 内部状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_internal.h | `imgui_internal.h` | ImGuiMultiSelectTempData構造体（一時データ） |
| 3-2 | imgui_internal.h | `imgui_internal.h` | ImGuiMultiSelectState構造体（永続データ） |

**主要処理フロー**:
- **ms->FocusScopeId**: 現在のマルチセレクトスコープのID
- **ms->IsFocused**: このスコープがフォーカスされているか
- **storage->RangeSrcItem**: Shift選択の起点
- **storage->NavIdItem**: ナビゲーション対象

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

```
BeginMultiSelect(flags, selection_size, items_count)
    │
    ├─ g.MultiSelectTempData.resize()
    │
    ├─ ms->Clear()
    │
    ├─ PushFocusScope(ms->FocusScopeId)
    │
    ├─ g.MultiSelectStorage.GetOrAddByKey(id)
    │
    ├─ [if BoxSelect] BeginBoxSelect(scope_rect, ...)
    │
    ├─ [if focused && ClearOnEscape] Shortcut(ImGuiKey_Escape)
    │     └─ MultiSelectAddSetAll(ms, false)
    │
    ├─ [if focused && !SingleSelect] Shortcut(Ctrl+A)
    │     └─ MultiSelectAddSetAll(ms, true)
    │
    └─ return &ms->IO
```

### データフロー図

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

flags ─────────────────────┐
                           │
selection_size ────────────┼──▶ BeginMultiSelect() ──────────▶ ImGuiMultiSelectIO*
                           │           │                            │
items_count ───────────────┘           │                            ├── Requests[]
                                       │                            ├── RangeSrcItem
g.NavJustMovedToId ───────────────────▶│                            ├── NavIdItem
                                       │                            └── ItemsCount
g.NavFocusScopeId ────────────────────▶│
                                       │
g.IO.KeyMods ─────────────────────────▶├──▶ ms (TempData)
                                       │
g.MultiSelectStorage ─────────────────▶├──▶ storage (State)
                                       │
                                       └──▶ g.CurrentMultiSelect設定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言、フラグ・構造体定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | BeginMultiSelect/EndMultiSelect実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | 内部データ構造定義 |
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | 使用例デモ |
