# 通知設計書 65-NOTIFICATION_PRE_SORT_CHILDREN

## 概要

本ドキュメントは、Godotエンジンにおける`NOTIFICATION_PRE_SORT_CHILDREN`通知の設計仕様を定義する。この通知はContainerクラスで子ノードのソート処理が開始される直前に送信される内部通知である。

### 本通知の処理概要

`NOTIFICATION_PRE_SORT_CHILDREN`通知は、ContainerノードがGUIレイアウトのために子コントロールをソート・再配置する直前に発火される。これにより、コンテナを継承したカスタムクラスがソート前に必要な前処理を実行できる。

**業務上の目的・背景**：GUIレイアウトシステムにおいて、子コントロールの配置を計算する前に事前準備が必要な場合がある。例えば、レイアウト計算に使用するデータの更新、キャッシュのクリア、子ノードの可視性に基づく準備処理などを行うためにこの通知が使用される。

**通知の送信タイミング**：Container::queue_sort()によってソートがスケジュールされ、実際のソート処理（_sort_children）が実行される際、NOTIFICATION_SORT_CHILDRENの直前に送信される。

**通知の受信者**：Containerクラスおよびその派生クラス（BoxContainer、GridContainer、MarginContainerなど）。_notificationメソッドで受信して処理する。

**通知内容の概要**：通知値は`50`（Container::NOTIFICATION_PRE_SORT_CHILDREN）。追加のパラメータは含まれない。

**期待されるアクション**：受信者はソート前の準備処理（レイアウトデータの更新、キャッシュのリセット、子ノードの状態確認など）を実装する。

## 通知種別

アプリ内通知（エンジン内部通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

### 送信先決定ロジック

Container自身の_notificationメソッドに対して送信される。propagate_notificationは使用しない。

## 通知テンプレート

### エンジン内部通知の場合

| 項目 | 内容 |
|-----|------|
| 通知定数名 | NOTIFICATION_PRE_SORT_CHILDREN |
| 通知値 | 50 |
| 定義クラス | Container |

### 通知ペイロード

通知に追加データは含まれない。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| p_notification | 通知ID（50） | エンジン内部 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| レイアウト更新 | _sort_children実行 | コンテナがツリー内 | queue_sortによるソート実行時 |
| サイズ変更 | NOTIFICATION_RESIZED | レイアウト更新必要 | コンテナのサイズが変更された時 |
| テーマ変更 | NOTIFICATION_THEME_CHANGED | レイアウト更新必要 | テーマが変更された時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ツリー外 | is_inside_tree()がfalseの場合 |
| ソート未スケジュール | pending_sortがfalseの場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[レイアウト更新トリガー] --> B[queue_sort呼び出し]
    B --> C{ツリー内?}
    C -->|Yes| D{pending_sort?}
    C -->|No| E[処理終了]
    D -->|No| F[pending_sort = true]
    D -->|Yes| E
    F --> G[_sort_childrenをcall_deferred]
    G --> H[_sort_children実行]
    H --> I[NOTIFICATION_PRE_SORT_CHILDREN送信]
    I --> J[pre_sort_childrenシグナル発火]
    J --> K[NOTIFICATION_SORT_CHILDREN送信]
    K --> L[sort_childrenシグナル発火]
    L --> M[pending_sort = false]
    M --> N[処理終了]
    E --> N
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。

### 更新テーブル一覧

本通知はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ツリー外呼び出し | ノードがシーンツリーに未参加 | pending_sortをfalseにして終了 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（フレームレート依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

常時（レイアウト更新時）

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

- 本通知はエンジン内部の通知であり、外部からの直接送信は不可能
- レイアウト処理はメインスレッドで実行される

## 備考

- 対となる通知として`NOTIFICATION_SORT_CHILDREN`（51）がある
- `pre_sort_children`シグナルも同時に発火される
- call_deferredで遅延実行されるため、同一フレーム内での複数回のqueue_sortは1回にまとめられる

---

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

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

### 推奨読解順序

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

まず、通知定数の定義場所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | container.h | `scene/gui/container.h` | 63-66行目でNOTIFICATION_PRE_SORT_CHILDRENが50として定義されていることを確認 |
| 1-2 | container.h | `scene/gui/container.h` | 38行目でpending_sortフラグが定義されている |

**読解のコツ**: Containerクラス固有の通知であり、ControlやNodeではなくContainerで定義されている点に注目する。

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

通知を発火する_sort_childrenメソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | container.cpp | `scene/gui/container.cpp` | 81-93行目の_sort_children()メソッドで通知が発火される |

**主要処理フロー**:
1. **82-85行目**: ツリー外の場合はpending_sortをfalseにして終了
2. **87行目**: `notification(NOTIFICATION_PRE_SORT_CHILDREN);`で通知送信
3. **88行目**: `emit_signal(SceneStringName(pre_sort_children));`でシグナル発火
4. **90行目**: `notification(NOTIFICATION_SORT_CHILDREN);`で次の通知送信

#### Step 3: ソートスケジューリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | container.cpp | `scene/gui/container.cpp` | 130-141行目のqueue_sort()メソッドでソートがスケジュールされる |

**主要処理フロー**:
- **131-133行目**: ツリー外の場合は早期リターン
- **135-137行目**: 既にpending_sortがtrueの場合は早期リターン
- **139行目**: `callable_mp(this, &Container::_sort_children).call_deferred();`で遅延呼び出し
- **140行目**: `pending_sort = true;`でフラグ設定

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

```
Container
    │
    ├─ queue_sort()
    │      └─ _sort_children().call_deferred()
    │
    └─ _sort_children()
           │
           ├─ notification(NOTIFICATION_PRE_SORT_CHILDREN)
           │      └─ _notification() で受信
           │
           ├─ emit_signal("pre_sort_children")
           │
           ├─ notification(NOTIFICATION_SORT_CHILDREN)
           │
           └─ emit_signal("sort_children")
```

### データフロー図

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

レイアウト変更     ───▶ queue_sort()              ───▶ _sort_children()
トリガー                      │                               │
                              ▼                               ▼
                         call_deferred                PRE_SORT_CHILDREN通知
                                                              │
                                                              ▼
                                                    pre_sort_childrenシグナル
                                                              │
                                                              ▼
                                                    SORT_CHILDREN通知
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| container.h | `scene/gui/container.h` | ソース | 通知定数・クラス定義 |
| container.cpp | `scene/gui/container.cpp` | ソース | Container実装・通知発火 |
| box_container.cpp | `scene/gui/box_container.cpp` | ソース | BoxContainer派生クラス |
| grid_container.cpp | `scene/gui/grid_container.cpp` | ソース | GridContainer派生クラス |
| margin_container.cpp | `scene/gui/margin_container.cpp` | ソース | MarginContainer派生クラス |
| flow_container.cpp | `scene/gui/flow_container.cpp` | ソース | FlowContainer派生クラス |
| split_container.cpp | `scene/gui/split_container.cpp` | ソース | SplitContainer派生クラス |
