# 画面設計書 13-検索オーバーレイ

## 概要

本ドキュメントは、Ghosttyアプリケーションの検索オーバーレイの設計仕様を定義する。検索オーバーレイは、ターミナル内のテキスト検索を行うためのGTK専用オーバーレイUIであり、検索入力、マッチ数表示、前後マッチへのナビゲーション、ドラッグによる位置変更機能を提供する。

### 本画面の処理概要

検索オーバーレイは、ターミナル画面上にフローティング表示され、ユーザーが入力したテキストに一致する箇所をリアルタイムで検索・ハイライト表示する画面である。

**業務上の目的・背景**：ターミナルエミュレータの利用者が大量の出力ログやコマンド履歴から特定のテキストを素早く検索するために必要な機能である。コマンド出力やログの中から特定のエラーメッセージやパターンを探す際に、視覚的なフィードバックを提供し、作業効率を向上させる。GTK版（Linux）専用の実装であり、libadwaitaのウィジェットを使用してGNOMEデスクトップに統合された外観を提供する。

**画面へのアクセス方法**：
1. キーボードショートカット（Ctrl+F または設定されたキーバインド）で検索オーバーレイを表示
2. コマンドパレットから検索コマンドを実行
3. メニューから「Find」を選択

**主要な操作・処理内容**：
1. 検索テキストの入力（SearchEntry）
2. リアルタイム検索とマッチ数の更新
3. 現在のマッチ位置の表示（例：「3/15」）
4. 上矢印ボタンまたはShift+Enterで前のマッチへ移動
5. 下矢印ボタンまたはEnterで次のマッチへ移動
6. 閉じるボタンまたはEscapeで検索終了
7. ドラッグで画面の四隅に位置変更（halign/valignの切り替え）

**画面遷移**：
- 遷移元：メインターミナルウィンドウ（キーボードショートカット、メニュー、コマンドパレットから）
- 遷移先：なし（オーバーレイを閉じてメインターミナルに戻る）

**権限による表示制御**：権限による制御は存在しない。すべてのユーザーが同一の機能を利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 66 | テキスト検索 | 主機能 | ターミナル内テキスト検索のUI表示 |
| 67 | 正規表現検索 | 補助機能 | 正規表現によるパターン検索 |

## 画面種別

オーバーレイ（フローティングUI）

## URL/ルーティング

GTKネイティブアプリケーションのため、URLルーティングは存在しない。SearchOverlayウィジェットのactiveプロパティをtrueに設定することで表示される。

## 入出力項目

| 項目名 | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| 検索テキスト | 入力 | String | Yes | 検索対象のテキスト（SearchEntry） |

## 表示項目

| 項目名 | データ型 | ソース | 説明 |
|--------|----------|--------|------|
| 検索入力フィールド | GtkSearchEntry | ユーザー入力 | プレースホルダー「Find...」 |
| マッチ数ラベル | String | 計算値 | 「{selected+1}/{total}」形式（例：「3/15」） |
| 前のマッチボタン | GtkButton | - | 「go-up-symbolic」アイコン |
| 次のマッチボタン | GtkButton | - | 「go-down-symbolic」アイン |
| 閉じるボタン | GtkButton | - | 「window-close-symbolic」アイコン |

## イベント仕様

### 1-検索テキスト変更（search-changed）

SearchEntryのsearch-changedシグナルが発火し、searchChanged関数（323-326行目）が呼び出される。入力テキストを引数としてsearch-changedシグナルをemitし、ターミナルの検索処理をトリガーする。

### 2-検索停止（stop-search）

ESCキー押下またはSearchEntryのstop-searchシグナルで、stopSearch関数（331-333行目）が呼び出される。stop-searchシグナルをemitし、オーバーレイを非表示にする。

### 3-次のマッチ（next-match）

Enterキー押下または下矢印ボタンクリックで、nextMatch関数（335-337行目）が呼び出される。next-matchシグナルをemitし、次のマッチ位置にスクロールする。

### 4-前のマッチ（previous-match）

Shift+Enterキー押下または上矢印ボタンクリックで、previousMatch関数（339-341行目）が呼び出される。previous-matchシグナルをemitし、前のマッチ位置にスクロールする。

### 5-Enterキー押下（search_entry_key_pressed）

EventControllerKeyのkey-pressedシグナルで、searchEntryKeyPressed関数（343-361行目）が呼び出される。Shiftキーの状態に応じてnext-matchまたはprevious-matchシグナルをemitする。

### 6-ドラッグ終了（onDragEnd）

GestureDragのdrag-endシグナルで、onDragEnd関数（363-404行目）が呼び出される。ドラッグ終了位置に基づいてhalign_target/valign_targetを更新し、オーバーレイの表示位置を四隅のいずれかに移動する。

### 7-閉じるボタン押下

閉じるボタンのclickedシグナルでstop_searchテンプレートコールバックが呼び出され、検索を終了する。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | データベース操作なし（メモリ内検索のみ） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-01 | プレースホルダー | Find... | 検索フィールドが空の時 |
| MSG-02 | 情報 | 0/0 | マッチなしの時 |
| MSG-03 | 情報 | {n}/{total} | マッチありの時 |

## 例外処理

| 例外状態 | 画面の振る舞い |
|---------|---------------|
| マッチなし | ラベルに「0/0」を表示 |
| 検索テキストが空 | ラベルに「0/0」を表示、ハイライトなし |
| 正規表現エラー | 現在の実装では特別な処理なし（空マッチとして扱う） |

## 備考

- GTK専用画面（macOSでは別の検索実装を使用）
- libadwaita (Adw.Bin) をベースにした実装
- Blueprintテンプレート（search-overlay.blp）でUI定義
- halign-target/valign-targetプロパティで四隅への配置を制御
- デフォルト位置は右上（halign: end, valign: start）
- ドラッグで位置変更可能、親コンテナの中央を境界として自動的に最寄りの隅に移動
- マッチラベルは固定幅6文字（width-chars: 6）で右寄せ表示

---

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

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

### 推奨読解順序

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

Privateストラクチャが検索状態（アクティブ状態、マッチ数、選択位置、配置方向）を管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | search_overlay.zig | `src/apprt/gtk/class/search_overlay.zig` | Private構造体（207-227行目）のフィールド定義 |

**読解のコツ**: Zigのextern structとGObjectの統合を理解すること。privateメンバーはoffsetを通じてアクセスされ、GObjectのプロパティシステムと連携する。

#### Step 2: UIテンプレートを理解する

Blueprintテンプレートがウィジェット構成を定義する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | search-overlay.blp | `src/apprt/gtk/ui/1.2/search-overlay.blp` | テンプレート全体構成（94行） |

**主要処理フロー**:
1. **5-11行目**: テンプレートプロパティのバインディング定義
2. **12-16行目**: GestureDragの設定
3. **28-41行目**: SearchEntryの定義とシグナル接続
4. **44-52行目**: マッチ数ラベルのクロージャバインディング
5. **54-81行目**: ナビゲーションボタンの定義
6. **83-91行目**: 閉じるボタンの定義

#### Step 3: プロパティ定義を理解する

GObjectプロパティがビューと状態を結びつける。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | search_overlay.zig | `src/apprt/gtk/class/search_overlay.zig` | propertiesブロック（37-155行目）のプロパティ定義 |

**主要処理フロー**:
- **38-56行目**: activeプロパティ - オーバーレイの表示/非表示を制御
- **58-75行目**: search-totalプロパティ - 検索マッチ総数
- **94-111行目**: search-selectedプロパティ - 現在選択中のマッチインデックス
- **130-155行目**: halign-target/valign-targetプロパティ - 配置位置

#### Step 4: シグナル定義を理解する

シグナルが検索イベントを外部コンポーネントに通知する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | search_overlay.zig | `src/apprt/gtk/class/search_overlay.zig` | signalsブロック（157-205行目）のシグナル定義 |

**主要処理フロー**:
- **159-168行目**: stop-searchシグナル - 検索終了通知
- **170-180行目**: search-changedシグナル - 検索テキスト変更通知
- **182-192行目**: next-matchシグナル - 次マッチ移動通知
- **194-204行目**: previous-matchシグナル - 前マッチ移動通知

#### Step 5: イベントハンドラを理解する

テンプレートコールバックがユーザー操作を処理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | search_overlay.zig | `src/apprt/gtk/class/search_overlay.zig` | テンプレートコールバック（323-404行目） |

**主要処理フロー**:
- **323-326行目**: searchChanged - テキスト変更時の処理
- **331-333行目**: stopSearch - ESC押下時の処理
- **335-341行目**: nextMatch/previousMatch - ナビゲーション処理
- **343-361行目**: searchEntryKeyPressed - Enter/Shift+Enter処理
- **363-404行目**: onDragEnd - ドラッグによる位置変更処理

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

```
SearchOverlay (GObject/AdwBin)
    │
    ├─ properties
    │      ├─ active ─────────────▶ visible (Blueprintバインド)
    │      ├─ search-total ───────▶ match_label_closure
    │      ├─ has-search-total ───▶ match_label_closure
    │      ├─ search-selected ────▶ match_label_closure
    │      ├─ has-search-selected ─▶ match_label_closure
    │      ├─ halign-target ──────▶ halign (Blueprintバインド)
    │      └─ valign-target ──────▶ valign (Blueprintバインド)
    │
    ├─ signals
    │      ├─ stop-search ────────▶ Surface検索停止
    │      ├─ search-changed ─────▶ Surface検索実行
    │      ├─ next-match ─────────▶ Surface次マッチ移動
    │      └─ previous-match ─────▶ Surface前マッチ移動
    │
    ├─ SearchEntry
    │      ├─ stop-search ────────▶ stopSearch()
    │      ├─ search-changed ─────▶ searchChanged()
    │      ├─ next-match ─────────▶ nextMatch()
    │      ├─ previous-match ─────▶ previousMatch()
    │      └─ EventControllerKey ─▶ searchEntryKeyPressed()
    │
    ├─ Buttons
    │      ├─ prev_button (clicked) ─▶ nextMatch()
    │      ├─ next_button (clicked) ─▶ previousMatch()
    │      └─ close_button (clicked) ─▶ stopSearch()
    │
    └─ GestureDrag
           └─ drag-end ──────────▶ onDragEnd()
```

### データフロー図

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

User Input                    SearchOverlay                       Signals
- キー入力         ───▶       - searchChanged()      ───▶         - search-changed
- Enter押下                   - searchEntryKeyPressed()            - next-match
- Shift+Enter                 - nextMatch()                        - previous-match
- ESC押下                     - previousMatch()                    - stop-search
- ボタンクリック              - stopSearch()

Surface                       SearchOverlay                       UI
- setSearchTotal()  ───▶      - Private.search_total  ───▶       - Label更新
- setSearchSelected()         - Private.search_selected           - "n/total"
                              - closureMatchLabel()

Drag Gesture                  SearchOverlay                       Layout
- ドラッグ操作      ───▶      - onDragEnd()          ───▶        - halign更新
                              - halign_target更新                  - valign更新
                              - valign_target更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| search_overlay.zig | `src/apprt/gtk/class/search_overlay.zig` | ソース | 検索オーバーレイウィジェット本体 |
| search-overlay.blp | `src/apprt/gtk/ui/1.2/search-overlay.blp` | テンプレート | BlueprintによるUI定義 |
| surface.zig | `src/apprt/gtk/class/surface.zig` | ソース | 検索オーバーレイを含むSurfaceウィジェット |
| gresource.zig | `src/apprt/gtk/build/gresource.zig` | ソース | GResourceパス生成ユーティリティ |
| class.zig | `src/apprt/gtk/class.zig` | ソース | Common型変換ユーティリティ |
