# 画面設計書 37-レイアウト保存ダイアログ

## 概要

本ドキュメントは、Godot Engineエディタにおけるレイアウト保存ダイアログ（EditorLayoutsDialog）の画面設計を記述する。このダイアログはエディタのウィンドウレイアウト（ドックの配置など）を保存・管理するために使用される。

### 本画面の処理概要

このダイアログ画面では、エディタのレイアウト設定を名前を付けて保存したり、既存のレイアウトを選択して操作（読み込み/削除）したりできる。保存されたレイアウトはConfigFileに永続化され、エディタ再起動後も利用可能である。

**業務上の目的・背景**：エディタユーザーは、作業内容に応じて異なるドック配置を好むことがある。例えば、スクリプト編集時はスクリプトエディタを大きく表示し、レベルデザイン時は3Dビューポートを広くするなど。レイアウト保存機能により、これらの設定を名前付きで保存し、ワンクリックで切り替えることができる。

**画面へのアクセス方法**：エディタメニューの「エディタ」→「エディタレイアウト」→「保存」または「削除」を選択してアクセスする。

**主要な操作・処理内容**：
1. 既存レイアウト一覧の表示（ItemList）
2. 既存レイアウトの選択（複数選択可）
3. 新規レイアウト名の入力（LineEdit）
4. name_confirmedシグナルでレイアウト名を親に通知

**画面遷移**：
- 遷移元：エディタメニュー（エディタレイアウト）
- 遷移先（確定時）：レイアウトが保存/読み込み/削除され、ダイアログが閉じる
- 遷移先（キャンセル時）：変更なしでダイアログが閉じる

**権限による表示制御**：set_name_line_enabled()により、新規レイアウト名入力欄の表示/非表示が制御される。保存ダイアログでは表示、削除ダイアログでは非表示。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| F-060 | エディタレイアウト管理 | 主機能 | レイアウトの保存・読み込み・削除 |
| F-061 | レイアウト設定ファイル | 補助機能 | ConfigFileへの永続化 |

## 画面種別

登録・選択（モーダルダイアログ）

## URL/ルーティング

該当なし（デスクトップアプリケーションのモーダルダイアログ）

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| 名前入力有効化 | 入力 | bool | オプション | set_name_line_enabled()で設定 |
| 選択レイアウト | 入力 | int[] | 条件付き | 既存レイアウトからの選択 |
| 新規レイアウト名 | 入力 | String | 条件付き | 名前入力欄が有効な場合 |
| レイアウト名 | 出力 | String | - | name_confirmedシグナルで出力 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| Select Existing Layout | ラベル | 既存レイアウトリストのタイトル |
| 既存レイアウトリスト | アイテムリスト | 保存済みレイアウトの一覧（複数選択可） |
| Or enter new layout name | プレースホルダー | 新規名前入力欄のヒントテキスト |
| 新規名前入力 | テキスト入力 | 新しいレイアウト名を入力 |

## イベント仕様

### 1-ダイアログ表示

_post_popup()が呼び出され、以下の処理が行われる：
1. layout_namesリストをクリア
2. nameテキスト入力をクリア
3. EditorSettings::get_editor_layouts_config()からConfigFileを読み込み
4. ConfigFileのセクション（'/'を含まないもの）をlayout_namesに追加
5. nameが表示中であればnameにフォーカス、そうでなければlayout_namesにフォーカス

### 2-既存レイアウト選択

layout_namesでアイテムを選択（複数選択可）すると、multi_selectedシグナルにより_update_ok_disable_state()が呼び出される。アイテムが選択されていればOKボタンが有効化される。

### 3-新規名前入力

nameフィールドにフォーカスすると、_deselect_layout_names()が呼び出され、既存レイアウト選択がクリアされる。テキスト入力すると_update_ok_disable_state()が呼び出され、空でなければOKボタンが有効化される。

### 4-Enterキー押下

nameフィールドでEnterキー（ui_text_submit）を押すと、_line_gui_input()が呼び出され、ok_pressed()が実行される。

### 5-OKボタン押下

ok_pressed()が呼び出され、以下の分岐処理が行われる：
1. layout_namesで選択がある場合：選択された各アイテムに対してname_confirmedシグナル発行
2. nameが表示かつ非空の場合：name.get_text()でname_confirmedシグナル発行

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

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| レイアウト保存（呼び出し元で処理） | editor_layouts.cfg | UPDATE | レイアウト設定をセクションとして保存 |
| レイアウト削除（呼び出し元で処理） | editor_layouts.cfg | DELETE | レイアウトセクションを削除 |

### テーブル別更新項目詳細

#### editor_layouts.cfg（レイアウト設定ファイル）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SELECT | セクション一覧 | config->get_sections() | '/'を含まないセクションのみ |
| UPDATE/DELETE | レイアウトセクション | name_confirmedで渡された名前 | 親ダイアログで処理 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| - | プレースホルダー | Or enter new layout name. | 新規名前入力欄 |
| - | ラベル | Select Existing Layout: | 既存レイアウトリストタイトル |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ConfigFile読み込みエラー | _post_popup()が早期リターン（既存レイアウト非表示） |
| 名前が空かつ選択なし | OKボタンが無効化される |

## 備考

- layout_namesは複数選択モード（SELECT_MULTI）で動作
- layout_namesは右クリック選択を許可（set_allow_rmb_select(true)）
- レイアウト名に'/'を含むものは非表示（サブセクション扱いのため）
- ダイアログの最小サイズは300 * EDSCALE（幅）、50 * EDSCALE（高さ）
- name_confirmedシグナルは複数回発行される可能性がある（複数選択時）

---

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

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

### 推奨読解順序

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

ダイアログの構成要素とシグナルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | editor_layouts_dialog.h | `editor/settings/editor_layouts_dialog.h` | クラスメンバ変数（41-43行目）、publicメソッド（55-57行目） |

**読解のコツ**: ItemListとLineEditの2つのUIコンポーネントが主要要素。name_confirmedシグナルが出力の主要インターフェース。

#### Step 2: コンストラクタを理解する

UI構築とイベント接続を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | editor_layouts_dialog.cpp | `editor/settings/editor_layouts_dialog.cpp` | コンストラクタ（112-135行目） |

**主要処理フロー**:
1. **116-126行目**: ItemList（layout_names）の初期化と設定
2. **128-134行目**: LineEdit（name）の初期化とイベント接続

#### Step 3: ダイアログ表示処理を理解する

_post_popup()の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | editor_layouts_dialog.cpp | `editor/settings/editor_layouts_dialog.cpp` | _post_popup()（86-110行目） |

**主要処理フロー**:
- **88-89行目**: リストとテキスト入力のクリア
- **91-96行目**: ConfigFileからのレイアウト読み込み
- **100-104行目**: '/'を含まないセクションの追加
- **105-109行目**: フォーカス設定

#### Step 4: 確定処理を理解する

ok_pressed()の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | editor_layouts_dialog.cpp | `editor/settings/editor_layouts_dialog.cpp` | ok_pressed()（75-84行目） |

**主要処理フロー**:
- **76-80行目**: 選択アイテムがある場合、各アイテムに対してシグナル発行
- **81-83行目**: 名前入力がある場合、入力値でシグナル発行

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

```
EditorLayoutsDialog (ConfirmationDialog)
    │
    ├─ _post_popup()                     [表示時初期化]
    │      ├─ layout_names->clear()
    │      ├─ name->clear()
    │      ├─ ConfigFile::load()
    │      ├─ config->get_sections()
    │      └─ layout_names->add_item()
    │
    ├─ _update_ok_disable_state()        [OKボタン制御]
    │      ├─ layout_names->is_anything_selected()
    │      └─ name->get_text()
    │
    ├─ _deselect_layout_names()          [選択解除]
    │      ├─ layout_names->deselect_all()
    │      └─ _update_ok_disable_state()
    │
    ├─ _line_gui_input(p_event)          [キー入力処理]
    │      ├─ ui_text_submit → ok_pressed()
    │      └─ ui_cancel → hide()
    │
    └─ ok_pressed()                      [確定]
           └─ emit_signal("name_confirmed")
```

### データフロー図

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

_post_popup() ──────────▶ ConfigFile::load() ──────────▶ layout_names表示
                              │
                              └─ EditorSettings::get_editor_layouts_config()

既存レイアウト選択 ─────▶ multi_selected ─────────────▶ OKボタン有効化
ItemList                      │
                              └─ _update_ok_disable_state()

新規名前入力 ───────────▶ text_changed ────────────────▶ OKボタン有効化
LineEdit                      │
                              └─ _update_ok_disable_state()

フォーカス取得 ─────────▶ focus_entered ───────────────▶ 既存選択解除
(nameフィールド)              │
                              └─ _deselect_layout_names()

OKボタン/Enter ─────────▶ ok_pressed() ────────────────▶ "name_confirmed"
                              │                          シグナル発行
                              ├─ 選択あり → 選択アイテム名
                              └─ 名前入力あり → 入力テキスト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| editor_layouts_dialog.cpp | `editor/settings/editor_layouts_dialog.cpp` | ソース | ダイアログの実装 |
| editor_layouts_dialog.h | `editor/settings/editor_layouts_dialog.h` | ヘッダ | クラス定義 |
| editor_settings.h | `editor/settings/editor_settings.h` | ヘッダ | レイアウト設定パス取得 |
| config_file.h | `core/io/config_file.h` | ヘッダ | 設定ファイルI/O |
| item_list.h | `scene/gui/item_list.h` | ヘッダ | レイアウト一覧UI |
| line_edit.h | `scene/gui/line_edit.h` | ヘッダ | 名前入力UI |
