# 画面設計書 12-新規型作成先選択コントロール

## 概要

本ドキュメントは、Roslyn（.NET Compiler Platform）のVisual Studio拡張機能における「新規型作成先選択コントロール」の画面設計を記述するものである。

### 本画面の処理概要

新規型作成先選択コントロール（NewTypeDestinationSelection）は、型生成やクラス抽出、インターフェース抽出などのリファクタリング操作において、新しく生成される型の名前と作成先（現在のファイルまたは新規ファイル）を指定するための共通UIコンポーネントである。

**業務上の目的・背景**：
コードリファクタリングにおいて新しい型（クラス、インターフェース等）を生成する際、開発者は型の名前、作成先ファイル、および生成されるファイル名を決定する必要がある。本コントロールは、これらの設定を統一されたUIで提供することにより、複数のリファクタリングダイアログで一貫したユーザー体験を実現する。また、入力バリデーション（識別子の妥当性、ファイル名の妥当性、名前衝突チェック）を提供し、不正なリファクタリング操作を防止する。

**画面へのアクセス方法**：
本コントロールは単体では使用されず、以下のダイアログに埋め込まれて使用される：
1. 型生成ダイアログ（GenerateTypeDialog）
2. クラス抽出ダイアログ（ExtractClassDialog）
3. インターフェース抽出ダイアログ（ExtractInterfaceDialog）

**主要な操作・処理内容**：
1. 新規型名の入力：テキストボックスで新しい型の名前を入力
2. 生成名の自動表示：名前空間と型名を組み合わせた完全修飾名を読み取り専用で表示
3. 作成先の選択：「現在のファイルに追加」または「新規ファイル」をラジオボタンで選択
4. ファイル名の入力：新規ファイル選択時にファイル名を入力（自動補完あり）
5. 入力バリデーション：型名とファイル名の妥当性を検証

**画面遷移**：
- 遷移元：各種リファクタリングダイアログからコントロールとして埋め込み
- 遷移先：なし（親ダイアログの一部として機能）

**権限による表示制御**：
- `CanAddDocument`プロパティがfalseの場合、「新規ファイル」オプションが無効化される
- これはプロジェクトへのファイル追加権限に依存

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 39 | 型生成 | 補助機能 | 新規型のファイル名・プロジェクト選択の共通コントロール |

## 画面種別

入力フォーム（型名・ファイル名入力、作成先選択）

## URL/ルーティング

N/A（WPF UserControlとして実装、Visual Studio拡張機能の一部）

## 入出力項目

### 入力（バインディングプロパティ）

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| ViewModel | NewTypeDestinationSelectionViewModel | Yes | 入力状態を管理するViewModel |

### ViewModel構成プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|------|------|
| TypeName | string | 新規型の名前 |
| FileName | string | 新規ファイルの名前 |
| GeneratedName | string | 生成される完全修飾型名（読み取り専用） |
| Destination | NewTypeDestination | 作成先（CurrentFile/NewFile） |
| CanAddDocument | bool | 新規ファイル追加が可能かどうか |
| FileNameEnabled | bool | ファイル名入力が有効かどうか |

## 表示項目

### 型名入力セクション

| 項目名 | コントロール | バインディング | 説明 |
|--------|-------------|---------------|------|
| ラベル | Label (TypeNameLabel) | - | "New Type Name:" |
| 型名入力 | TextBox (TypeNameTextBox) | TypeName (TwoWay) | 新規型の名前を入力 |

### 生成名表示セクション

| 項目名 | コントロール | バインディング | 説明 |
|--------|-------------|---------------|------|
| ラベル | Label (GeneratedNameLabel) | - | "Generated name:" |
| 生成名 | TextBox (GeneratedNameTextBox) | GeneratedName (OneWay) | 完全修飾名を表示（読み取り専用） |

### 作成先選択セクション（GroupBox）

| 項目名 | コントロール | バインディング | 説明 |
|--------|-------------|---------------|------|
| 現在ファイル | RadioButton | Destination (CurrentFile) | 現在のファイルに追加 |
| 新規ファイル | RadioButton | Destination (NewFile) | 新規ファイルを作成 |
| ファイル名入力 | TextBox (fileNameTextBox) | FileName (TwoWay) | 新規ファイル名を入力 |

## イベント仕様

### 1-型名入力変更

1. TypeNameTextBoxのTextが変更される
2. TwoWayバインディングによりViewModel.TypeNameが更新される
3. ViewModelのTypeNameセッターでFileNameが自動更新される（型名 + 拡張子）
4. GeneratedNameプロパティ変更通知が発行される

### 2-作成先変更

1. ラジオボタンの選択が変更される
2. EnumBoolConverterによりDestinationプロパティが更新される
3. FileNameEnabledプロパティが連動して更新される
4. NewFile選択時はファイル名入力が有効化される

### 3-テキストボックスフォーカス取得

1. テキストボックスがフォーカスを取得
2. `SelectAllInTextBox`メソッドが実行される
3. マウス左ボタンが押されていない場合、テキスト全選択が行われる

### 4-バリデーション（TrySubmit）

1. 親ダイアログからTrySubmitが呼び出される
2. 型名の競合チェック（conflictingNamesとの照合）
3. 識別子の妥当性チェック（ISyntaxFactsService.IsValidIdentifier）
4. ファイル名の拡張子チェック
5. ファイル名の不正文字チェック
6. エラーがある場合はメッセージを返却、正常時はtrueを返却

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

N/A（本コントロールはデータベースとの直接的なやり取りは行わない）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|----------------|
| - | エラー | "Name conflicts with an existing type name" | 型名が既存の型と競合する場合 |
| - | エラー | "Name is not a valid {language} identifier" | 型名が無効な識別子の場合 |
| - | エラー | "File name must have the {extension} extension" | ファイル拡張子が不正な場合 |
| - | エラー | "Illegal characters in path" | ファイル名に不正文字が含まれる場合 |

## 例外処理

| 例外ケース | 対処 |
|-----------|------|
| SyntaxFactsServiceがnull | InvalidOperationExceptionをスロー（設計上発生しない想定） |
| CanAddDocument=false | 「新規ファイル」オプションを無効化、CurrentFileのみ選択可能 |

## 備考

- 本コントロールはDependencyPropertyとしてViewModelを公開しており、XAMLからバインディング可能
- EnumBoolConverterを使用してラジオボタンとEnum値の相互変換を実現
- 言語（C#/VB）に応じてファイル拡張子（.cs/.vb）が自動設定される
- VSThemeDictionary.xamlを参照しており、Visual Studioのテーマに対応

---

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

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

### 推奨読解順序

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

入力状態とバリデーションロジックを管理するViewModelの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | NewTypeDestinationSelectionViewModel.cs | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelectionViewModel.cs` | TypeName/FileName/Destinationプロパティ、TrySubmitメソッドによるバリデーション |

**読解のコツ**:
- `NewTypeDestination`列挙型（CurrentFile/NewFile）が作成先を表す
- TypeNameのセッターでFileNameが自動更新される連動ロジックに注目

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

XAML定義とコードビハインドでUIの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NewTypeDestinationSelection.xaml | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelection.xaml` | StackPanel内のラベル/テキストボックス/ラジオボタン構成 |
| 2-2 | NewTypeDestinationSelection.xaml.cs | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelection.xaml.cs` | DependencyProperty定義、SelectAllInTextBox実装 |

**主要処理フロー**:
1. **行18-27**: ViewModelプロパティのDependencyProperty定義
2. **行41-47**: コンストラクタでデフォルトViewModelを設定
3. **行49-56**: SelectAllInTextBoxでテキスト全選択

#### Step 3: バリデーションロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NewTypeDestinationSelectionViewModel.cs | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelectionViewModel.cs` | TrySubmitメソッド（行109-145）のバリデーション実装 |

**主要処理フロー**:
- **行118-122**: 型名の競合チェック
- **行124-128**: 識別子妥当性チェック
- **行130-135**: ファイル拡張子チェック
- **行137-142**: ファイル名不正文字チェック

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

```
NewTypeDestinationSelection (UserControl)
    │
    ├─ DependencyProperty: ViewModel
    │      └─ PropertyMetadata → DataContext設定
    │
    ├─ NewTypeDestinationSelectionViewModel
    │      ├─ TypeName (setter)
    │      │      ├─ FileName自動更新
    │      │      └─ GeneratedName通知
    │      │
    │      ├─ Destination (setter)
    │      │      └─ FileNameEnabled通知
    │      │
    │      └─ TrySubmit()
    │             ├─ conflictingNames.Contains()
    │             ├─ ISyntaxFactsService.IsValidIdentifier()
    │             ├─ Path.GetExtension()
    │             └─ Path.GetInvalidFileNameChars()
    │
    └─ EnumBoolConverter
           └─ ラジオボタン ⇔ Enum変換
```

### データフロー図

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

ユーザー入力          NewTypeDestinationSelectionViewModel    検証結果
(型名) ───────────▶ TypeName ──────────────────────────────▶ GeneratedName
                       │                                      (完全修飾名)
                       └─▶ FileName自動更新

ラジオボタン ─────▶ Destination ─────────────────────────▶ FileNameEnabled
(作成先)              │
                      └─▶ UI状態更新

TrySubmit()        ISyntaxFactsService                      エラーメッセージ
呼び出し ──────────▶ バリデーション ─────────────────────▶ または true
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NewTypeDestinationSelection.xaml | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelection.xaml` | XAML | UI定義 |
| NewTypeDestinationSelection.xaml.cs | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelection.xaml.cs` | ソース | コードビハインド |
| NewTypeDestinationSelectionViewModel.cs | `src/VisualStudio/Core/Def/CommonControls/NewTypeDestinationSelectionViewModel.cs` | ソース | ViewModel実装 |
| EnumBoolConverter.cs | `src/VisualStudio/Core/Def/Implementation/Utilities/EnumBoolConverter.cs` | ソース | Enum-Bool変換 |
| VSThemeDictionary.xaml | `src/VisualStudio/Core/Def/VSThemeDictionary.xaml` | XAML | テーマリソース |
| ServicesVSResources.resx | `src/VisualStudio/Core/Def/ServicesVSResources.resx` | リソース | ローカライズ文字列 |
| AbstractNotifyPropertyChanged.cs | `src/VisualStudio/Core/Def/Implementation/Utilities/AbstractNotifyPropertyChanged.cs` | ソース | ViewModel基底クラス |
