# 画面設計書 45-Pointers

## 概要

本ドキュメントは、Avalonia UIフレームワークのControlCatalogサンプルアプリケーションにおける「Pointers」デモページの画面設計書です。

### 本画面の処理概要

Pointersページは、マウス・タッチ・ペンなどのポインター入力デバイスの処理方法をデモンストレーションする画面です。マルチタッチ対応、中間ポイント取得、筆圧検出、ポインターキャプチャなど、ポインター入力の高度な機能を示しています。

**業務上の目的・背景**：現代のアプリケーションでは、マウスだけでなくタッチスクリーンやスタイラスペンなど、多様な入力デバイスへの対応が求められます。本画面は、AvaloniaのPointerイベントシステムを使用して、ポインター種別の識別、マルチタッチ処理、筆圧・傾きの取得、ポインターキャプチャの制御などを実装する方法を示しています。描画アプリケーションやタッチ対応UIの開発に参考になる実装例です。

**画面へのアクセス方法**：MainWindowからMainViewのHamburgerMenuを開き、「Pointers」メニュー項目を選択することでアクセスできます。

**主要な操作・処理内容**：
1. Contactsタブ：マルチタッチポイントの追跡と色分け表示
2. IntermediatePointsタブ：ポインター移動の中間ポイント取得と描画
3. Pressureタブ：筆圧に応じた線の太さでの描画
4. Captureタブ：ポインターキャプチャの動作確認

**画面遷移**：本画面は単独のデモページであり、MainViewのHamburgerMenuから遷移します。他画面への直接遷移機能は持ちません。

**権限による表示制御**：本デモ画面では権限による表示制御は実装されていません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 52 | MouseDevice | 主機能 | マウス入力とポインター位置管理 |
| 49 | InputElement | 補助機能 | 入力要素のイベント処理 |

## 画面種別

デモ / 入力処理

## URL/ルーティング

ControlCatalog内のHamburgerMenuナビゲーションによるページ切り替え（URL/ルーティング定義なし）

## 入出力項目

| 項目名 | 項目種別 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| ThreadSleep | 入力 | int | - | IntermediatePointsタブでのスレッドスリープ時間（0-500ms） |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| Contactsタブ | タブ1 | マルチタッチポイントの追跡表示 |
| IntermediatePointsタブ | タブ2 | 中間ポイント取得と描画 |
| Pressureタブ | タブ3 | 筆圧描画デモ |
| Captureタブ | タブ4 | ポインターキャプチャデモ |
| ThreadSleepスライダー | IntermediatePointsタブ上部 | スリープ時間調整（0-500ms） |
| ステータステキスト | IntermediatePointsタブ/Pressureタブ | ポインター情報表示 |
| BorderCapture1/2 | Captureタブ | キャプチャテスト用Border要素 |

## イベント仕様

### 1-PointerContactsTab - マルチタッチ処理

PointerPressed/PointerMoved/PointerReleasedイベントを処理。各ポインターに固有の色を割り当て、位置を追跡してカスタム描画する。ポインターリリース時に辞書からポインターを削除。

### 2-PointerCanvas - 中間ポイント/筆圧処理

PointerEventArgs.GetIntermediatePoints()で中間ポイントを取得。DrawOnlyPointsモードでは点として、それ以外では筆圧に応じた太さの線として描画。ダブルクリックで描画をクリア。

### 3-Captureタブ - ポインターキャプチャ

Border_PointerPressedでe.Pointer.Capture(sender)によりキャプチャ取得。Border_PointerReleasedでe.Pointer.Capture(null)によりキャプチャ解放。PointerCaptureLostイベントでキャプチャ喪失を検知。

### 4-ステータス更新

DispatcherTimer.Runで250ms間隔でステータスを更新。イベント/秒、PointerUpdateKind、ボタン状態、筆圧・傾き・ツイスト情報を表示。

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

本画面はUIコントロールのデモ画面であり、データベースへのアクセス・更新は行いません。

## メッセージ仕様

本画面では特定のメッセージ表示は実装されていません。ステータス表示領域に動的にポインター情報が表示されます。

## 例外処理

- Captureタブで、キャプチャ中のポインターリリースで他のコントロールにキャプチャされている場合はInvalidOperationExceptionをスロー
- ペン入力でPressure=0の場合は描画をスキップ

## 備考

- PointerType（Mouse/Touch/Pen）による入力デバイス識別
- GetIntermediatePoints()で高解像度の入力ポイントを取得
- PointerPointPropertiesで筆圧（Pressure）、傾き（XTilt/YTilt）、ツイスト（Twist）を取得
- IsBarrelButtonPressed、IsEraser、IsInvertedでペン固有の状態を取得
- PreventGestureRecognition()でジェスチャー認識を無効化し、生のポインターイベントを取得

---

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

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

### 推奨読解順序

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

ポインター追跡とポイント描画のためのデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PointerCanvas.cs | `samples/ControlCatalog/Pages/PointerCanvas.cs` | PointerPoints内部クラス（23-94行）でポイント管理構造を確認 |
| 1-2 | PointerCanvas.cs | `samples/ControlCatalog/Pages/PointerCanvas.cs` | CanvasPoint構造体（25-31行）でBrush/Point/Radius/Pressureを確認 |
| 1-3 | PointerContactsTab.cs | `samples/ControlCatalog/Pages/PointerContactsTab.cs` | PointerInfoクラス（16-20行）でPoint/Colorを確認 |

**読解のコツ**: AvaloniaのIPointerインターフェースとPointerPointPropertiesクラスの仕様を理解しておくと良い。

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

PointersPageのTabControl構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PointersPage.xaml | `samples/ControlCatalog/Pages/PointersPage.xaml` | TabControl構造（5-68行）で4つのタブを確認 |
| 2-2 | PointersPage.xaml.cs | `samples/ControlCatalog/Pages/PointersPage.xaml.cs` | コンストラクタ（9-11行）でInitializeComponent |

**主要処理フロー**:
1. **6-8行**: Contactsタブ - PointerContactsTabコントロール
2. **9-31行**: IntermediatePointsタブ - PointerCanvas + スライダー
3. **32-42行**: Pressureタブ - PointerCanvas（筆圧モード）
4. **43-67行**: Captureタブ - Border要素 + イベントハンドラ

#### Step 3: ポインターイベント処理を理解する

各タブでのポインターイベント処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PointerContactsTab.cs | `samples/ControlCatalog/Pages/PointerContactsTab.cs` | UpdatePointer（55-68行）でポインター追跡 |
| 3-2 | PointerCanvas.cs | `samples/ControlCatalog/Pages/PointerCanvas.cs` | HandleEvent（165-196行）でイベント処理 |
| 3-3 | PointersPage.xaml.cs | `samples/ControlCatalog/Pages/PointersPage.xaml.cs` | Border_Pointer*（14-58行）でキャプチャ処理 |

**主要処理フロー**:
- **PointerContactsTab（70-76行）**: OnPointerPressed - Capture + 色割り当て
- **PointerCanvas（206-217行）**: OnPointerPressed - ダブルクリッククリア
- **PointersPage（53-58行）**: Border_PointerPressed - Capture取得

#### Step 4: カスタム描画を理解する

DrawingContextを使用したカスタム描画を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PointerContactsTab.cs | `samples/ControlCatalog/Pages/PointerContactsTab.cs` | Render（99-108行）で円描画 |
| 4-2 | PointerCanvas.cs | `samples/ControlCatalog/Pages/PointerCanvas.cs` | PointerPoints.Render（36-65行）で線/点描画 |

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

```
PointersPage (UserControl)
    │
    ├─ TabControl
    │      ├─ Contactsタブ
    │      │      └─ PointerContactsTab (Control)
    │      │             ├─ OnPointerPressed/Moved/Released
    │      │             │      └─ UpdatePointer()
    │      │             │             └─ _pointers辞書管理
    │      │             └─ Render()
    │      │                    └─ DrawEllipse()
    │      │
    │      ├─ IntermediatePointsタブ
    │      │      └─ PointerCanvas (Control)
    │      │             ├─ OnPointerPressed/Moved/Released
    │      │             │      └─ HandleEvent()
    │      │             │             └─ GetIntermediatePoints()
    │      │             ├─ Render()
    │      │             │      └─ PointerPoints.Render()
    │      │             └─ DispatcherTimer
    │      │                    └─ ステータス更新
    │      │
    │      ├─ Pressureタブ
    │      │      └─ PointerCanvas (DrawOnlyPoints=false)
    │      │             └─ 筆圧に応じた線描画
    │      │
    │      └─ Captureタブ
    │             └─ Border x 2
    │                    ├─ Border_PointerPressed
    │                    │      └─ e.Pointer.Capture()
    │                    ├─ Border_PointerReleased
    │                    │      └─ e.Pointer.Capture(null)
    │                    └─ Border_PointerCaptureLost
```

### データフロー図

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

ポインター入力 ──────────▶ PointerEventArgs ──────────▶ 描画更新
(Mouse/Touch/Pen)         ├─ GetCurrentPoint()           │
                          ├─ GetIntermediatePoints()     ▼
                          └─ Pointer.Capture()        InvalidateVisual()
                                 │
                                 ▼
                          PointerPointProperties
                          ├─ Position
                          ├─ Pressure
                          ├─ XTilt/YTilt
                          └─ Twist
                                 │
                                 ▼
                          ステータス表示
                          (イベント/秒、ボタン状態等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PointersPage.xaml | `samples/ControlCatalog/Pages/PointersPage.xaml` | XAML | 画面レイアウト・タブ定義 |
| PointersPage.xaml.cs | `samples/ControlCatalog/Pages/PointersPage.xaml.cs` | ソース | コードビハインド・キャプチャ処理 |
| PointerCanvas.cs | `samples/ControlCatalog/Pages/PointerCanvas.cs` | ソース | 中間ポイント・筆圧描画カスタムコントロール |
| PointerContactsTab.cs | `samples/ControlCatalog/Pages/PointerContactsTab.cs` | ソース | マルチタッチ追跡カスタムコントロール |
