# 機能設計書 92-Button

## 概要

本ドキュメントはImGuiのButton機能について、その処理内容、入出力仕様、実装詳細を記述した機能設計書である。

### 本機能の処理概要

Buttonは、クリック可能なボタンウィジェットを作成するための基本的なUI機能である。ユーザーがボタンをクリック（またはキーボード/ゲームパッドで選択）した際にtrueを返し、それ以外の場合はfalseを返す。ImGuiにおける最も基本的かつ頻繁に使用されるウィジェットの一つである。

**業務上の目的・背景**：GUIアプリケーションにおいてユーザーアクションをトリガーするための最も一般的なUIコンポーネントである。ファイルの保存、設定の適用、ダイアログの確認など、あらゆるユーザー操作の起点として機能する。ImGuiのイミディエイトモードパラダイムに従い、ボタンが押されたかどうかを毎フレーム確認し、押された場合にのみ対応する処理を実行するパターンで使用される。

**機能の利用シーン**：フォームの送信ボタン、ダイアログのOK/キャンセルボタン、ツールバーのアクションボタン、メニュー項目の代替、デバッグ操作のトリガーなど、ほぼすべてのGUIアプリケーションで使用される。

**主要な処理内容**：
1. ボタンのサイズを計算する（ラベルサイズ+フレームパディング）
2. バウンディングボックスを確定し、領域を確保する
3. ButtonBehaviorでクリック・ホバー・ホールド状態を判定する
4. 状態に応じた色でフレームを描画する
5. ラベルテキストを中央揃えで描画する
6. 押下状態（pressed）を戻り値として返す

**関連システム・外部連携**：ImGuiのDrawList描画システム、ナビゲーションシステム（キーボード/ゲームパッド操作）、スタイルシステム（ImGuiCol_Button、ImGuiCol_ButtonHovered、ImGuiCol_ButtonActive）と連携する。

**権限による制御**：BeginDisabled/EndDisabledで無効化可能。無効化時はクリックが無視され、見た目も無効化スタイルになる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Demo Window | 補助機能 | 各種ボタンウィジェットの表示 |
| 11 | Log | 補助機能 | クリアボタン等の操作ボタン |
| 14 | Long Text | 補助機能 | テキスト追加ボタン |
| 23 | Widgets | 主機能 | ボタンウィジェットのデモ |

## 機能種別

UIウィジェット / ユーザー入力処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | ボタンに表示するテキスト | NULL終端文字列 |
| size | const ImVec2& | No | ボタンのサイズ。(0,0)の場合は自動計算 | デフォルト: ImVec2(0, 0) |

### 入力データソース

- 呼び出し元からの直接指定
- ImGuiStyleからのスタイル設定値（FramePadding、FrameRounding、ButtonTextAlign等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pressed | bool | ボタンが押されたかどうか |

### 出力先

- 戻り値として呼び出し元に返却
- ImDrawList（現在のウィンドウの描画リスト）

## 処理フロー

### 処理シーケンス

```
1. ButtonExの呼び出し
   └─ Button関数はButtonEx(label, size_arg, ImGuiButtonFlags_None)を呼び出す

2. ウィンドウの取得とスキップチェック
   └─ GetCurrentWindow()で現在のウィンドウを取得
   └─ SkipItemsがtrueの場合はfalseを返す

3. サイズ計算
   └─ CalcTextSize()でラベルサイズを取得
   └─ CalcItemSize()で最終サイズを決定（ラベル+FramePadding*2）

4. アイテム登録
   └─ ItemSize()でレイアウト領域を確保
   └─ ItemAdd()で描画リストに追加

5. インタラクション判定
   └─ ButtonBehavior()でhovered/held/pressed状態を取得

6. 描画
   └─ 状態に応じた色を取得
   └─ RenderNavCursor()でナビゲーションカーソルを描画
   └─ RenderFrame()でボタン背景を描画
   └─ RenderTextClipped()でラベルを描画

7. ログ出力
   └─ LogEnabled時は"[label]"形式でログに出力

8. 結果返却
   └─ pressed状態を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: Button] --> B[ButtonEx呼び出し]
    B --> C{SkipItems?}
    C -->|Yes| D[return false]
    C -->|No| E[サイズ計算]
    E --> F[ItemSize/ItemAdd]
    F --> G{ItemAdd成功?}
    G -->|No| D
    G -->|Yes| H[ButtonBehavior]
    H --> I[色を決定]
    I --> J[RenderNavCursor]
    J --> K[RenderFrame]
    K --> L[RenderTextClipped]
    L --> M{LogEnabled?}
    M -->|Yes| N[ログ出力]
    M -->|No| O[return pressed]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-92-01 | 自動サイズ | size引数が(0,0)の場合、ラベルサイズ+FramePadding*2で自動計算 | size.x==0 または size.y==0 |
| BR-92-02 | 色の選択 | Active→Hovered→Normalの優先順位で色を選択 | 常時 |
| BR-92-03 | テキスト配置 | ButtonTextAlignスタイルに従って配置 | 常時 |

### 計算ロジック

- サイズ計算: `size = CalcItemSize(size_arg, label_size.x + FramePadding.x * 2.0f, label_size.y + FramePadding.y * 2.0f)`
- 色選択: `(held && hovered) ? ButtonActive : hovered ? ButtonHovered : Button`

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

データベース操作なし（UI描画のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 早期リターン | window->SkipItems == true | falseを返す |
| - | 早期リターン | ItemAdd失敗 | falseを返す |

### リトライ仕様

リトライ不要（フレームごとに再評価）

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

トランザクション管理なし（即時処理）

## パフォーマンス要件

- 単一フレーム内で多数のボタンを描画可能
- ButtonBehaviorによるホバー/クリック判定は軽量

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

- ラベル文字列は表示目的のみに使用
- IDはラベルから自動生成されるため、同一ラベルのボタンを複数配置する場合はPushID/PopIDで区別が必要

## 備考

- ボタンのIDはラベルから自動生成される
- 同一ウィンドウ内で同じラベルのボタンを使用する場合、意図しない動作を避けるためPushID/PopIDを使用すること
- ##で始まる部分はIDとして使用されるが表示されない（例: "Save##main"）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 632行目: Button関数のAPI宣言を確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiStyleのFramePadding、FrameRounding、ButtonTextAlign等を確認 |
| 1-3 | imgui.h | `imgui.h` | ImGuiCol_Button、ImGuiCol_ButtonHovered、ImGuiCol_ButtonActiveの定義 |

**読解のコツ**: ImGuiのウィジェットは、スタイル設定に強く依存する。FramePaddingはボタンの見た目に直接影響するため、この値の意味を理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 815-818行目: Button関数の実装（ButtonExへの委譲） |

**主要処理フロー**:
1. **815-818行目**: Button関数はButtonExを呼び出すラッパー

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 776-813行目: ButtonEx関数の実装 |

**主要処理フロー**:
- **782行目**: window->GetID(label)でIDを生成
- **783行目**: CalcTextSizeでラベルサイズを計算
- **786-787行目**: AlignTextBaseLineフラグ対応
- **788行目**: CalcItemSizeで最終サイズを決定
- **790-793行目**: ItemSize/ItemAddで領域確保
- **795-796行目**: ButtonBehaviorでインタラクション判定
- **799行目**: 状態に応じた色を取得
- **800行目**: RenderNavCursorでナビカーソル描画
- **801行目**: RenderFrameでボタン背景描画
- **805行目**: RenderTextClippedでラベル描画

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

```
ImGui::Button(label, size_arg)
    │
    └─ ButtonEx(label, size_arg, ImGuiButtonFlags_None)
           │
           ├─ GetCurrentWindow()
           │      └─ 現在のウィンドウコンテキストを取得
           │
           ├─ window->GetID(label)
           │      └─ ラベルからIDを生成
           │
           ├─ CalcTextSize(label)
           │      └─ ラベルのピクセルサイズを計算
           │
           ├─ CalcItemSize()
           │      └─ 最終的なボタンサイズを決定
           │
           ├─ ItemSize() / ItemAdd()
           │      └─ レイアウトシステムに登録
           │
           ├─ ButtonBehavior(bb, id, &hovered, &held, flags)
           │      └─ クリック/ホバー/ホールド状態を判定
           │
           ├─ GetColorU32()
           │      └─ 状態に応じた色を取得
           │
           ├─ RenderNavCursor()
           │      └─ ナビゲーションカーソルを描画
           │
           ├─ RenderFrame()
           │      └─ ボタン背景を描画
           │
           └─ RenderTextClipped()
                  └─ ラベルテキストを描画
```

### データフロー図

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

label (文字列) ─────────────> GetID ─────────────────────────> ImGuiID
                                │
                            CalcTextSize ───────────────────> label_size
                                │
size_arg ───────────────────> CalcItemSize ─────────────────> 最終サイズ
                                │
                            ItemSize/ItemAdd
                                │
マウス/キーボード状態 ─────> ButtonBehavior ─────────────────> hovered, held, pressed
                                │
ImGuiStyle ─────────────────> GetColorU32 ──────────────────> 描画色
                                │
                            RenderFrame ────────────────────> DrawList
                            RenderTextClipped ──────────────> DrawList
                                │
                            return pressed ─────────────────> bool (戻り値)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | Button APIの宣言、ImGuiStyle定義、色定数 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ButtonEx、ButtonBehavior等の内部API宣言 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | Button/ButtonExの実装 |
| imgui.cpp | `imgui.cpp` | ソース | ButtonBehavior、ItemSize、ItemAdd、RenderFrame等のコア関数 |
