# 機能設計書 172-BeginTable

## 概要

本ドキュメントは、ImGuiライブラリにおける`BeginTable`関数の機能設計を記載する。この関数は、高機能なテーブルレイアウトを開始するためのメイン関数であり、旧Columns APIの完全な代替として設計されている。

### 本機能の処理概要

**業務上の目的・背景**：データの一覧表示、設定画面のレイアウト、スプレッドシート風UIなど、多くのGUIアプリケーションにおいてテーブル形式の表示は不可欠である。`BeginTable`関数は、列のリサイズ、ソート、非表示、並べ替え、スクロール、固定行/列など、高度な機能を持つテーブルを簡単に作成できるようにする。旧Columns APIの制限を解消し、より柔軟で機能的なテーブル表示を可能にする。

**機能の利用シーン**：
- データベースのレコード一覧表示
- 設定画面でのラベルと入力項目の整列
- ファイルブラウザのファイル一覧（名前、サイズ、日付等）
- スプレッドシート風のデータ編集インターフェース
- プロパティエディタでのプロパティ表示

**主要な処理内容**：
1. テーブルIDの生成と既存テーブルインスタンスの取得または新規作成
2. フラグの正規化と設定の適用（サイズポリシー、ボーダー設定等）
3. スクロール用の子ウィンドウの作成（ScrollX/ScrollYフラグ使用時）
4. 列情報のメモリ確保と初期化
5. 設定の読み込み（INIファイルからの復元）
6. テーブルをImGuiコンテキストのカレントテーブルとして登録

**関連システム・外部連携**：
- ImGuiの設定保存システム（INIファイル）との連携でテーブル状態を永続化
- 子ウィンドウシステム（スクロール対応時）
- 描画リストシステム（DrawSplitter）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Tables | 主画面 | テーブルの開始処理 |

## 機能種別

UI制御機能（スコープ開始）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str_id | const char* | Yes | テーブルを識別する文字列ID | 空でない文字列 |
| columns | int | Yes | 列の数 | 1以上、IMGUI_TABLE_MAX_COLUMNS未満 |
| flags | ImGuiTableFlags | No（デフォルト:0） | テーブルの動作を制御するフラグ | ビットフラグの組み合わせ |
| outer_size | const ImVec2& | No（デフォルト:(0,0)） | テーブルの外部サイズ | 有効な座標値 |
| inner_width | float | No（デフォルト:0.0f） | 内部幅（ScrollX使用時） | 0以上 |

### ImGuiTableFlagsの主要フラグ

| フラグ | 説明 |
|--------|------|
| ImGuiTableFlags_Resizable | 列のリサイズを有効化 |
| ImGuiTableFlags_Reorderable | 列の並べ替えを有効化 |
| ImGuiTableFlags_Hideable | 列の非表示を有効化 |
| ImGuiTableFlags_Sortable | ソートを有効化 |
| ImGuiTableFlags_ScrollX | 水平スクロールを有効化 |
| ImGuiTableFlags_ScrollY | 垂直スクロールを有効化 |
| ImGuiTableFlags_BordersInnerH | 内部水平ボーダーを表示 |
| ImGuiTableFlags_BordersOuterH | 外部水平ボーダーを表示 |
| ImGuiTableFlags_BordersInnerV | 内部垂直ボーダーを表示 |
| ImGuiTableFlags_BordersOuterV | 外部垂直ボーダーを表示 |
| ImGuiTableFlags_SizingFixedFit | 固定サイズポリシー |
| ImGuiTableFlags_SizingStretchSame | 均等ストレッチポリシー |

### 入力データソース

- ユーザー指定のパラメータ
- INI設定ファイル（テーブル設定の復元時）
- ImGuiコンテキストのテーブルプール

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | テーブルが表示可能な場合true、クリップされて不可視の場合false |

### 出力先

- ImGuiコンテキストにカレントテーブルを設定
- 子ウィンドウの作成（スクロール使用時）
- 描画リストへの登録

## 処理フロー

### 処理シーケンス

```
1. 文字列IDからImGuiIDを計算
   └─ GetID(str_id)を呼び出し
2. 早期リターン判定
   ├─ 親ウィンドウがSkipItemsの場合はfalseを返却
   └─ クリップ判定（outer_sizeが指定され、完全に不可視の場合）
3. テーブルインスタンスの取得/作成
   └─ g.Tables.GetOrAddByKey(id)でプールから取得
4. フラグの正規化
   └─ TableFixFlags()でデフォルト値と矛盾の解消
5. スクロール用子ウィンドウの作成（必要な場合）
   └─ BeginChildEx()を呼び出し
6. テーブル状態の初期化
   ├─ 列メモリの確保（TableBeginInitMemory）
   ├─ 設定のリセット/読み込み
   └─ リクエストの適用（TableBeginApplyRequests）
7. テーブルをカレントとして登録
   └─ g.CurrentTable = table
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[GetID でIDを計算]
    B --> C{親ウィンドウが<br/>SkipItems?}
    C -->|Yes| D[false を返却]
    C -->|No| E{テーブルが<br/>クリップ外?}
    E -->|Yes| F[ItemSize/ItemAdd後<br/>falseを返却]
    E -->|No| G[テーブルインスタンス取得]
    G --> H[フラグの正規化]
    H --> I{ScrollX or<br/>ScrollY?}
    I -->|Yes| J[子ウィンドウ作成]
    I -->|No| K[外部ウィンドウを使用]
    J --> L[テーブル初期化]
    K --> L
    L --> M{初回初期化?}
    M -->|Yes| N[メモリ確保<br/>設定読み込み]
    M -->|No| O[既存設定を使用]
    N --> P[リクエスト適用]
    O --> P
    P --> Q[カレントテーブル登録]
    Q --> R[true を返却]
    D --> Z[終了]
    F --> Z
    R --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-172-01 | 必須EndTable | BeginTableがtrueを返した場合、必ずEndTableを呼び出す | BeginTableがtrueの場合 |
| BR-172-02 | 列数制限 | 列数は1以上IMGUI_TABLE_MAX_COLUMNS未満 | 常に |
| BR-172-03 | Resizableと内部ボーダー | Resizableフラグは自動的にBordersInnerVを有効化 | Resizable指定時 |
| BR-172-04 | スクロールとNoHostExtend | ScrollX/ScrollY使用時はNoHostExtendX/Yが無効化される | スクロールフラグ指定時 |

### 計算ロジック

outer_sizeの解釈:
- `outer_size.x <= 0.0f`: 右端から右揃え
- `outer_size.x > 0.0f`: 固定幅
- `outer_size.y < 0.0f`: 下端から配置
- `outer_size.y = 0.0f`: 最小高さなし（自動拡張）
- `outer_size.y > 0.0f`: 最小高さ指定

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

該当なし（メモリ上のデータ構造のみを操作）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | アサーション失敗 | columns <= 0 または columns >= IMGUI_TABLE_MAX_COLUMNS | デバッグビルドで停止 |
| N/A | アサーション失敗 | ScrollXフラグ使用時にinner_width < 0 | デバッグビルドで停止 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- テーブルインスタンスはプールで管理され、毎フレームのアロケーションを回避
- O(n)の初期化コスト（nは列数）
- クリップされたテーブルは早期リターンで処理をスキップ

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

特になし

## 備考

- テーブルの設定は自動的にINIファイルに保存される（NoSavedSettingsフラグで無効化可能）
- 同一IDで複数インスタンスを持つテーブルをサポート
- imgui_tables.cppファイル冒頭のコメントに詳細な仕様説明がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiTable構造体の定義 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiTableColumn構造体の定義 |
| 1-3 | imgui_internal.h | `imgui_internal.h` | ImGuiTableTempData構造体の定義 |

**読解のコツ**: ImGuiTableは永続的なテーブル状態を保持し、ImGuiTableTempDataはフレームごとの一時データを保持する。ImGuiTableColumnは各列の状態を管理する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 901行目: 公開APIの宣言を確認 |
| 2-2 | imgui_tables.cpp | `imgui_tables.cpp` | 312-316行目: BeginTable実装（内部版への委譲） |

**主要処理フロー**:
1. **312-316行目**: 文字列IDからIDを計算し、BeginTableExを呼び出し

#### Step 3: 内部実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_tables.cpp | `imgui_tables.cpp` | 318-645行目: BeginTableEx実装 |

**主要処理フロー**:
- **322-323行目**: 親ウィンドウのSkipItems確認
- **326-328行目**: 列数とinner_widthのバリデーション
- **337-348行目**: クリップ判定と早期リターン
- **355-364行目**: テーブルインスタンスの取得と一時データの準備
- **367-368行目**: フラグの正規化
- **402-456行目**: スクロール用子ウィンドウの作成
- **573-576行目**: メモリの初期化（初回時）
- **643行目**: リクエストの適用

#### Step 4: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_tables.cpp | `imgui_tables.cpp` | 272-303行目: TableFixFlags関数 |
| 4-2 | imgui_tables.cpp | `imgui_tables.cpp` | 657-676行目: TableBeginInitMemory関数 |
| 4-3 | imgui_tables.cpp | `imgui_tables.cpp` | 679-730行目: TableBeginApplyRequests関数 |

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

```
BeginTable(str_id, columns, flags, outer_size, inner_width)
    │
    ├─ GetID(str_id)
    │
    └─ BeginTableEx(name, id, columns, flags, outer_size, inner_width)
           │
           ├─ TableFixFlags(flags, outer_window)
           │      └─ フラグの正規化と矛盾解消
           │
           ├─ g.Tables.GetOrAddByKey(id)
           │      └─ テーブルプールからインスタンス取得
           │
           ├─ BeginChildEx() [ScrollX/ScrollY使用時]
           │      └─ スクロール用子ウィンドウ作成
           │
           ├─ TableBeginInitMemory(table, columns_count)
           │      └─ 列データ用メモリ確保
           │
           ├─ TableResetSettings(table) [リセット要求時]
           │
           ├─ TableLoadSettings(table) [設定読み込み時]
           │
           └─ TableBeginApplyRequests(table)
                  ├─ TableSetColumnWidth() [リサイズ要求時]
                  └─ TableSetColumnDisplayOrder() [並べ替え要求時]
```

### データフロー図

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

str_id ─────────▶ GetID() ──────────┐
                                     │
columns ────────────────────────────┤
                                     │
flags ──────────▶ TableFixFlags() ──┤
                                     ▼
outer_size ─────────────┐   ┌───────────────────┐
                        ├──▶│ BeginTableEx()     │
inner_width ────────────┘   │   - インスタンス取得│
                            │   - 子ウィンドウ作成│
                            │   - メモリ初期化   │
                            │   - 設定読み込み   │
                            └────────┬──────────┘
                                     │
                                     ▼
                              [bool 戻り値]
                              [g.CurrentTable設定]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言、ImGuiTableFlags定義 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | 内部API宣言、ImGuiTable/ImGuiTableColumn定義 |
| imgui_tables.cpp | `imgui_tables.cpp` | ソース | 実装本体（1-184行目にコメントで詳細仕様） |
