# 機能設計書 184-EndTabBar

## 概要

本ドキュメントは、ImGuiライブラリのEndTabBar関数の機能設計を記述する。この関数はBeginTabBarで開始されたタブバーを終了するためのAPIである。

### 本機能の処理概要

EndTabBar関数は、BeginTabBarで開始されたタブバーのコンテキストを終了し、必要な後処理を行う。この関数はBeginTabBarがtrueを返した場合にのみ呼び出す必要がある。

**業務上の目的・背景**：ImGuiのBegin/Endパターンに従い、タブバーのスコープを明確に管理する。EndTabBarは、タブバーのレイアウト計算、コンテンツ高さの調整、スタックからのポップなどの終了処理を担当する。

**機能の利用シーン**：
- BeginTabBarがtrueを返した後のタブバー終了処理
- 複数のタブを追加した後のタブバー完了

**主要な処理内容**：
1. タブバーコンテキストの検証
2. レイアウト未完了時のTabBarLayout呼び出し
3. タブコンテンツ高さの計算と更新
4. カーソル位置の復元
5. IDスタックからのポップ
6. タブバースタックからのポップ

**関連システム・外部連携**：
- BeginTabBarとのペア使用（必須）
- BeginTabItem/EndTabItemとの連携
- レイアウトシステム（カーソル位置管理）

**権限による制御**：本機能に権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | Documents | 主機能 | タブバーの終了 |

## 機能種別

UI構造制御処理

## 入力仕様

### 入力パラメータ

なし（引数を取らない関数）

### 入力データソース

- 現在のタブバーコンテキスト（g.CurrentTabBar）
- 現在のウィンドウコンテキスト

## 出力仕様

### 出力データ

なし（void関数）

### 出力先

- グローバルタブバースタックからのポップ
- 現在のタブバーポインタの更新

## 処理フロー

### 処理シーケンス

```
1. ウィンドウのスキップ状態チェック
   └─ SkipItemsの場合は即座にreturn
2. タブバーコンテキストの検証
   └─ g.CurrentTabBarがNULLの場合はアサーション
3. レイアウト処理
   └─ WantLayoutがtrueの場合はTabBarLayoutを呼び出し
4. コンテンツ高さの更新
   ├─ 可視タブが存在する場合: 現在のカーソル位置から計算
   └─ 可視タブがない場合: 前回の高さを使用（フリッカー防止）
5. 複数回呼び出しの場合のカーソル復元
6. IDスタックからのポップ（非DockNodeの場合）
7. タブバースタックからのポップ
8. g.CurrentTabBarの更新
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{window->SkipItems?}
    B -->|Yes| C[return]
    B -->|No| D{CurrentTabBar != NULL?}
    D -->|No| E[アサーション失敗]
    D -->|Yes| F{WantLayout?}
    F -->|Yes| G[TabBarLayout]
    F -->|No| H{可視タブあり?}
    G --> H
    H -->|Yes| I[CurrTabsContentsHeightを計算]
    H -->|No| J[PrevTabsContentsHeightを使用]
    I --> K{BeginCount > 1?}
    J --> K
    K -->|Yes| L[BackupCursorPosを復元]
    K -->|No| M[IDをポップ]
    L --> M
    M --> N[タブバースタックからポップ]
    N --> O[CurrentTabBarを更新]
    O --> P[終了]
    C --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-184-01 | ペアリング | BeginTabBarがtrueを返した場合のみ呼び出す | 常時 |
| BR-184-02 | コンテキスト検証 | g.CurrentTabBarがNULLの場合はエラー | 常時 |
| BR-184-03 | フリッカー防止 | 可視タブがない場合は前回の高さを維持 | 可視タブなし時 |
| BR-184-04 | 複数回呼び出し | 同一フレームで複数回BeginTabBarした場合の処理 | BeginCount > 1 |

### 計算ロジック

コンテンツ高さの計算:
```
CurrTabsContentsHeight = max(
    CursorPos.y - BarRect.Max.y,
    CurrTabsContentsHeight
)
```

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

該当なし（ImGuiはUIライブラリであり、データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | アサーション | g.CurrentTabBarがNULL | IM_ASSERT_USER_ERROR_RET |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- タブバー終了処理は軽量であること
- 毎フレーム呼び出しても効率的に動作すること

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

該当なし

## 備考

- BeginTabBarがfalseを返した場合、EndTabBarを呼び出してはならない
- タブコンテンツがない場合、視覚的なフリッカーを防止するために前回の高さが使用される
- SetTabItemClosedを使用しない場合、タブが消えた時に一時的なフリッカーが発生する可能性がある

---

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

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

### 推奨読解順序

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

まず、タブバーの終了処理に関連するデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiTabBar構造体のCurrTabsContentsHeight、PrevTabsContentsHeight |
| 1-2 | imgui_internal.h | `imgui_internal.h` | WantLayout、VisibleTabWasSubmittedフィールド |

**読解のコツ**: タブコンテンツの高さ管理がフリッカー防止の鍵となる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | EndTabBar関数（9703-9737行目） |

**主要処理フロー**:
1. **9706-9708行目**: SkipItemsチェック
2. **9710-9711行目**: CurrentTabBarのアサーション
3. **9714-9715行目**: WantLayout時のTabBarLayout呼び出し
4. **9718-9722行目**: 可視タブありの場合のコンテンツ高さ計算
5. **9724-9727行目**: 可視タブなしの場合の高さ維持
6. **9728-9729行目**: 複数回呼び出し時のカーソル復元
7. **9731-9733行目**: IDスタックからのポップ

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

```
ImGui::EndTabBar()
    │
    ├─ (検証: SkipItems, CurrentTabBar)
    │
    ├─ TabBarLayout() [条件付き: WantLayout]
    │
    ├─ コンテンツ高さの更新
    │      ├─ 可視タブあり: 現在位置から計算
    │      └─ 可視タブなし: 前回値を維持
    │
    ├─ カーソル位置の復元 [条件付き: BeginCount > 1]
    │
    ├─ PopID() [条件付き: 非DockNode]
    │
    └─ タブバースタックからポップ
           └─ g.CurrentTabBarの更新
```

### データフロー図

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

g.CurrentTabBar ───▶ EndTabBar() ──────▶ g.CurrentTabBarStack (ポップ)
                           │               g.CurrentTabBar (更新)
                           │
                           ├─ レイアウト処理
                           ├─ 高さ計算
                           └─ スタック操作
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | API宣言 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | EndTabBar実装 |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダー | ImGuiTabBar構造体定義 |
