# 帳票設計書 4-INI設定ファイル保存（ディスク）

## 概要

本ドキュメントは、Dear ImGuiライブラリのINI設定ファイル保存（ディスク）機能に関する帳票設計書である。ウィンドウ位置やサイズなどの設定をINI形式でディスクに保存する機能について記述する。

### 本帳票の処理概要

INI設定ファイル保存機能は、ImGuiアプリケーションの状態（ウィンドウの位置、サイズ、折りたたみ状態など）をINI形式のテキストファイルとしてディスクに永続化する機能である。

**業務上の目的・背景**：GUI アプリケーションにおいて、ユーザーがカスタマイズしたウィンドウレイアウトや設定を次回起動時にも維持することは、優れたユーザーエクスペリエンスの提供に不可欠である。INI設定ファイル保存機能により、アプリケーション終了時の状態が自動的に保存され、次回起動時に復元される。これにより、ユーザーは毎回同じウィンドウ配置を手動で設定する必要がなくなる。

**帳票の利用シーン**：アプリケーション終了時に自動的に呼び出される（DestroyContext時）。また、設定変更後に一定時間（io.IniSavingRate秒）経過すると自動保存される。開発者が明示的にSaveIniSettingsToDisk関数を呼び出して即時保存することも可能。Metricsウィンドウからも「Save to disk」ボタンで手動保存できる。

**主要な出力内容**：
1. ウィンドウの位置情報（Pos）
2. ウィンドウのサイズ情報（Size）
3. ウィンドウの折りたたみ状態（Collapsed）
4. カスタム設定ハンドラーによる追加データ

**帳票の出力タイミング**：io.IniFilenameが設定されている場合、設定変更後io.IniSavingRate秒（デフォルト5秒）経過後に自動保存。また、DestroyContext呼び出し時にも保存される。

**帳票の利用者**：エンドユーザー（自動）、アプリケーション開発者

## 帳票種別

設定ファイル出力（INI形式テキストファイル）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 任意のImGuiウィンドウ | - | 自動保存（設定変更後） |
| - | Metrics/Debuggerウィンドウ | - | Settings > Save to diskボタン |
| - | アプリケーション終了 | - | DestroyContext時に自動保存 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | INI形式テキストファイル |
| 用紙サイズ | N/A（ファイル出力） |
| 向き | N/A |
| ファイル名 | デフォルト: imgui.ini（io.IniFilenameで変更可能） |
| 出力方法 | ファイルへの上書き保存 |
| 文字コード | UTF-8 |

### INI固有設定

| 項目 | 内容 |
|-----|------|
| オープンモード | "wt"（テキスト書き込みモード） |
| 自動保存間隔 | io.IniSavingRate（デフォルト5.0秒） |
| セクション形式 | [TypeName][Name] |

## 帳票レイアウト

### レイアウト概要

INI形式のセクション構造で、各ウィンドウごとにセクションが作成される。

```
[Window][ウィンドウ名]
Pos=x,y
Size=width,height
Collapsed=0

[Window][別のウィンドウ]
Pos=x,y
Size=width,height
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | セクションヘッダー | ウィンドウの識別情報 | [Window][名前] | INIセクション形式 |
| 2 | Pos | ウィンドウ位置 | ImGuiWindowSettings | Pos=x,y |
| 3 | Size | ウィンドウサイズ | ImGuiWindowSettings | Size=w,h |
| 4 | Collapsed | 折りたたみ状態 | ImGuiWindowSettings | Collapsed=0/1 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| IniFilename設定 | io.IniFilenameがNULLでないこと | Yes |
| SettingsLoaded | 設定が読み込み済みであること | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | SettingsHandler登録順 | 登録順 |

### 改ページ条件

N/A（INIファイルのため改ページ概念なし）

## データベース参照仕様

### 参照テーブル一覧

N/A（データベースは使用しない）

### 内部データ構造参照

| データ構造 | 用途 | アクセス方法 |
|-----------|------|-------------|
| ImGuiContext.SettingsWindows | ウィンドウ設定のリスト | g.SettingsWindows |
| ImGuiContext.SettingsHandlers | 設定ハンドラーのリスト | g.SettingsHandlers |
| ImGuiContext.SettingsIniData | 出力用テキストバッファ | g.SettingsIniData |
| ImGuiContext.SettingsDirtyTimer | 保存タイマー | g.SettingsDirtyTimer |
| ImGuiIO.IniFilename | INIファイルパス | g.IO.IniFilename |
| ImGuiIO.IniSavingRate | 自動保存間隔 | g.IO.IniSavingRate |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 保存タイミング | SettingsDirtyTimer <= 0.0f | なし | フレーム毎にDeltaTimeを減算 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[SaveIniSettingsToDisk呼び出し] --> B[SettingsDirtyTimer = 0]
    B --> C{ini_filename有効?}
    C -->|No| Z[終了]
    C -->|Yes| D[SaveIniSettingsToMemory呼び出し]
    D --> E[SettingsHandlers.WriteAllFn実行]
    E --> F[SettingsIniDataにデータ蓄積]
    F --> G[ImFileOpen実行]
    G --> H{オープン成功?}
    H -->|No| Z
    H -->|Yes| I[ImFileWrite実行]
    I --> J[ImFileClose実行]
    J --> Z
```

### 自動保存フロー

```mermaid
flowchart TD
    A[設定変更検知] --> B[MarkIniSettingsDirty呼び出し]
    B --> C[SettingsDirtyTimer = IniSavingRate]
    C --> D[毎フレーム UpdateSettings]
    D --> E{SettingsDirtyTimer > 0?}
    E -->|Yes| F[SettingsDirtyTimer -= DeltaTime]
    F --> G{SettingsDirtyTimer <= 0?}
    G -->|No| D
    G -->|Yes| H{IniFilename設定あり?}
    H -->|Yes| I[SaveIniSettingsToDisk]
    H -->|No| J[WantSaveIniSettings = true]
    I --> D
    J --> D
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ファイル名未指定 | ini_filenameがNULL | なし（早期リターン） | 有効なファイル名を設定 |
| ファイルオープン失敗 | ImFileOpenがNULLを返す | なし（早期リターン） | ファイルパス・権限を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数十〜数百ウィンドウ |
| 目標出力時間 | I/O依存（通常1秒未満） |
| 自動保存頻度 | io.IniSavingRate（デフォルト5秒）間隔 |

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

- INIファイルにはウィンドウ位置・サイズ情報が含まれるため、機密性は低い
- ファイルパスはio.IniFilenameで指定可能なため、書き込み先の検証が必要
- カスタムSettingsHandlerを使用する場合は、保存データの内容に注意

## 備考

- io.IniFilenameをNULLに設定すると自動保存が無効化される
- デフォルトファイル名「imgui.ini」はカレントディレクトリ相対パスのため、アプリケーションで絶対パスを設定することを推奨
- SaveIniSettingsToMemory関数と連携してメモリ上のデータからディスクに保存される
- カスタムSettingsHandlerを登録することで、独自データの保存も可能

---

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

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

### 推奨読解順序

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

まず、設定保存で使用されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 1124-1131行目: Settings/.Ini Utilities セクションを確認 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiSettingsHandler構造体を確認 |
| 1-3 | imgui_internal.h | `imgui_internal.h` | ImGuiWindowSettings構造体を確認 |

**読解のコツ**: imgui.hのコメントでAPIの概要を把握し、imgui_internal.hで内部のハンドラー構造を理解する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | 15471-15485行目: SaveIniSettingsToDisk関数の実装 |

**主要処理フロー**:
1. **15473行目**: SettingsDirtyTimer = 0.0fでタイマーリセット
2. **15475-15476行目**: ini_filenameがNULLなら早期リターン
3. **15478-15479行目**: SaveIniSettingsToMemoryでデータ生成
4. **15480行目**: ImFileOpenでファイルオープン（"wt"モード）
5. **15481-15482行目**: オープン失敗なら早期リターン
6. **15483行目**: ImFileWriteでデータ書き込み
7. **15484行目**: ImFileCloseでファイルクローズ

#### Step 3: メモリ上でのデータ生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | 15488-15499行目: SaveIniSettingsToMemory関数 |

**主要処理フロー**:
- **15491行目**: SettingsDirtyTimer = 0.0fでタイマーリセット
- **15492-15493行目**: SettingsIniDataバッファをクリア
- **15494-15495行目**: 各SettingsHandlerのWriteAllFnを呼び出し
- **15496-15498行目**: バッファサイズを返す

#### Step 4: 自動保存メカニズムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui.cpp | `imgui.cpp` | 15312-15337行目: UpdateSettings関数 |
| 4-2 | imgui.cpp | `imgui.cpp` | 15339-15346行目: MarkIniSettingsDirty関数 |

**主要処理フロー**:
- **15325-15336行目**: SettingsDirtyTimer > 0の場合、DeltaTimeを減算
- **15328-15331行目**: タイマーが0以下になったらSaveIniSettingsToDisk実行
- **15332-15333行目**: IniFilenameがNULLの場合はWantSaveIniSettingsをtrue

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

```
SaveIniSettingsToDisk(ini_filename)
    │
    ├─ g.SettingsDirtyTimer = 0.0f
    │
    ├─ SaveIniSettingsToMemory(&ini_data_size)
    │      │
    │      ├─ g.SettingsIniData.Buf.resize(0)
    │      │
    │      └─ for (handler : g.SettingsHandlers)
    │             └─ handler.WriteAllFn(&g, &handler, &g.SettingsIniData)
    │
    ├─ ImFileOpen(ini_filename, "wt")
    │
    ├─ ImFileWrite(ini_data, sizeof(char), ini_data_size, f)
    │
    └─ ImFileClose(f)

[自動保存フロー]
MarkIniSettingsDirty()
    └─ g.SettingsDirtyTimer = g.IO.IniSavingRate
           │
           └─ [毎フレーム]
                  └─ UpdateSettings()
                         ├─ g.SettingsDirtyTimer -= g.IO.DeltaTime
                         └─ [タイマー <= 0]
                                └─ SaveIniSettingsToDisk(g.IO.IniFilename)
```

### データフロー図

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

ウィンドウ操作 ────────▶ MarkIniSettingsDirty()
                              │
                              ▼
                        SettingsDirtyTimer設定
                              │
                              ▼ [毎フレーム]
                        UpdateSettings()
                              │
                              ▼ [タイマー満了]
SaveIniSettingsToDisk ──▶ SaveIniSettingsToMemory()
                              │
                              ▼
                        WriteAllFn() ──────────▶ SettingsIniData
                              │
                              ▼
                        ImFileWrite() ─────────▶ imgui.ini
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言（SaveIniSettingsToDisk等） |
| imgui.cpp | `imgui.cpp` | ソース | 設定保存機能の実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiSettingsHandler, ImGuiWindowSettings定義 |
