# 機能設計書 178-TableSetupScrollFreeze

## 概要

本ドキュメントは、ImGuiライブラリにおける`TableSetupScrollFreeze`関数の機能設計を記載する。この関数は、テーブルのスクロール時に固定される列と行の数を設定する。

### 本機能の処理概要

**業務上の目的・背景**：大きなテーブルをスクロールする際、ヘッダー行や左端の識別列を常に表示しておきたい場合がある。`TableSetupScrollFreeze`関数は、スクロール時に固定される（フリーズされる）列数と行数を指定することで、ユーザーがデータの文脈を失わないようにする。

**機能の利用シーン**：
- ヘッダー行を固定してデータをスクロールする場合
- 左端のID列を固定して他の列をスクロールする場合
- 両方（ヘッダー行と左端列）を固定する場合
- Excelのような「ウィンドウ枠の固定」機能を実現する場合

**主要な処理内容**：
1. テーブルスコープ内であることの検証
2. 固定列数の設定（ScrollXフラグ使用時のみ有効）
3. 固定行数の設定（ScrollYフラグ使用時のみ有効）
4. 実際のフリーズ状態の計算（スクロール位置に依存）
5. 固定領域と非固定領域間の列順序の維持

**関連システム・外部連携**：テーブルスクロールシステム

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | Tables | 主画面 | スクロール固定の設定 |

## 機能種別

設定機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| columns | int | Yes | 固定する列の数 | 0以上、IMGUI_TABLE_MAX_COLUMNS未満 |
| rows | int | Yes | 固定する行の数 | 0以上、128未満 |

### 入力データソース

- ImGuiコンテキストのカレントテーブル
- 現在のスクロール位置

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | なし |

### 出力先

- テーブルのフリーズ設定（FreezeColumnsRequest, FreezeRowsRequest等）

## 処理フロー

### 処理シーケンス

```
1. カレントテーブルの取得と検証
   └─ BeginTableスコープ内であることを確認
2. レイアウトロック前の確認
   └─ IsLayoutLocked == falseを確認
3. パラメータの検証
   ├─ columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS
   └─ rows >= 0 && rows < 128
4. 固定列の設定
   ├─ ScrollXフラグがある場合: FreezeColumnsRequest = min(columns, ColumnsCount)
   └─ ScrollXフラグがない場合: FreezeColumnsRequest = 0
5. 実際の固定列数の計算
   └─ スクロール位置が0でない場合のみ有効
6. 固定行の設定
   ├─ ScrollYフラグがある場合: FreezeRowsRequest = rows
   └─ ScrollYフラグがない場合: FreezeRowsRequest = 0
7. 実際の固定行数の計算
   └─ スクロール位置が0でない場合のみ有効
8. IsUnfrozenRowsの設定
   └─ FreezeRowsCount == 0の場合true
9. 固定領域の列順序の維持
   └─ フリーズ境界を越える列の並べ替えを調整
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{テーブル<br/>スコープ内?}
    B -->|No| C[アサート/リターン]
    B -->|Yes| D{レイアウト<br/>ロック済み?}
    D -->|Yes| C
    D -->|No| E[パラメータ検証]
    E --> F{ScrollX<br/>フラグ?}
    F -->|Yes| G[FreezeColumnsRequest設定]
    F -->|No| H[FreezeColumnsRequest = 0]
    G --> I{Scroll.x != 0?}
    H --> I
    I -->|Yes| J[FreezeColumnsCount = Request]
    I -->|No| K[FreezeColumnsCount = 0]
    J --> L{ScrollY<br/>フラグ?}
    K --> L
    L -->|Yes| M[FreezeRowsRequest設定]
    L -->|No| N[FreezeRowsRequest = 0]
    M --> O{Scroll.y != 0?}
    N --> O
    O -->|Yes| P[FreezeRowsCount = Request]
    O -->|No| Q[FreezeRowsCount = 0]
    P --> R[IsUnfrozenRows設定]
    Q --> R
    R --> S[列順序の調整]
    S --> T[終了]
    C --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-178-01 | 最初の行前に呼び出し | TableNextRow前に呼び出す必要がある | IsLayoutLocked == false |
| BR-178-02 | ScrollXが必要 | 列の固定にはScrollXフラグが必要 | columns > 0 |
| BR-178-03 | ScrollYが必要 | 行の固定にはScrollYフラグが必要 | rows > 0 |
| BR-178-04 | スクロール位置依存 | 実際の固定は、スクロール位置が0でない場合のみ適用 | Scroll != 0 |
| BR-178-05 | 列順序維持 | 固定列と非固定列の間で列を並べ替えることはできない | Reorderableフラグ使用時 |

### 計算ロジック

固定列/行の実際の適用:
```
FreezeColumnsCount = (Scroll.x != 0) ? FreezeColumnsRequest : 0
FreezeRowsCount = (Scroll.y != 0) ? FreezeRowsRequest : 0
```

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | アサーション失敗 | BeginTable外で呼び出し | デバッグビルドで停止 |
| N/A | アサーション失敗 | TableNextRow後に呼び出し | デバッグビルドで停止 |
| N/A | アサーション失敗 | columns < 0 または columns >= MAX | デバッグビルドで停止 |
| N/A | アサーション失敗 | rows < 0 または rows >= 128 | デバッグビルドで停止 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- O(k)の処理コスト（kは固定列数、列順序調整のため）

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

特になし

## 備考

- 固定行は通常ヘッダー行を含む
- 固定列の並べ替えは固定領域内でのみ可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiTable構造体のFreezeColumnsRequest, FreezeColumnsCount等 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 907行目: 公開APIの宣言 |
| 2-2 | imgui_tables.cpp | `imgui_tables.cpp` | 1663-1689行目: TableSetupScrollFreeze実装 |

**主要処理フロー**:
- **1665-1668行目**: 検証とアサート
- **1672-1673行目**: 固定列の設定
- **1674-1675行目**: 固定行の設定
- **1676行目**: IsUnfrozenRowsの設定
- **1680-1688行目**: 列順序の調整

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

```
TableSetupScrollFreeze(columns, rows)
    │
    ├─ FreezeColumnsRequest = min(columns, ColumnsCount) [ScrollX時]
    │
    ├─ FreezeColumnsCount = (Scroll.x != 0) ? Request : 0
    │
    ├─ FreezeRowsRequest = rows [ScrollY時]
    │
    ├─ FreezeRowsCount = (Scroll.y != 0) ? Request : 0
    │
    └─ [固定列境界を越える列の順序調整]
           └─ DisplayOrderToIndexの更新
```

### データフロー図

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

columns ────────────────▶ ┌──────────────────────┐
                         │ TableSetupScrollFreeze│
rows ───────────────────▶│   - 列/行リクエスト設定│ ────▶ [FreezeColumnsRequest]
                         │   - 実際の固定数計算  │
table->Flags ───────────▶│   - 列順序調整        │ ────▶ [FreezeRowsRequest]
                         │                       │
Scroll.x/y ─────────────▶│                       │ ────▶ [DisplayOrderToIndex]
                         └──────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiTable構造体定義 |
| imgui_tables.cpp | `imgui_tables.cpp` | ソース | 実装本体 |
