# 画面設計書 12-参照パスプロパティページ

## 概要

本ドキュメントは、F# プロジェクトのアセンブリ参照パスを設定するためのプロパティページ「参照パスプロパティページ」の画面設計を記載します。

### 本画面の処理概要

**業務上の目的・背景**：参照パスプロパティページは、F# プロジェクトがアセンブリを検索する追加のディレクトリパスを設定するための画面です。プロジェクト参照として明示的に追加されていないアセンブリを、ビルド時に検索できるようにするために使用します。これは、共有ライブラリの配置場所、サードパーティ製コンポーネントの格納先、組織内の共通アセンブリリポジトリなどを指定する際に重要です。設定されたパスは MSBuild のアセンブリ参照解決プロセスで使用されます。

**画面へのアクセス方法**：Visual Studio のソリューションエクスプローラーで F# プロジェクトを右クリックし、「プロパティ」を選択します。プロジェクトプロパティウィンドウが開いたら、「参照パス」タブをクリックして本画面にアクセスします。

**主要な操作・処理内容**：
1. フォルダパスの入力：テキストボックスに参照パスを直接入力
2. フォルダの参照：「...」ボタンでフォルダ選択ダイアログを表示し、フォルダを選択
3. フォルダの追加：「Add Folder」ボタンで入力したパスをリストに追加
4. フォルダの更新：「Update」ボタンでリスト内の選択項目を現在の入力値で更新
5. フォルダの削除：削除ボタン（X アイコン）または Delete キーでリストから削除
6. 順序の変更：上下矢印ボタンでリスト内の項目順序を変更（参照解決の優先度に影響）

**画面遷移**：
- この画面への遷移元：プロジェクトプロパティの他のタブ（アプリケーション、ビルド、デバッグ、ビルドイベント）
- この画面からの遷移先：なし（本画面内で完結）

**権限による表示制御**：プロジェクトファイルへの書き込み権限がない場合、設定値の変更は反映されません。参照パスの設定はプロジェクトユーザーファイル (.fsproj.user) に保存されるため、ソース管理には含まれません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 52 | アセンブリ参照解決 | 主機能 | アセンブリの検索パス設定 |

## 画面種別

設定（プロパティページ）

## URL/ルーティング

Visual Studio 内蔵のプロパティページとして動作するため、URL/ルーティングは存在しません。
COM クラス GUID: DF16B1A2-0E91-4499-AE60-C7144E614BF1

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|-----------|----------|------|------|
| ReferencePath | 入力/出力 | String | いいえ | セミコロン区切りの参照パスリスト |

## 表示項目

| コントロール名 | 種類 | 説明 | データバインド |
|---------------|------|------|----------------|
| FolderLabel | Label | 「Folder:」ラベル | - |
| Folder | TextBox | フォルダパス入力欄 | - |
| FolderBrowse | Button | 「...」ボタン（フォルダ選択ダイアログ表示） | - |
| AddFolder | Button | 「Add Folder」ボタン | - |
| UpdateFolder | Button | 「Update」ボタン | - |
| ReferencePathLabel | Label | 「Reference paths:」ラベル | - |
| ReferencePath | ListBox | 参照パス一覧（複数行表示） | ReferencePath |
| MoveUp | Button | 上矢印ボタン（順序を上に移動） | - |
| MoveDown | Button | 下矢印ボタン（順序を下に移動） | - |
| RemoveFolder | Button | 削除ボタン（X アイコン） | - |

## イベント仕様

### 1-AddFolder_Click

「Add Folder」ボタン押下時の処理。

1. Folder テキストボックスから絶対パスを取得（GetCurrentFolderPathAbsolute）
2. パスが空でなく、リストに未登録であることを確認
3. IsValidFolderPath でフォルダの存在を確認
4. 有効な場合、ReferencePath リストボックスに追加し選択状態にする
5. SetDirty を呼び出しページを変更状態にする
6. 無効なパスの場合、PPG_InvalidFolderPath エラーメッセージを表示

### 2-UpdateFolder_Click

「Update」ボタン押下時の処理。

1. Folder テキストボックスから絶対パスを取得
2. リストで選択されている項目のインデックスを取得
3. パスが有効な場合、選択項目の値を更新
4. SetDirty を呼び出しページを変更状態にする
5. UpdateFolder ボタンを無効化

### 3-RemoveFolder_Click

削除ボタン押下時の処理。

1. ReferencePath リストの選択インデックスを取得
2. 選択項目が存在する場合、リストから削除
3. SetDirty を呼び出しページを変更状態にする

### 4-MoveUp_Click

上矢印ボタン押下時の処理。

1. 選択インデックスと選択項目を取得
2. インデックスが 0 より大きい場合のみ処理
3. 選択位置の 1 つ上に項目を挿入
4. 新しい位置を選択状態に
5. 元の位置の項目を削除
6. SetDirty を呼び出し

### 5-MoveDown_Click

下矢印ボタン押下時の処理。

1. 選択インデックスと選択項目を取得
2. 選択項目がリストの最後でない場合のみ処理
3. 選択位置の 2 つ下に項目を挿入
4. 新しい位置を選択状態に
5. 元の位置の項目を削除
6. SetDirty を呼び出し

### 6-FolderBrowse_Click

「...」ボタン押下時の処理。

1. GetDirectoryViaBrowse でフォルダ選択ダイアログを表示
2. フォルダが選択された場合、GetRelativeRefPathDirectoryPath で相対パスに変換
3. Folder テキストボックスに設定

### 7-ReferencePath_SelectedIndexChanged

リストボックスの選択変更時の処理。

1. 選択項目のパスを Folder テキストボックスに表示
2. EnableReferencePathGroup を呼び出し各ボタンの有効/無効を更新

### 8-ReferencePath_KeyDown

リストボックスでの Delete キー押下時の処理。

1. Delete キーが押された場合、選択項目を削除
2. 削除後、適切な項目を選択状態にする

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

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

本画面はデータベースを使用しません。設定値はプロジェクトユーザーファイル (.fsproj.user) に保存されます。

| 操作（イベント） | 対象ファイル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Apply（適用） | .fsproj.user | UPDATE | ReferencePath プロパティを更新 |

### プロジェクトユーザーファイル更新項目詳細

#### .fsproj.user ファイル

| 操作 | 項目（要素名） | 更新値・取得条件 | 備考 |
|-----|--------------|-----------------|------|
| UPDATE | ReferencePath | セミコロン区切りのパスリスト | PersistedInProjectUserFile フラグにより .user ファイルに保存 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| PPG_ReferencePathsTitle | 表示 | Reference Paths | ページタイトル |
| PPG_InvalidFolderPath | エラー | 無効なフォルダパス | 存在しないフォルダパスを追加しようとした場合 |
| PPG_SelectReferencePath | 表示 | Select Reference Path | フォルダ選択ダイアログのタイトル |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 無効なフォルダパス | ShowErrorMessage で PPG_InvalidFolderPath を表示 |
| パス結合エラー | RethrowIfUnrecoverable で回復不能な例外のみ再スロー |
| プロジェクトプロパティ取得失敗 | 空文字列を返す |

## 備考

- 参照パスはプロジェクトファイルではなく .fsproj.user ファイルに保存される（ControlDataFlags.PersistedInProjectUserFile）
- パスはプロジェクトディレクトリからの相対パスとして保存可能
- 高コントラストモードに対応したボタン画像の動的切り替えを実装
- SystemEvents.UserPreferenceChanged イベントでシステム設定変更を監視
- PageResizable プロパティが True を返すため、ページのリサイズが可能

---

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

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

### 推奨読解順序

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

参照パスの保存形式とプロパティバインディングを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | ControlData プロパティ、PersistedInProjectUserFile フラグの意味 |

**読解のコツ**: ReferencePath はセミコロン区切りの文字列として保存され、ReferencePathSet/ReferencePathGet で ListBox との相互変換が行われます。

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

ReferencePathsPropPage クラスの初期化とレイアウトを把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | New() コンストラクタ、ボタン画像の初期化 |

**主要処理フロー**:
1. **行 38-59**: New() コンストラクタ - 画像の初期化、イベントハンドラ登録
2. **行 209-217**: ControlData プロパティ - ReferencePath の PropertyControlData 定義
3. **行 277-280**: PostInitPage - EnableReferencePathGroup の呼び出し

#### Step 3: パス操作ロジックを理解する

フォルダの追加・更新・削除・移動の処理フローを追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | AddFolder_Click, UpdateFolder_Click, MoveUp_Click, MoveDown_Click |

**主要処理フロー**:
- **行 286-296**: AddFolder_Click - フォルダ追加処理
- **行 298-311**: UpdateFolder_Click - フォルダ更新処理
- **行 329-346**: MoveUp_Click - 上移動処理
- **行 348-365**: MoveDown_Click - 下移動処理

#### Step 4: パス変換ロジックを理解する

絶対パスと相対パスの変換処理を追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | GetCurrentFolderPathAbsolute, GetRelativeRefPathDirectoryPath |

**主要処理フロー**:
- **行 487-500**: GetCurrentFolderPathAbsolute - プロジェクトパスとの結合による絶対パス生成
- **行 511-538**: GetRelativeRefPathDirectoryPath - 相対パスへの変換

#### Step 5: UI 状態管理を理解する

ボタンの有効/無効状態の制御ロジックを追います。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | EnableReferencePathGroup メソッド |

**主要処理フロー**:
- **行 407-423**: EnableReferencePathGroup - 選択状態に応じた各ボタンの有効/無効制御

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

```
FSharpReferencePathsPropPageComClass (COM エントリポイント)
    │
    └─ ReferencePathsPropPage (ユーザーコントロール)
           │
           ├─ ControlData プロパティ
           │      └─ PropertyControlData (ReferencePath, PersistedInProjectUserFile)
           │             ├─ ReferencePathSet (文字列 → ListBox)
           │             └─ ReferencePathGet (ListBox → 文字列)
           │
           ├─ AddFolder_Click
           │      ├─ GetCurrentFolderPathAbsolute
           │      │      └─ GetRefPathProjectPath (DTEProject.Properties)
           │      ├─ IsValidFolderPath (Directory.Exists)
           │      └─ SetDirty
           │
           ├─ FolderBrowse_Click
           │      ├─ GetDirectoryViaBrowse (フォルダ選択ダイアログ)
           │      └─ GetRelativeRefPathDirectoryPath
           │
           ├─ MoveUp_Click / MoveDown_Click
           │      └─ SetDirty
           │
           └─ 高コントラストモード対応
                  ├─ GenerateButtonImages
                  ├─ UpdateButtonImages
                  └─ SystemEvents_UserPreferenceChanged
```

### データフロー図

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

フォルダパス入力
(Folder TextBox)  ────▶  GetCurrentFolderPathAbsolute
                         │
                         ▼
                         IsValidFolderPath (検証)
                         │
                         ▼
                         ReferencePath ListBox  ────▶  .fsproj.user ファイル
                                                       (ReferencePath)

フォルダ選択
ダイアログ       ────▶  GetRelativeRefPathDirectoryPath
                        (相対パス変換)
                         │
                         ▼
                        Folder TextBox

リスト選択変更   ────▶  EnableReferencePathGroup
                        │
                        ├─▶ AddFolder.Enabled
                        ├─▶ UpdateFolder.Enabled
                        ├─▶ MoveUp.Enabled
                        ├─▶ MoveDown.Enabled
                        └─▶ RemoveFolder.Enabled
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReferencePathsPropPage.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.vb` | ソース | 参照パスプロパティページ本体 |
| ReferencePathsPropPage.resx | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/ReferencePathsPropPage.resx` | リソース | UI 文字列、レイアウト定義、ボタン画像 |
| PropPageUserControlBase.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/PropPageUserControlBase.vb` | ソース | プロパティページ基底クラス |
| FSharpPropPageBase.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/PropertyPages/FSharpPropPageBase.vb` | ソース | F# プロパティページ COM 基底クラス |
| Utils.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/Common/Utils.vb` | ソース | AppendBackslash, MapBitmapColor などユーティリティ |
| SR.vb | `vsintegration/src/FSharp.ProjectSystem.PropertyPages/` | ソース | 文字列リソースアクセサ |
