# 機能設計書 107-テーマ管理

## 概要

本ドキュメントは、Windows Terminalのテーマ管理機能について記述する。テーマはウィンドウ・タブ行・タブの外観をカスタマイズする設定の集合であり、ライト/ダーク/システムテーマの切り替え、タイトルバーやタブのカスタムカラー設定、アクセントカラーの利用を含む。ThemePairによるライト/ダーク自動切替にも対応している。

### 本機能の処理概要

**業務上の目的・背景**：ターミナルエミュレータの外観を統一的にカスタマイズする需要がある。テーマ機能は、ウィンドウのタイトルバー色、タブ行の背景色、タブの非フォーカス時の色などを一括で管理し、ユーザーの好みやシステムのダーク/ライトモードに合わせた外観を提供する。

**機能の利用シーン**：ユーザーがsettings.jsonでテーマを定義し、グローバル設定で適用テーマを選択する。システムのテーマ切り替えに応じて自動でライト/ダークテーマが切り替わる。タイトルバーにアクセントカラーやターミナル背景色を使用することも可能。

**主要な処理内容**：
1. テーマ定義のJSON読み込み・書き出し（Theme::FromJson / ToJson）
2. ウィンドウ・タブ行・タブ・設定UIの外観プロパティ管理（WindowTheme, TabRowTheme, TabTheme, SettingsTheme）
3. ThemeColorの3種類の色指定（固定色、アクセントカラー、ターミナル背景色）のEvaluate処理
4. ライト/ダークテーマの自動切替（ThemePair）
5. システムダークモード検出（IsSystemInDarkTheme）

**関連システム・外部連携**：WinRT/XAML UIフレームワーク、Windowsレジストリ（DWMアクセントカラー）、settings.json。

**権限による制御**：特段の権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | GlobalAppearance（外観設定） | 補助機能 | テーマの選択と適用 |

## 機能種別

設定管理 / UI外観

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | テーマの識別名 | 空文字チェック |
| window | WindowTheme | No | ウィンドウ外観設定 | JSONオブジェクト |
| tabRow | TabRowTheme | No | タブ行外観設定 | JSONオブジェクト |
| tab | TabTheme | No | タブ外観設定 | JSONオブジェクト |
| settings | SettingsTheme | No | 設定UI外観 | JSONオブジェクト |

### 入力データソース

- settings.json（themes配列）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Theme | Theme | テーマオブジェクト |
| RequestedTheme | ElementTheme | ライト/ダーク/デフォルト |
| ThemeColor::Evaluate結果 | Brush | 評価済みのXAMLブラシ |

### 出力先

- UI要素への外観適用（タイトルバー、タブ行、タブ）
- settings.jsonへのシリアライズ

## 処理フロー

### 処理シーケンス

```
1. テーマ読み込み (Theme::FromJson)
   |-- nameキーの読み込み
   |-- 各サブオブジェクトのデシリアライズ
   |   |-- WindowTheme: RequestedTheme, DarkTitlebar等
   |   |-- TabRowTheme: Background等
   |   |-- TabTheme: UnfocusedBackground等
   |   +-- SettingsTheme: 設定UI関連
   +-- Themeオブジェクト生成

2. テーマカラー評価 (ThemeColor::Evaluate)
   |-- ColorType判定
   |   |-- Accent: DWMレジストリからアクセントカラー取得
   |   |   +-- タイトルバー用: HKCU\Software\Microsoft\Windows\DWM\AccentColor
   |   |   +-- 非タイトルバー: SystemAccentColorリソース
   |   |-- Color: 固定色をSolidColorBrushとして返却
   |   +-- TerminalBackground: terminalBackgroundブラシをそのまま返却
   +-- ブラシを返却

3. ThemePair評価
   |-- IsSystemInDarkTheme()でシステムテーマ判定
   +-- ダーク/ライトに応じたテーマ名を選択
```

### フローチャート

```mermaid
flowchart TD
    A[settings.json読み込み] --> B[Theme::FromJson]
    B --> C[各サブテーマをパース]
    C --> D[ThemeColor::Evaluate呼び出し]
    D --> E{ColorType}
    E -->|Accent| F[DWMレジストリ or SystemAccentColor]
    E -->|Color| G[固定色SolidColorBrush]
    E -->|TerminalBackground| H[ターミナル背景ブラシ]
    F --> I[UIに適用]
    G --> I
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-107-1 | デフォルトテーマ | WindowThemeが未定義の場合はElementTheme::Defaultを返却 | RequestedTheme取得時 |
| BR-107-2 | アクセントカラー取得 | タイトルバー用は DWM レジストリ値、それ以外は SystemAccentColor | ThemeColor::Evaluate |
| BR-107-3 | 非フォーカスタブ透明度 | Accent/TerminalBackgroundは30%(=77/256)、Colorはアルファ値をそのまま使用 | UnfocusedTabOpacity |
| BR-107-4 | ThemePair同名最適化 | DarkNameとLightNameが同一の場合、JSON出力時は文字列として簡略化 | ThemePair::ToJson |
| BR-107-5 | ダークモード検出 | 前景色の輝度判定式: (5*G + 2*R + B) > (8*128) | IsSystemInDarkTheme |

### 計算ロジック

- **輝度判定式**: `(5 * G + 2 * R + B) > (8 * 128)` で前景色が明るいか（=ダークモード）を判定
- **非フォーカスタブ透明度**: Accent/TerminalBackground時は `77` (= 0.3 * 256)

## データベース操作仕様

本機能はデータベースを使用しない。settings.jsonファイルで永続化される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | JSON null | サブテーマがnull | nullptrを返却 |
| - | レジストリ読み取り失敗 | DWMキーが存在しない | LOG_IF_FAILEDでログ出力、デフォルト値使用 |

### リトライ仕様

リトライは不要。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- テーマカラーの評価はUI描画時に呼ばれるため、低レイテンシが求められる
- レジストリアクセスは起動時または設定変更時のみ発生

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

- レジストリアクセスはHKEY_CURRENT_USERのREADのみ

## 備考

- マクロ `MTSM_THEME_SETTINGS`, `MTSM_THEME_WINDOW_SETTINGS` 等でプロパティを一括定義している
- `THEME_OBJECT` マクロにより WindowTheme, TabRowTheme, TabTheme, SettingsTheme の Copy/ToJson が自動生成される
- `THEME_OBJECT_CONVERTER` マクロにより各サブテーマの JSON 変換トレイトが自動生成される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Theme.h | `src/cascadia/TerminalSettingsModel/Theme.h` | ThemePair(33-51行目)、ThemeColor(53-70行目)、各サブテーマオブジェクト(84-87行目)、Theme(89-112行目) |

**読解のコツ**: `THEME_SETTINGS_INITIALIZE`マクロ(72-73行目)がWINRT_PROPERTYに展開される。`THEME_OBJECT`マクロ(75-82行目)でWindowTheme等のクラスが自動生成されるため、マクロ展開後の構造を理解すること。ThemeColor::ColorTypeの3種類（Color, Accent, TerminalBackground）がテーマの色指定の核となる。

#### Step 2: 色評価ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Theme.cpp | `src/cascadia/TerminalSettingsModel/Theme.cpp` | ThemeColor::FromColor/FromAccent/FromTerminalBackground(68-88行目)、Evaluate(127-160行目)、UnfocusedTabOpacity(173-184行目) |

**主要処理フロー**:
1. **68-88行目**: ファクトリメソッドで3種類のThemeColorを生成
2. **90-112行目**: DWMレジストリからアクセントカラーを取得（openDwmRegKey, readDwmSubValue, _getAccentColorForTitlebar）
3. **127-160行目**: Evaluate関数でColorTypeに応じたXAMLブラシを生成
4. **173-184行目**: 非フォーカスタブの透明度をColorTypeに応じて返却

#### Step 3: JSON永続化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Theme.cpp | `src/cascadia/TerminalSettingsModel/Theme.cpp` | FromJson(271-293行目)、ToJson(348-363行目)、ThemePair::FromJson(381-395行目) |

**読解のコツ**: `THEME_SETTINGS_LAYER_JSON`マクロ(279-287行目)で各サブテーマをレイヤー的にパースしている。`THEME_OBJECT_CONVERTER`マクロ(194-221行目)はConversionTraitの自動生成であり、これによりJsonUtils::GetValueForKeyが各サブテーマ型を直接パースできる。

#### Step 4: ダークモード検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Theme.cpp | `src/cascadia/TerminalSettingsModel/Theme.cpp` | IsSystemInDarkTheme(422-428行目)、RequestedTheme(376-379行目) |

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

```
CascadiaSettings (設定読み込み)
    |
    +-- Theme::FromJson                     ... JSONからテーマ生成
    |       +-- JsonUtils::GetValueForKey   ... nameキー取得
    |       +-- ConversionTrait<WindowTheme>::FromJson
    |       +-- ConversionTrait<TabRowTheme>::FromJson
    |       +-- ConversionTrait<TabTheme>::FromJson
    |       +-- ConversionTrait<SettingsTheme>::FromJson
    |
    +-- ThemePair::FromJson                 ... ライト/ダーク対応
    |       +-- DarkName / LightName取得
    |
    +-- Theme::RequestedTheme              ... ElementTheme取得
    |       +-- WindowTheme::RequestedTheme
    |
    +-- ThemeColor::Evaluate               ... 色の実評価
    |       +-- Accent: _getAccentColorForTitlebar / SystemAccentColor
    |       +-- Color: SolidColorBrush生成
    |       +-- TerminalBackground: ブラシ透過
    |
    +-- Theme::IsSystemInDarkTheme         ... システムテーマ判定
            +-- UISettings::GetColorValue(Foreground)
            +-- isColorLight (輝度判定)
```

### データフロー図

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

settings.json                  Theme                          UI外観
  themes[] ---------> FromJson (デシリアライズ) ------> Themeオブジェクト
                                                             |
システムテーマ -------> IsSystemInDarkTheme -------> ThemePair選択
                                                             |
DWMレジストリ -------> _getAccentColorForTitlebar --> ThemeColor
  AccentColor                                          |
                                                       v
XAML UI <------------- ThemeColor::Evaluate <--- Brush生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Theme.h | `src/cascadia/TerminalSettingsModel/Theme.h` | ソース(ヘッダ) | テーマ関連クラスの宣言 |
| Theme.cpp | `src/cascadia/TerminalSettingsModel/Theme.cpp` | ソース(実装) | テーマのJSON変換・色評価 |
| MTSMSettings.h | `src/cascadia/TerminalSettingsModel/MTSMSettings.h` | ソース(ヘッダ) | MTSM_THEME_*マクロ定義 |
| ThemeColor.g.h | 自動生成 | 自動生成 | ThemeColorのWinRTプロジェクション |
| WindowTheme.g.h | 自動生成 | 自動生成 | WindowThemeのWinRTプロジェクション |
| TabRowTheme.g.h | 自動生成 | 自動生成 | TabRowThemeのWinRTプロジェクション |
| TabTheme.g.h | 自動生成 | 自動生成 | TabThemeのWinRTプロジェクション |
| ThemePair.g.h | 自動生成 | 自動生成 | ThemePairのWinRTプロジェクション |
| Theme.g.h | 自動生成 | 自動生成 | ThemeのWinRTプロジェクション |
