# 通知設計書 6-RaiseNotice

## 概要

本ドキュメントは、Windows Terminal におけるターミナルコントロール通知イベント（RaiseNotice）の設計仕様を定義する。ターミナルコントロール（ControlCore/TermControl）から発生する各種通知を ControlNoticeDialog としてユーザーに表示するイベント連鎖の仕組みである。

### 本通知の処理概要

RaiseNotice は、ターミナルコントロール内部で発生した通知（読み取り専用モード有効化、レンダラー警告、シェーダーエラー等）をイベントチェーンで伝搬し、最終的にモーダルダイアログとしてユーザーに表示する仕組みである。

**業務上の目的・背景**：ターミナルコントロール内部で発生する各種状態変化やエラーをユーザーに通知する汎用的な仕組みを提供する。通知レベル（Debug/Info/Warning/Error）に応じてタイトルアイコンが変わり、ユーザーが問題の重要度を一目で判別できる。読み取り専用モードの有効化通知やピクセルシェーダーのコンパイルエラー通知など、多様な用途に使用される。

**通知の送信タイミング**：ControlCore 内で `_raiseReadOnlyWarning()` が呼ばれた時（読み取り専用モード有効化時）、TermControl 内で `_RendererWarning()` が呼ばれた時（レンダラー警告発生時）など、各種エラーや状態変化の検出時にイベントが raise される。イベントは ControlCore -> TermControl -> TerminalPage の順で伝搬する。

**通知の受信者**：現在のウィンドウを操作しているユーザー自身。モーダルダイアログ（ContentDialog）として表示される。

**通知内容の概要**：NoticeLevel に応じたタイトル（Debug/Info/Warning/Error のローカライズ文字列）と、通知メッセージが表示される。メッセージ内容は通知の種類によって異なる（例：読み取り専用モードの説明、シェーダーファイルが見つからないエラーメッセージなど）。

**期待されるアクション**：ユーザーは通知内容を確認し、OKボタンでダイアログを閉じる。エラー内容に応じて設定の修正やファイルの配置等の対処を行う。

## 通知種別

アプリ内通知（ContentDialog ベースのモーダルダイアログ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（UIスレッドへの `co_await wil::resume_foreground` によるマーシャリング） |
| 優先度 | NoticeLevel に依存（Debug=10, Info=20, Warning=30, Error=40） |
| リトライ | 無し |

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

RaiseNotice イベントを発火した TermControl が所属する TerminalPage に対して表示される。`_RegisterTerminalEvents` でイベントハンドラが登録される。

## 通知テンプレート

### モーダルダイアログ（ContentDialog）の場合

| 項目 | 内容 |
|-----|------|
| UIコントロール | `ContentDialog`（ControlNoticeDialog） |
| x:Uid | `ControlNoticeDialog` |
| DefaultButton | Primary |

### 本文テンプレート

```
Title: {NoticeLevelに応じたローカライズ文字列}
  - Debug: NoticeDebug リソース
  - Info: NoticeInfo リソース
  - Warning: NoticeWarning リソース
  - Error: NoticeError リソース
Content: {通知メッセージ}
  - テキスト選択可能（IsTextSelectionEnabled="True"）
  - テキスト折り返し（TextWrapping="WrapWholeWords"）
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Level | 通知レベル（Debug/Info/Warning/Error） | NoticeEventArgs.Level | Yes |
| Message | 通知メッセージ文字列 | NoticeEventArgs.Message | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部イベント | ControlCore._raiseReadOnlyWarning | 読み取り専用モードが有効化された時 | Info レベルの通知 |
| 内部イベント | TermControl._RendererWarning | レンダラーで警告/エラーが発生した時 | Warning レベルの通知 |
| 内部イベント | TermControl._coreRaisedNotice | ControlCore から RaiseNotice が伝搬した時 | 中継（レベルはコアの通知に依存） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| _dialogPresenter が無効 | ダイアログプレゼンターが取得できない場合、ダイアログは表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A1[ControlCore: 読み取り専用モード有効化] --> B1[_raiseReadOnlyWarning]
    A2[TermControl: レンダラー警告検出] --> B2[_RendererWarning]
    B1 --> C1[ControlCore.RaiseNotice.raise]
    C1 --> D[TermControl._coreRaisedNotice]
    D --> E[TermControl.RaiseNotice.raise]
    B2 --> E
    E --> F[TerminalPage._ControlNoticeRaisedHandler]
    F --> G[co_await UIスレッドへマーシャリング]
    G --> H[NoticeLevel に応じたタイトル決定]
    H --> I[_ShowControlNoticeDialog]
    I --> J{_dialogPresenter 有効?}
    J -->|Yes| K[FindName でControlNoticeDialog取得]
    K --> L[Title設定]
    L --> M[NoticeMessage.Text設定]
    M --> N[presenter.ShowDialog]
    J -->|No| O[表示スキップ]
```

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

### 参照テーブル一覧

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 弱参照消失 | co_await 後に TerminalPage が破棄されている場合 | `weakThis.get()` で null チェックし、null の場合は co_return |
| ダイアログプレゼンター無効 | `_dialogPresenter.get()` が null の場合 | ダイアログ表示をスキップ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | ContentDialog はモーダルのため同時に1つのみ表示可能 |

### 配信時間帯

制限なし

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

- 通知メッセージにファイルパス情報（シェーダーファイル等）が含まれる場合がある。
- ダイアログ内のテキストは選択可能（`IsTextSelectionEnabled="True"`）であり、コピーが可能。
- 内部エラーの HRESULT 値やシステムメッセージが表示されることがある。

## 備考

- RaiseNotice は汎用的な通知イベントであり、特定の通知内容に限定されない。
- イベントチェーン：ControlCore.RaiseNotice -> TermControl._coreRaisedNotice -> TermControl.RaiseNotice -> TerminalPage._ControlNoticeRaisedHandler
- ControlCore から直接 RaiseNotice する場合と、TermControl で生成して RaiseNotice する場合がある。
- `_RendererWarning` ではHRESULTに応じたメッセージのフォーマットが行われる：
  - `ERROR_FILE_NOT_FOUND` / `ERROR_PATH_NOT_FOUND`: ピクセルシェーダー未発見
  - `D2DERR_SHADER_COMPILE_FAILED`: シェーダーコンパイル失敗
  - `DWRITE_E_NOFONT`: フォント未発見
  - `ATLAS_ENGINE_ERROR_MAC_TYPE`: MacType エラー
  - その他: FormatMessage による汎用メッセージ
- ControlCore の `_coreRaisedNotice` の説明コメントに「コアがライトロックを保持中に raise する可能性があるため、ハンドラ内でコアのメソッドを呼び出すとデッドロックの危険がある」と記載されている。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EventArgs.idl | `src/cascadia/TerminalControl/EventArgs.idl` | `NoticeLevel` 列挙型（行77-83: Debug=10, Info=20, Warning=30, Error=40）と `NoticeEventArgs` runtimeclass（行85-89） |
| 1-2 | EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | `NoticeEventArgs` 構造体の実装（行116-128）。Level と Message プロパティ |

**読解のコツ**: NoticeLevel は数値付き列挙型で、重要度の大小比較に使える設計になっている。

#### Step 2: エントリーポイント（発生源）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | `_raiseReadOnlyWarning()` メソッド（行2228-2232）。Info レベルの通知を生成して RaiseNotice を raise |
| 2-2 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | `_RendererWarning()` メソッド（行1306-1356）。HRESULT に応じたメッセージ生成と Warning レベルの通知 |

**主要処理フロー**:
1. **行2230-2231** (ControlCore.cpp): `NoticeEventArgs` を生成し `RaiseNotice.raise` を呼ぶ
2. **行1323-1352** (TermControl.cpp): HRESULT の switch 文でメッセージを決定
3. **行1354-1355** (TermControl.cpp): Warning レベルの `NoticeEventArgs` を生成し `RaiseNotice.raise`

#### Step 3: イベント伝搬を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | `_coreRaisedNotice()`（行3645-3653）。ControlCore からのイベントを中継 |
| 3-2 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | 行312: `_revokers.RaiseNotice` でイベント登録 |

#### Step 4: ハンドラ（受信側）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_RegisterTerminalEvents()`（行1955）でハンドラ登録 |
| 4-2 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_ControlNoticeRaisedHandler()`（行3143-3171）。UIスレッドへのマーシャリング、NoticeLevel 判定、ダイアログ表示 |
| 4-3 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | `_ShowControlNoticeDialog()`（行3174-3189）。ControlNoticeDialog の FindName・タイトル設定・表示 |

#### Step 5: XAML定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | `ControlNoticeDialog` ContentDialog の定義（行133-145）。テキスト選択可能な TextBlock と NoticeMessage Run を確認 |

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

```
[ControlCore]
    |
    +-- _raiseReadOnlyWarning() (ControlCore.cpp 行2228)
    |      +-- RaiseNotice.raise(NoticeLevel::Info, ...) (行2231)
    |
    +-- [ControlCore.RaiseNotice イベント]
           |
           +-- TermControl._coreRaisedNotice() (TermControl.cpp 行3645)
                  +-- TermControl.RaiseNotice.raise() (行3652)

[TermControl]
    |
    +-- _RendererWarning() (TermControl.cpp 行1306)
    |      +-- [HRESULTに応じたメッセージ生成] (行1323-1352)
    |      +-- RaiseNotice.raise(NoticeLevel::Warning, ...) (行1355)
    |
    +-- [TermControl.RaiseNotice イベント]
           |
           +-- TerminalPage._ControlNoticeRaisedHandler() (TerminalPage.cpp 行3143)
                  +-- co_await UIスレッド (行3147)
                  +-- NoticeLevel 判定 → タイトル決定 (行3154-3168)
                  +-- _ShowControlNoticeDialog(title, message) (行3170)
                         +-- FindName("ControlNoticeDialog") (行3179)
                         +-- Title / NoticeMessage 設定 (行3181-3184)
                         +-- presenter.ShowDialog() (行3187)
```

### データフロー図

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

状態変化 / エラー検出        NoticeEventArgs 生成                     ContentDialog 表示
(ReadOnly有効化,        --> ControlCore → TermControl → TerminalPage -->  Title: レベル名
 レンダラー警告 等)          イベントチェーン伝搬                          Content: メッセージ
                             NoticeLevel 判定                            (モーダル表示)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EventArgs.idl | `src/cascadia/TerminalControl/EventArgs.idl` | IDL | NoticeLevel 列挙型と NoticeEventArgs の定義 |
| EventArgs.h | `src/cascadia/TerminalControl/EventArgs.h` | ソース | NoticeEventArgs の実装 |
| ControlCore.idl | `src/cascadia/TerminalControl/ControlCore.idl` | IDL | RaiseNotice イベントの定義 |
| ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | ソース | _raiseReadOnlyWarning の実装 |
| ControlCore.h | `src/cascadia/TerminalControl/ControlCore.h` | ソース | RaiseNotice イベントメンバ |
| TermControl.idl | `src/cascadia/TerminalControl/TermControl.idl` | IDL | TermControl 側の RaiseNotice イベント定義 |
| TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ソース | _RendererWarning, _coreRaisedNotice の実装 |
| TermControl.h | `src/cascadia/TerminalControl/TermControl.h` | ソース | RaiseNotice イベントメンバ |
| TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | XAML | ControlNoticeDialog のUI定義 |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | _ControlNoticeRaisedHandler と _ShowControlNoticeDialog の実装 |
