# 機能設計書 185-BeginTabItem

## 概要

本ドキュメントは、ImGuiライブラリのBeginTabItem関数の機能設計を記述する。この関数はタブバー内に個々のタブアイテムを作成するためのAPIである。

### 本機能の処理概要

BeginTabItem関数は、タブバー内にタブアイテム（タブページ）を作成し、そのタブが選択されている場合にコンテンツ領域への追加を可能にする。タブの選択状態、閉じるボタン、ドラッグによる並び替えなどの機能を提供する。

**業務上の目的・背景**：タブインターフェースにおいて、個々のタブは独立したコンテンツ領域を持つ必要がある。BeginTabItemは、タブのラベル表示、選択状態の管理、オプショナルな閉じるボタンの提供など、タブUIに必要な機能を包括的に提供する。

**機能の利用シーン**：
- ドキュメントエディタでの複数ドキュメントタブ
- 設定画面のカテゴリ分けタブ
- プロパティパネルの分類タブ
- 閉じることができるタブ（p_open使用時）

**主要な処理内容**：
1. タブバーコンテキストの検証
2. タブIDの計算とタブアイテム構造体の取得/作成
3. タブサイズの計算
4. タブの選択状態の管理
5. タブの描画（背景、ラベル、閉じるボタン）
6. 選択されている場合はIDスタックへのプッシュ

**関連システム・外部連携**：
- BeginTabBar/EndTabBarとの連携（タブバーコンテキスト）
- EndTabItemとのペア使用（選択時のみ）
- スタイルシステム（色、パディング）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | Documents | 主機能 | タブアイテムの開始 |

## 機能種別

UI構造制御処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | タブのラベルテキスト | 空文字列可 |
| p_open | bool* | No | 閉じるボタンの状態（デフォルト: NULL） | NULLの場合は閉じるボタンなし |
| flags | ImGuiTabItemFlags | No | タブアイテムの動作フラグ（デフォルト: 0） | 有効なフラグ値 |

### ImGuiTabItemFlags列挙型（主要なもの）

| フラグ | 説明 |
|--------|------|
| ImGuiTabItemFlags_None | デフォルト |
| ImGuiTabItemFlags_UnsavedDocument | ラベルに「*」を追加、閉じる時に確認 |
| ImGuiTabItemFlags_SetSelected | タブを選択状態に設定 |
| ImGuiTabItemFlags_NoCloseWithMiddleMouseButton | 中ボタンクリックでの閉じるを無効化 |
| ImGuiTabItemFlags_NoPushId | IDスタックへのプッシュを無効化 |
| ImGuiTabItemFlags_NoTooltip | ラベルが省略された場合のツールチップを無効化 |
| ImGuiTabItemFlags_NoReorder | ドラッグによる並び替えを無効化 |
| ImGuiTabItemFlags_Leading | タブバーの左端に配置 |
| ImGuiTabItemFlags_Trailing | タブバーの右端に配置 |

### 入力データソース

- 現在のタブバーコンテキスト（g.CurrentTabBar）
- タブの選択状態、閉じる状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | タブが選択されているかどうか。trueの場合はEndTabItemを呼び出す |

### 出力先

- タブアイテム構造体（ImGuiTabItem）
- タブバーの選択状態

## 処理フロー

### 処理シーケンス

```
1. ウィンドウのスキップ状態チェック
   └─ SkipItemsの場合はfalseを返却
2. タブバーコンテキストの検証
   └─ g.CurrentTabBarがNULLの場合はアサーション
3. p_openの状態チェック
   └─ p_openがfalseの場合はタブを表示しない
4. TabItemEx内部関数の呼び出し
   └─ タブの描画と状態管理
5. タブが選択されている場合
   └─ IDスタックへのプッシュ（NoPushIdでない場合）
6. 戻り値の返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{window->SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D{CurrentTabBar != NULL?}
    D -->|No| E[アサーション失敗]
    D -->|Yes| F{p_open && !*p_open?}
    F -->|Yes| G[ItemAdd呼び出し]
    G --> C
    F -->|No| H[TabItemEx呼び出し]
    H --> I{選択されている?}
    I -->|Yes| J{NoPushIdでない?}
    I -->|No| K[return false/tab_contents_visible]
    J -->|Yes| L[PushOverrideID]
    J -->|No| M[return true]
    L --> M
    K --> N[終了]
    C --> N
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-185-01 | ペアリング | 戻り値がtrueの場合のみEndTabItemを呼び出す | 常時 |
| BR-185-02 | タブバー必須 | BeginTabBar/EndTabBarの間で呼び出す必要がある | 常時 |
| BR-185-03 | 閉じるボタン | p_openがNULLでない場合のみ閉じるボタンを表示 | p_open指定時 |
| BR-185-04 | Buttonフラグ禁止 | ImGuiTabItemFlags_Buttonは使用不可（TabItemButtonを使用） | 常時 |

### 計算ロジック

タブサイズの計算:
```
size.x = label_size.x + FramePadding.x * 2 + (閉じるボタン分)
size.y = label_size.y + FramePadding.y * 2
size.x = min(size.x, TabBarCalcMaxTabWidth())
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | アサーション | タブバーコンテキストなし | IM_ASSERT_USER_ERROR_RETV |
| N/A | アサーション | ImGuiTabItemFlags_Buttonが設定されている | IM_ASSERT |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 多数のタブがあっても効率的に動作すること
- 非表示タブは描画処理をスキップすること

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

該当なし

## 備考

- タブが選択されていなくてもtrueを返す場合がある（Ctrl+Tabプレビュー時など）
- p_openがfalseに設定されるとタブは表示されない
- UnsavedDocumentフラグはラベルに「*」を追加し、閉じる際の挙動を変更する
- Leading/Trailingフラグでタブの配置位置を制御できる

---

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

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

### 推奨読解順序

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

まず、タブアイテムを表現するデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiTabItemFlags列挙型の定義 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiTabItem構造体（2793-2810行目） |

**読解のコツ**: ImGuiTabItemは個々のタブの状態（選択、幅、オフセット等）を保持する。

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

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

**主要処理フロー**:
1. **10351-10354行目**: SkipItemsチェック
2. **10356-10358行目**: タブバーコンテキストの検証
3. **10360行目**: TabItemEx呼び出し
4. **10361-10365行目**: IDスタックへのプッシュ（選択時）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | TabItemEx関数（10409-10654行目） |

**主要処理フロー**:
- **10413-10418行目**: レイアウト処理
- **10424行目**: タブIDの計算
- **10429-10433行目**: p_openがfalseの場合の処理
- **10445-10453行目**: タブアイテムの取得/作成
- **10549-10560行目**: クリック処理
- **10589-10614行目**: タブの描画

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

```
ImGui::BeginTabItem(label, p_open, flags)
    │
    ├─ (検証: SkipItems, CurrentTabBar, Buttonフラグ)
    │
    ├─ TabItemEx(tab_bar, label, p_open, flags, NULL)
    │      │
    │      ├─ TabBarLayout() [条件付き]
    │      ├─ タブIDの計算
    │      ├─ タブアイテムの取得/作成
    │      ├─ サイズ計算
    │      ├─ 選択状態の管理
    │      ├─ タブの描画
    │      └─ return tab_contents_visible
    │
    └─ PushOverrideID(tab->ID) [選択時かつNoPushIdでない場合]
```

### データフロー図

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

label ──────────▶ BeginTabItem() ─────▶ bool (選択状態)
p_open                   │                tab->ID (IDスタック)
flags                    │
                         ├─ コンテキスト検証
                         ├─ TabItemEx呼び出し
                         └─ ID管理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | API宣言、ImGuiTabItemFlags定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | BeginTabItem/TabItemEx実装 |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダー | ImGuiTabItem構造体定義 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（Tabsセクション） |
