# 画面設計書 21-Documents

## 概要

本ドキュメントは、Dear ImGuiのサンプルアプリケーション「Documents」画面の設計書です。複数ドキュメントをタブベースで管理するUIパターンのリファレンス実装として提供されています。

### 本画面の処理概要

**業務上の目的・背景**：本画面は、複数のドキュメント（ファイル）をタブインターフェースで管理するアプリケーションの実装パターンを示すサンプルです。テキストエディタやIDEのような複数ファイルを同時に開いて編集するアプリケーションを開発する際の参考実装として機能します。ドキュメントの開閉、未保存状態の管理、名前変更、保存確認ダイアログなど、実際のアプリケーションで必要となる典型的な機能を網羅しています。

**画面へのアクセス方法**：Demo Windowのメニューバーから「Examples」→「Documents」を選択することでウィンドウが表示されます。ShowExampleAppDocuments関数の呼び出しにより、bool型のポインタで表示/非表示を制御できます。

**主要な操作・処理内容**：
1. タブバーによる複数ドキュメントの切り替え表示
2. ドキュメントの開閉操作（メニューまたはチェックボックス）
3. ドキュメント名の変更（Renameポップアップ）
4. ドキュメントの編集（Modifyボタンで変更フラグを設定）
5. ドキュメントの保存（Saveボタン）
6. 未保存ドキュメントの保存確認ダイアログ表示
7. コンテキストメニューによるドキュメント操作

**画面遷移**：Demo Windowの「Examples」メニューから呼び出されます。独立したウィンドウとして動作し、他の画面との直接的な遷移関係はありません。

**権限による表示制御**：本サンプルでは権限による表示制御は実装されていません。すべての機能が常に利用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Begin | 主機能 | ドキュメントウィンドウの開始処理 |
| 25 | End | 主機能 | ドキュメントウィンドウの終了処理 |
| 183 | BeginTabBar | 主機能 | タブバーの開始 |
| 184 | EndTabBar | 主機能 | タブバーの終了 |
| 185 | BeginTabItem | 主機能 | タブアイテムの開始 |
| 186 | EndTabItem | 主機能 | タブアイテムの終了 |
| 150 | BeginMenuBar | 補助機能 | メニューバーの開始 |
| 156 | MenuItem | 補助機能 | メニューアイテムの作成 |

## 画面種別

タブベース複数ドキュメント管理

## URL/ルーティング

N/A（Dear ImGuiはImmediate Mode GUIライブラリのため、URL/ルーティングの概念は適用されません）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| p_open | bool* | 入出力 | ウィンドウの表示/非表示状態 |
| opt_reorderable | bool | 入力 | タブの並び替え可否設定 |
| opt_fitting_flags | ImGuiTabBarFlags | 入力 | タブバーのフィッティングポリシー |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| メニューバー | MenuBar | File メニュー（Open、Close All、Exit） |
| ドキュメントチェックボックス | Checkbox | 各ドキュメントの開閉状態を示すチェックボックス |
| タブバー | TabBar | 開いているドキュメントのタブ一覧 |
| ドキュメント名 | Text | 現在選択中のドキュメント名 |
| ドキュメント内容 | TextWrapped | ドキュメントの内容（Lorem ipsum テキスト） |
| Renameボタン | Button | ドキュメント名変更ボタン（Ctrl+R） |
| Modifyボタン | Button | 編集フラグ設定ボタン（Ctrl+M） |
| Saveボタン | Button | 保存ボタン（Ctrl+S） |
| Closeボタン | Button | ドキュメント閉じるボタン（Ctrl+W） |
| カラーエディタ | ColorEdit3 | ドキュメントに関連付けられた色の編集 |

## イベント仕様

### 1-ドキュメントタブ選択

ユーザーがタブをクリックすると、該当ドキュメントの内容が表示領域に表示されます。ImGuiTabBarFlags_Reorderableが有効な場合、タブのドラッグによる並び替えが可能です。

### 2-ドキュメントを開く

Fileメニューの「Open」サブメニューから未開封のドキュメントを選択すると、doc.DoOpen()が呼び出され、ドキュメントがタブバーに追加されます。

### 3-ドキュメントを閉じる

- タブの×ボタンをクリック
- Closeボタンをクリック
- コンテキストメニューから「Close」を選択
上記いずれかの操作で、ドキュメントがCloseQueueに追加されます。未保存の場合は保存確認ダイアログが表示されます。

### 4-名前変更

Renameボタンまたはコンテキストメニューから「Rename」を選択すると、ポップアップダイアログが表示されます。InputTextで新しい名前を入力し、Enterキーで確定します。

### 5-編集（Modify）

Modifyボタンをクリックすると、doc.Dirty = trueが設定され、タブに未保存マーク（ドット）が表示されます。

### 6-保存

Saveボタンまたはコンテキストメニューから「Save」を選択すると、doc.DoSave()が呼び出され、Dirtyフラグがfalseに設定されます。

### 7-保存確認ダイアログ

未保存のドキュメントを閉じようとすると、モーダルダイアログ「Save?」が表示されます。
- Yes: すべての未保存ドキュメントを保存して閉じる
- No: 保存せずに閉じる
- Cancel: 閉じる操作をキャンセル

## データベース更新仕様

N/A（本サンプルはデータベースを使用しません。すべてのデータはメモリ内の構造体で管理されます）

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|--------------|------|----------|----------------|
| MSG-001 | 確認 | 未保存ドキュメントを閉じようとした時 | "Save change to the following items?" |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| ウィンドウが非表示の場合 | Begin()がfalseを返した場合、End()のみ呼び出して早期リターン |
| ドキュメント名が空の場合 | InputTextのバッファサイズにより32文字までに制限 |

## 備考

- ドキュメントはUIDで一意に識別され、名前変更後もタブの追跡が可能
- タブ名には「###doc{UID}」形式でIDが付加され、表示名と内部IDが分離されている
- ImGuiTabItemFlags_UnsavedDocumentフラグにより、未保存状態が視覚的に表示される
- SetTabItemClosed()を使用して、プログラム的なタブクローズ時のちらつきを防止

---

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

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

### 推奨読解順序

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

まず、ドキュメントを表現するデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_demo.cpp | `imgui_demo.cpp` | MyDocument構造体（行10221-10241）とExampleAppDocuments構造体（行10243-10334）の定義を理解する |

**読解のコツ**: MyDocumentは個々のドキュメントを表し、Name、UID、Open、Dirty、Colorの各メンバを持ちます。ExampleAppDocumentsはドキュメントコレクションとCloseQueue、リネーム状態を管理します。

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

処理の起点となる関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_demo.cpp | `imgui_demo.cpp` | ShowExampleAppDocuments関数（行10336-10531）がエントリーポイント |

**主要処理フロー**:
1. **行10338**: static変数としてExampleAppDocumentsインスタンスを保持
2. **行10344**: ImGui::Begin()でウィンドウを開始
3. **行10352-10375**: メニューバーの処理
4. **行10377-10388**: デバッグ用チェックボックス群の表示
5. **行10403-10444**: タブバーとタブアイテムの処理
6. **行10447-10468**: リネームポップアップの処理
7. **行10471-10527**: 保存確認ダイアログの処理

#### Step 3: タブバー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_demo.cpp | `imgui_demo.cpp` | BeginTabBar/BeginTabItemの使用パターン（行10403-10444） |

**主要処理フロー**:
- **行10404-10405**: タブバーフラグの設定（Reorderable、DrawSelectedOverline）
- **行10406**: BeginTabBar()でタブバーを開始
- **行10416-10440**: 各ドキュメントに対してBeginTabItem()を呼び出し
- **行10425**: UnsavedDocumentフラグによる未保存表示

#### Step 4: コンテキストメニューとポップアップを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_demo.cpp | `imgui_demo.cpp` | DisplayDocContextMenu（行10300-10315）とリネーム/保存確認ポップアップ（行10447-10527） |

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

```
ShowExampleAppDocuments()
    |
    +-- ImGui::Begin() ... ImGui::End()
    |       |
    |       +-- ImGui::BeginMenuBar() / EndMenuBar()
    |       |       |
    |       |       +-- ImGui::BeginMenu() / EndMenu()
    |       |               |
    |       |               +-- ImGui::MenuItem()
    |       |
    |       +-- ImGui::Checkbox() [各ドキュメント]
    |       |
    |       +-- ImGui::BeginTabBar() / EndTabBar()
    |               |
    |               +-- app.NotifyOfDocumentsClosedElsewhere()
    |               |
    |               +-- ImGui::BeginTabItem() / EndTabItem() [各ドキュメント]
    |                       |
    |                       +-- app.DisplayDocContextMenu()
    |                       |       |
    |                       |       +-- ImGui::BeginPopupContextItem()
    |                       |       +-- ImGui::MenuItem()
    |                       |
    |                       +-- app.DisplayDocContents()
    |                               |
    |                               +-- ImGui::Button() [Rename, Modify, Save, Close]
    |                               +-- ImGui::ColorEdit3()
    |
    +-- ImGui::OpenPopup("Rename") / BeginPopup("Rename")
    |       |
    |       +-- ImGui::InputText()
    |
    +-- ImGui::OpenPopup("Save?") / BeginPopupModal("Save?")
            |
            +-- ImGui::BeginChild() [未保存ドキュメント一覧]
            +-- ImGui::Button() [Yes, No, Cancel]
```

### データフロー図

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

p_open (bool*) ---------> Begin() -----------------------> ウィンドウ表示
                              |
ユーザー操作 -----------> メニュー/ボタン処理 ----------> app.Documents更新
(クリック/キー)               |                                |
                              |                                v
                              |                           doc.Open
                              |                           doc.Dirty
                              |                           doc.Name
                              |                           doc.Color
                              v
                         タブバー描画 -------------------> 画面表示
                              |
                              v
                         ポップアップ処理 ---------------> ダイアログ表示
                         (Rename/Save?)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | ShowExampleAppDocuments関数の実装（行10217-10531） |
| imgui.h | `imgui.h` | ヘッダー | ImGuiタブバー・ポップアップ関連API定義 |
| imgui.cpp | `imgui.cpp` | ソース | タブバー・ポップアップの実装 |
