# 機能設計書 73-SameLine

## 概要

本ドキュメントは、Dear ImGuiライブラリのSameLine関数の機能設計を記述する。この関数は、ウィジェット間を水平にレイアウトするためのAPI関数である。

### 本機能の処理概要

SameLine関数は、次のウィジェットを前のウィジェットと同じ行に配置するためのレイアウト関数である。通常、ImGuiではウィジェットは垂直に積み重なるが、SameLineを呼び出すことで水平レイアウトを実現できる。オプションでX位置オフセットとスペーシングを指定可能。

**業務上の目的・背景**：GUIアプリケーションでは、複数のウィジェットを横並びに配置したいケースが頻繁に発生する。例えば「OK」と「Cancel」ボタンの横並び配置、ラベルと入力フィールドの組み合わせ、複数のアイコンボタンのツールバー配置などである。SameLineは、ImGuiの基本的な垂直レイアウトモデルを補完し、柔軟な水平配置を可能にする。コードの可読性を維持しながら、直感的な方法で複雑なレイアウトを構築できる。

**機能の利用シーン**：ボタンの横並び配置、フォームでのラベル+入力フィールドの配置、ツールバーの構築、ステータスバーの要素配置、グリッド状のボタンレイアウト、複合ウィジェットの構築など、幅広い場面で利用される。

**主要な処理内容**：
1. ウィンドウのSkipItemsフラグを確認する
2. X位置オフセットが指定されているかで処理を分岐する
3. カーソル位置を前の行の位置に戻す
4. スペーシングを適用してX位置を調整する
5. IsSameLineフラグをtrueに設定する

**関連システム・外部連携**：この関数は純粋にImGui内部のレイアウト管理に関わるため、外部システムとの連携はない。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Layout | 主機能 | 水平レイアウトのデモ |

## 機能種別

レイアウト制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| offset_from_start_x | float | No | ウィンドウ左端からのX位置オフセット（0.0fでデフォルト動作） | デフォルト: 0.0f |
| spacing | float | No | 前のアイテムとの間隔（負の値でデフォルトスペーシング） | デフォルト: -1.0f |

### 入力データソース

ユーザーコードから直接呼び出される。

## 出力仕様

### 出力データ

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

### 出力先

現在のウィンドウのDrawing Context（DC）内のCursorPos、CurrLineSize、CurrLineTextBaseOffset、IsSameLineを更新する。

## 処理フロー

### 処理シーケンス

```
1. ウィンドウのSkipItemsフラグを確認
   └─ trueの場合は即座にreturn
2. offset_from_start_xの値で処理を分岐
   2a. offset_from_start_x != 0 の場合
       └─ ウィンドウ左端からの絶対位置を計算
       └─ spacing < 0 の場合はspacing = 0に設定
   2b. offset_from_start_x == 0 の場合
       └─ 前のアイテムの右端に配置
       └─ spacing < 0 の場合はstyle.ItemSpacing.xを使用
3. CursorPosを更新
   └─ X: 計算した位置
   └─ Y: 前の行のY位置
4. CurrLineSize/CurrLineTextBaseOffsetを前の行の値に復元
5. IsSameLine = true を設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SkipItems?}
    B -->|Yes| C[return]
    B -->|No| D{offset_from_start_x != 0?}
    D -->|Yes| E[絶対位置を計算]
    D -->|No| F[相対位置を計算]
    E --> G{spacing < 0?}
    F --> H{spacing < 0?}
    G -->|Yes| I[spacing = 0]
    G -->|No| J[指定spacingを使用]
    H -->|Yes| K[spacing = ItemSpacing.x]
    H -->|No| L[指定spacingを使用]
    I --> M[CursorPos更新]
    J --> M
    K --> M
    L --> M
    M --> N[CurrLineSize/TextBaseOffset復元]
    N --> O[IsSameLine = true]
    O --> P[終了]
    C --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトスペーシング | spacing < 0 かつ offset_from_start_x == 0 の場合、style.ItemSpacing.xが適用される | 常時 |
| BR-02 | 絶対位置指定時 | offset_from_start_x != 0 かつ spacing < 0 の場合、spacing = 0となる | 常時 |
| BR-03 | Y位置復元 | Y位置は常に前の行のY位置に復元される | 常時 |

### 計算ロジック

**offset_from_start_x != 0の場合:**
```
CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing + DC.GroupOffset.x + DC.ColumnsOffset.x
CursorPos.y = DC.CursorPosPrevLine.y
```

**offset_from_start_x == 0の場合:**
```
CursorPos.x = DC.CursorPosPrevLine.x + spacing
CursorPos.y = DC.CursorPosPrevLine.y
```

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

該当なし（メモリ内操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 特にエラー条件なし | - |

### リトライ仕様

該当なし

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

該当なし（フレーム単位の即座反映）

## パフォーマンス要件

非常に軽量な操作（座標計算とメンバ変数への代入のみ）。毎フレーム複数回呼び出しても問題ない。

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

特になし（純粋なUI操作）

## 備考

- NewLine()はSameLine()を取り消すために使用可能
- BeginGroup()/EndGroup()と組み合わせてグループ単位での水平配置も可能
- style.ItemSpacing.xでデフォルトのスペーシング幅を調整可能

---

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

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

### 推奨読解順序

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

レイアウトに関わるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiWindowTempData構造体のCursorPos、CursorPosPrevLine、CurrLineSize、IsSameLineフィールドを確認（2587-2638行目） |
| 1-2 | imgui.h | `imgui.h` | ImGuiStyle構造体のItemSpacingフィールドを確認 |

**読解のコツ**: CursorPosPrevLineは前の行の終了位置を保持し、SameLineはこの位置を利用して水平配置を実現する。

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

SameLine関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | SameLine関数の実装（11354-11378行目） |

**主要処理フロー**:
1. **11358-11359行目**: SkipItemsチェック
2. **11361-11366行目**: offset_from_start_x != 0の場合の絶対位置計算
3. **11368-11374行目**: offset_from_start_x == 0の場合の相対位置計算
4. **11375-11376行目**: CurrLineSize/CurrLineTextBaseOffsetの復元
5. **11377行目**: IsSameLine = trueの設定

#### Step 3: 関連関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | NewLine関数（1592-1607行目）でSameLineの取り消し処理を確認 |

**主要処理フロー**:
- **1601行目**: IsSameLine = falseの設定

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

```
ImGui::SameLine(offset_from_start_x, spacing_w)
    │
    ├─ SkipItemsチェック
    │
    ├─ 分岐: offset_from_start_x != 0
    │      │
    │      ├─ 絶対位置計算
    │      │      └─ Pos.x - Scroll.x + offset + spacing + GroupOffset + ColumnsOffset
    │      │
    │      └─ spacing < 0 → spacing = 0
    │
    ├─ 分岐: offset_from_start_x == 0
    │      │
    │      ├─ 相対位置計算
    │      │      └─ CursorPosPrevLine.x + spacing
    │      │
    │      └─ spacing < 0 → spacing = ItemSpacing.x
    │
    ├─ CursorPos.y = CursorPosPrevLine.y
    │
    ├─ CurrLineSize/CurrLineTextBaseOffset復元
    │
    └─ IsSameLine = true
```

### データフロー図

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

offset_from_start_x ──┬──▶ SameLine() ──▶ DC.CursorPos
spacing_w ────────────┘         │              (X,Y更新)
                                │
                                ├────────────▶ DC.CurrLineSize
                                │              (前の行の値に復元)
                                │
                                ├────────────▶ DC.CurrLineTextBaseOffset
                                │              (前の行の値に復元)
                                │
                                └────────────▶ DC.IsSameLine = true
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | SameLine関数の宣言（578行目） |
| imgui.cpp | `imgui.cpp` | ソース | SameLine関数の実装（11354-11378行目） |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | NewLine関数の実装（1592-1607行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダー | ImGuiWindowTempData構造体の定義（2587-2638行目） |
