# 機能設計書 152-BeginMainMenuBar

## 概要

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

### 本機能の処理概要

BeginMainMenuBarは、画面上部にフルスクリーン幅のメインメニューバーを作成・開始するための関数である。ビューポートの上端に固定されたメニューバーウィンドウを作成し、アプリケーション全体のメニュー構造を提供する。

**業務上の目的・背景**：デスクトップアプリケーションでは、画面上部に「ファイル」「編集」「表示」などのメインメニューを配置するのが一般的なUIパターンである。BeginMainMenuBarは、このようなアプリケーション全体のメニューバーを簡単に実装するための機能を提供する。ウィンドウ内のメニューバー（BeginMenuBar）とは異なり、ビューポート全体の上端に固定配置されるため、どのウィンドウがフォーカスされていても常にアクセス可能である。

**機能の利用シーン**：アプリケーションのメインエントリーポイントで呼び出し、グローバルなメニュー項目（ファイル操作、編集操作、ウィンドウ管理など）を提供する。Main Menu Bar画面で使用され、各種サブメニューやメニューアイテムを含む。

**主要な処理内容**：
1. メインビューポートを取得する
2. DisplaySafeAreaPaddingを考慮したオフセットを設定する
3. BeginViewportSideBarを使用して上端固定ウィンドウを作成する
4. BeginMenuBarを呼び出してメニューバーを開始する
5. 戻り値としてウィンドウが開かれたかどうかを返す

**関連システム・外部連携**：ImGuiのビューポートシステムと連携し、マルチビューポート環境でも正しく動作する。DisplaySafeAreaPaddingを尊重することでTV等のセーフエリアにも対応。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | Main Menu Bar | 主機能 | フルスクリーンメニューバーの開始 |

## 機能種別

ウィンドウ生成 / レイアウト処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (なし) | void | - | パラメータなし | - |

### 入力データソース

- ImGuiContext（グローバルコンテキスト）
- メインビューポート（GetMainViewport）
- ImGuiStyle（DisplaySafeAreaPadding、FramePadding）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | メニューバーが開始されたかどうか。falseの場合はEndMainMenuBarを呼び出さない |

### 出力先

- 画面上部に固定されたメニューバーウィンドウ

## 処理フロー

### 処理シーケンス

```
1. ビューポートとオフセットの準備
   └─ GetMainViewport()でメインビューポートを取得
   └─ DisplaySafeAreaPaddingを考慮したMenuBarOffsetMinValを設定

2. ウィンドウフラグの設定
   └─ NoScrollbar、NoSavedSettings、MenuBarフラグを設定
   └─ フレーム高さを計算

3. BeginViewportSideBarの呼び出し
   └─ "##MainMenuBar"という名前で上端固定ウィンドウを作成
   └─ ImGuiDir_Upで上端に配置

4. 失敗時の処理
   └─ is_openがfalseの場合、End()を呼び出してfalseを返す

5. メニューバーの開始
   └─ NoSavedSettingsフラグを一時的に解除
   └─ BeginMenuBar()を呼び出し
   └─ is_openを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: BeginMainMenuBar] --> B[GetMainViewport]
    B --> C[MenuBarOffsetMinVal設定<br/>SafeAreaPadding考慮]
    C --> D[ウィンドウフラグ設定<br/>NoScrollbar/NoSavedSettings/MenuBar]
    D --> E[GetFrameHeight]
    E --> F[BeginViewportSideBar<br/>##MainMenuBar, Dir_Up]
    F --> G[MenuBarOffsetMinValをリセット]
    G --> H{is_open?}
    H -->|No| I[End]
    I --> J[return false]
    H -->|Yes| K[NoSavedSettingsフラグ解除]
    K --> L[BeginMenuBar]
    L --> M[return is_open]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-152-01 | ペア呼び出し | 戻り値がtrueの場合のみEndMainMenuBarを呼び出す | 常時 |
| BR-152-02 | セーフエリア対応 | DisplaySafeAreaPaddingを考慮した位置にテキストを配置 | 常時 |
| BR-152-03 | 固定位置 | ビューポート上端に固定配置される | 常時 |
| BR-152-04 | 設定保存一時解除 | 内部のテーブルや子ウィンドウの設定保存を許可するため一時的にNoSavedSettingsを解除 | 常時 |

### 計算ロジック

- MenuBarOffsetMinVal.x: `g.Style.DisplaySafeAreaPadding.x`
- MenuBarOffsetMinVal.y: `ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)`
- メニューバー高さ: `GetFrameHeight()`

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

データベース操作なし（UI生成のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | falseリターン | BeginViewportSideBarが失敗 | End()を呼び出して終了 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 1フレームにつき1回のみ呼び出し推奨
- ウィンドウ作成とメニューバー開始の処理のみ

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

- 特になし

## 備考

- ウィンドウ名は"##MainMenuBar"（内部名、ユーザーには見えない）
- BeginViewportSideBarを内部で使用し、ビューポートのWorkRectを縮小する
- Issue #8356 への対応として、NoSavedSettingsフラグを一時的に解除

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 811行目: BeginMainMenuBar API宣言を確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiStyleのDisplaySafeAreaPadding、FramePaddingを確認 |
| 1-3 | imgui_internal.h | `imgui_internal.h` | ImGuiNextWindowDataのMenuBarOffsetMinValを確認 |

**読解のコツ**: BeginMainMenuBarは内部でBeginViewportSideBarとBeginMenuBarを組み合わせて実装されている。これらの関数の役割を理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 9125-9148行目: BeginMainMenuBar関数の実装 |

**主要処理フロー**:
1. **9127-9128行目**: コンテキストとビューポートの取得
2. **9130-9133行目**: セーフエリアを考慮したMenuBarOffsetMinValの設定
3. **9134-9136行目**: ウィンドウフラグの設定とBeginViewportSideBar呼び出し
4. **9137-9142行目**: 失敗時の処理
5. **9144-9147行目**: NoSavedSettings解除とBeginMenuBar呼び出し

#### Step 3: BeginViewportSideBarを理解する

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

**主要処理フロー**:
- **9098-9107行目**: ビューポートのワークエリアから位置とサイズを計算
- **9110-9113行目**: ワークエリアインセットを更新（次フレーム用）
- **9116-9120行目**: ウィンドウスタイルを設定してBeginを呼び出し

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

```
ImGui::BeginMainMenuBar()
    │
    ├─ GetMainViewport()
    │      └─ メインビューポートを取得
    │
    ├─ GetFrameHeight()
    │      └─ フレーム高さを計算
    │
    ├─ BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags)
    │      │
    │      ├─ GetBuildWorkRect()
    │      │      └─ ビューポートのワーク領域を取得
    │      │
    │      ├─ SetNextWindowPos()
    │      │      └─ ウィンドウ位置を設定
    │      │
    │      ├─ SetNextWindowSize()
    │      │      └─ ウィンドウサイズを設定
    │      │
    │      ├─ PushStyleVar() x 2
    │      │      └─ WindowRounding=0、WindowMinSize=(0,0)を設定
    │      │
    │      ├─ Begin()
    │      │      └─ ウィンドウを開始
    │      │
    │      └─ PopStyleVar()
    │             └─ スタイル変更を元に戻す
    │
    ├─ End() [失敗時のみ]
    │      └─ ウィンドウを閉じる
    │
    └─ BeginMenuBar()
           └─ メニューバー領域を開始
```

### データフロー図

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

g.Style ──────────────────> MenuBarOffsetMinVal計算 ─────────> g.NextWindowData
 - DisplaySafeAreaPadding
 - FramePadding

GetMainViewport() ────────> ビューポート取得
                                  │
                                  ▼
                           BeginViewportSideBar
                                  │
                                  ├──────────────────────────> "##MainMenuBar"ウィンドウ
                                  │
                                  ├──────────────────────────> viewport->BuildWorkInsetMin更新
                                  │
                                  ▼
                           BeginMenuBar
                                  │
                                  └──────────────────────────> メニューバー領域開始
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | BeginMainMenuBar APIの宣言 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiNextWindowData、ImGuiViewportPの定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | BeginMainMenuBar実装（9125-9148行目）、BeginViewportSideBar実装（9090-9123行目） |
| imgui.cpp | `imgui.cpp` | ソース | Begin、GetMainViewport等のコア関数 |
