# 画面設計書 79-TextFormatter

## 概要

本ドキュメントは、RenderDemoアプリケーションにおけるTextFormatter（テキストフォーマッター）ページの画面設計を定義するものです。このページは、Avaloniaフレームワークが提供する高度なテキストフォーマッティングAPI（TextFormatter）を使用して、テキストとコントロールを同一行にレイアウトする機能を視覚的にデモンストレーションします。

### 本画面の処理概要

**業務上の目的・背景**：TextFormatterは、テキストとインライン要素（画像、ボタン等）を同一行にレイアウトするための高度なAPIです。チャットアプリケーションでの絵文字埋め込みや、ドキュメントエディタでのインラインウィジェット配置などで使用されます。本画面は、カスタムTextSourceとDrawableTextRunを実装して、テキストとButtonコントロールを混在させる方法を開発者が学習できるようにすることを目的としています。

**画面へのアクセス方法**：RenderDemoアプリケーションを起動後、左側のHamburgerMenuから「TextFormatter」タブを選択することでアクセスできます。

**主要な操作・処理内容**：
1. MeasureOverrideでTextFormatterを使用してTextLineを生成
2. カスタムTextSource（CustomTextSource）でテキストとコントロールを含む行を構築
3. ArrangeOverrideでControlRun内のButtonを配置
4. RenderでTextLine.Draw()を呼び出し描画

**画面遷移**：
- 遷移元：RenderDemo MainWindow（HamburgerMenuより選択）
- 遷移先：なし（デモページのため画面遷移機能は持たない）

**権限による表示制御**：本画面はデモ用途のため、権限による表示制御は実装されていません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 81 | FormattedText | 主機能 | TextFormatterのデモ。高度なテキストフォーマット |

## 画面種別

デモ / 高度なテキストレイアウト表示

## URL/ルーティング

本アプリケーションはデスクトップアプリケーションのため、URLルーティングは使用しません。
HamburgerMenuのタブ選択により画面切り替えが行われます。

## 入出力項目

| 項目名 | 入力/出力 | 型 | 説明 |
|--------|----------|-----|------|
| ClickMeボタン | 入力 | Button | インラインで表示されるボタンコントロール |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| テキスト行（前半） | TextCharacters | "<-Hello World->" テキスト |
| インラインボタン | Button | "ClickMe"テキストを持つボタン |
| テキスト行（後半） | TextCharacters | "<-Hello World->" テキスト（繰り返し） |

## イベント仕様

### 1-Measure時

コントロールの測定時にTextFormatterを使用して行を生成します。

**処理フロー**:
1. MeasureOverride(availableSize)が呼ばれる
2. GenericTextRunPropertiesを作成（デフォルトTypeface、黒色、中央揃え）
3. GenericTextParagraphPropertiesを作成
4. Button + TextBlockを子コントロールとして作成
5. CustomTextSourceを作成（Buttonとプロパティを渡す）
6. control.Measure(Size.Infinity)でボタンを測定
7. TextFormatter.Current.FormatLine()でTextLineを生成
8. _textLineフィールドに保存

### 2-Arrange時

テキスト行内のコントロールを配置します。

**処理フロー**:
1. ArrangeOverride(finalSize)が呼ばれる
2. TextLineのTextRunsを走査
3. ControlRunの場合、Control.Arrange()で配置
4. DrawableTextRunの場合、currentXに幅を加算

### 3-Render時

TextLineを描画します。

**処理フロー**:
1. Render(DrawingContext)が呼ばれる
2. _textLine?.Draw(context, new Point())で描画

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

本画面はデモ表示専用のため、データベース操作は行いません。

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | データベース操作なし |

## メッセージ仕様

本画面はデモ表示専用のため、メッセージ表示機能はありません。

| メッセージID | 種別 | 内容 | 表示条件 |
|-------------|------|------|---------|
| なし | - | - | - |

## 例外処理

| 例外 | 対処 |
|------|------|
| _textLineがnull | Renderメソッドで?演算子により安全にスキップ |
| レンダリングエラー | Avaloniaフレームワークの標準エラーハンドリングに委譲 |

## 備考

- CustomTextSourceはITextSourceインターフェースを実装
- ControlRunはDrawableTextRunを継承し、コントロールをテキスト行に埋め込む
- GetTextRun()は呼び出しごとに異なる要素を返す（テキスト→コントロール→テキスト→null）
- BaselineAlignment.Centerでコントロールを垂直中央揃え
- TextRun.DefaultTextSourceLengthは埋め込みコントロール用の長さ定数
- ControlRun.Draw()はnoopとして実装（実際の描画はArrangeで行われる）

---

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

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

### 推奨読解順序

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

TextFormatterの関連クラス構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TextFormatterPage.axaml.cs | `samples/RenderDemo/Pages/TextFormatterPage.axaml.cs` | CustomTextSourceとControlRunの内部クラスを確認 |

**読解のコツ**: ITextSourceはGetTextRunメソッドを実装し、インデックスに応じてTextRunを返します。ControlRunはDrawableTextRunを継承してコントロールをラップします。

#### Step 2: XAMLを確認する

シンプルなXAML構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TextFormatterPage.axaml | `samples/RenderDemo/Pages/TextFormatterPage.axaml` | 空のUserControlであることを確認 |

#### Step 3: MeasureOverrideを理解する

TextLineの生成処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TextFormatterPage.axaml.cs | `samples/RenderDemo/Pages/TextFormatterPage.axaml.cs` | MeasureOverrideでのTextFormatter使用を確認 |

**主要処理フロー**:
- **行29-33**: GenericTextRunProperties/ParagraphPropertiesの作成
- **行35**: Button + TextBlock作成
- **行39**: CustomTextSource作成
- **行41**: control.Measure(Size.Infinity)
- **行43-44**: TextFormatter.Current.FormatLine()でTextLine生成

#### Step 4: ArrangeOverrideを理解する

コントロール配置処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TextFormatterPage.axaml.cs | `samples/RenderDemo/Pages/TextFormatterPage.axaml.cs` | ArrangeOverrideでのコントロール配置を確認 |

**主要処理フロー**:
- **行49-64**: TextRunsを走査し、ControlRunの場合はArrangeを呼ぶ

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

```
MainWindow
    |
    +-- HamburgerMenu (controls:HamburgerMenu)
           |
           +-- TabItem[Header="TextFormatter"]
                  |
                  +-- TextFormatterPage (UserControl)
                         |
                         +-- MeasureOverride
                         |      |
                         |      +-- GenericTextRunProperties/ParagraphProperties
                         |      +-- Button { TextBlock "ClickMe" }
                         |      +-- CustomTextSource
                         |      +-- TextFormatter.Current.FormatLine()
                         |             |
                         |             +-- TextLine (_textLine)
                         |
                         +-- ArrangeOverride
                         |      |
                         |      +-- foreach (TextRun in _textLine.TextRuns)
                         |             |
                         |             +-- ControlRun.Control.Arrange()
                         |
                         +-- Render
                                |
                                +-- _textLine.Draw(context)
```

### データフロー図

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

テキスト文字列      --> CustomTextSource     --> TextRun列
"<-Hello World->"       .GetTextRun()

Button              --> ControlRun           --> DrawableTextRun
+ TextBlock             (埋め込み)

TextRun列           --> TextFormatter        --> TextLine
                        .FormatLine()

TextLine            --> .Draw()              --> 画面描画
                    --> .TextRuns            --> コントロール配置
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TextFormatterPage.axaml | `samples/RenderDemo/Pages/TextFormatterPage.axaml` | XAML | UIレイアウト（空のUserControl） |
| TextFormatterPage.axaml.cs | `samples/RenderDemo/Pages/TextFormatterPage.axaml.cs` | C# | TextFormatter使用の実装（CustomTextSource、ControlRun含む） |
| MainWindow.xaml | `samples/RenderDemo/MainWindow.xaml` | XAML | ホスト画面（HamburgerMenuでページを管理） |
