# 機能設計書：スティッキースクロール（Sticky Scroll）

## 1. 機能概要

### 1.1 機能の目的
スティッキースクロール機能は、エディタの上部にネストされたスコープ（クラス、関数、ブロック等）のヘッダー行を固定表示する機能である。深いネスト構造のコードを編集する際に、現在のコンテキストを常に把握できるようにすることを目的とする。

### 1.2 機能の範囲
- スコープヘッダーの固定表示
- クリックによる該当行へのナビゲーション
- フォールディングアイコンとの連携
- Ctrl+クリックによる定義へ移動

### 1.3 関連画面
- エディタメインビュー（上部オーバーレイ）

## 2. 機能要件

### 2.1 ユーザーストーリー
- 開発者として、深いネストのコードでも現在のコンテキストを把握したい
- 開発者として、スティッキー行をクリックしてスコープの開始位置にジャンプしたい
- 開発者として、スティッキー行からフォールディングを操作したい

### 2.2 入力仕様
| 項目 | 説明 |
|------|------|
| ビューモデル | 現在のビューモデル |
| 設定 | enabled、maxLineCount |
| スクロール位置 | 現在のスクロール位置 |
| シンボル/フォールディング | スコープ情報 |

### 2.3 出力仕様
| 項目 | 説明 |
|------|------|
| StickyScrollWidgetState | スティッキー行の状態 |
| オーバーレイ表示 | スティッキー行のレンダリング |

### 2.4 処理フロー

```mermaid
sequenceDiagram
    participant Editor
    participant StickyScrollController
    participant StickyLineCandidateProvider
    participant StickyScrollWidget

    Editor->>StickyScrollController: onScrollChange
    StickyScrollController->>StickyLineCandidateProvider: getCandidateStickyLines()
    StickyLineCandidateProvider-->>StickyScrollController: スティッキー候補行
    StickyScrollController->>StickyScrollController: findScrollWidgetState()
    StickyScrollController->>StickyScrollWidget: setState()
    StickyScrollWidget->>Editor: オーバーレイ表示

    Note over Editor,StickyScrollWidget: クリック時
    StickyScrollWidget->>StickyScrollController: クリックイベント
    StickyScrollController->>Editor: revealPosition()
```

### 2.5 ビジネスルール
1. `editor.stickyScroll.enabled`がfalseの場合は表示しない
2. 最大表示行数は`editor.stickyScroll.maxLineCount`で制限
3. エディタ高さの25%を超えないように制限
4. 相対行番号モードではカーソル移動で再描画

## 3. 画面設計

### 3.1 画面レイアウト
スティッキースクロールはエディタの上部にオーバーレイとして表示される。

### 3.2 画面要素
| 要素 | 説明 | 操作 |
|------|------|------|
| スティッキー行 | スコープヘッダーの表示 | クリックでジャンプ |
| フォールディングアイコン | 折りたたみ操作 | クリックでトグル |
| コンテキストメニュー | 追加操作 | 右クリックで表示 |

## 4. データ設計

### 4.1 入力データ構造
```typescript
interface StickyScrollConfig {
    enabled: boolean;
    maxLineCount: number;
}

interface StickyLineCandidate {
    startLineNumber: number;
    endLineNumber: number;
    nestingDepth: number;
}
```

### 4.2 出力データ構造
```typescript
class StickyScrollWidgetState {
    static Empty: StickyScrollWidgetState;
    startLineNumbers: number[];
    endLineNumbers: number[];
    lastLineRelativePosition: number;
    showEndForLine?: number;
}

interface StickyRange {
    startLineNumber: number;
    endLineNumber: number;
}
```

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

### 5.1 推奨読解順序

1. **設定の理解**
   - `src/vs/editor/common/config/editorOptions.ts` - stickyScroll設定定義

2. **コントローラ層**
   - `src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts` - スティッキースクロール制御（**50-640行目**）
     - `StickyScrollController`クラスがスティッキースクロール処理全体を制御
     - **83-151行目**: コンストラクタでイベントハンドラ登録
     - **181-198行目**: `focus()`でフォーカス処理
     - **221-226行目**: `goToFocused()`でジャンプ処理
     - **245-406行目**: マウスイベント処理
     - **452-493行目**: `_readConfiguration()`で設定読み込み
     - **537-576行目**: `_renderStickyScroll()`でレンダリング
     - **603-634行目**: `findScrollWidgetState()`で状態計算

3. **プロバイダ層**
   - `src/vs/editor/contrib/stickyScroll/browser/stickyScrollProvider.ts` - スティッキー候補取得
     - `StickyLineCandidateProvider`がスコープ情報を提供

4. **ウィジェット層**
   - `src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts` - UI描画
     - `StickyScrollWidget`がオーバーレイ表示を管理

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

```
stickyScrollController.ts
  └── StickyScrollController
        ├── _readConfiguration()
        │     └── EditorOption.stickyScroll
        ├── _registerMouseListeners()
        │     ├── ClickLinkGesture
        │     └── goToDefinitionWithLocation()
        ├── _renderStickyScroll()
        │     └── _updateState()
        ├── findScrollWidgetState()
        │     └── StickyLineCandidateProvider.getCandidateStickyLinesIntersecting()
        └── StickyScrollWidget.setState()

stickyScrollProvider.ts
  └── StickyLineCandidateProvider
        └── getCandidateStickyLinesIntersecting()
              └── シンボル/フォールディング情報取得
```

### 5.3 データフロー図

```
[スクロールイベント]
        ↓
[_renderStickyScroll() - レンダリング開始]
        ↓
[StickyLineCandidateProvider - 候補取得]
        ↓
[findScrollWidgetState() - 状態計算]
        ↓
[StickyScrollWidgetState生成]
        ↓
[StickyScrollWidget.setState() - UI更新]
```

### 5.4 読解のコツ
- `StickyScrollController`は`IEditorContribution`を実装
- `IStickyScrollController`インターフェースで公開APIを定義
- `ClickLinkGesture`を使用してCtrl+クリックを検出
- `FoldingModel`と連携してフォールディング操作をサポート
- `EditorContextKeys.stickyScrollFocused`でフォーカス状態を管理
- エディタ高さの25%を最大表示領域として制限

### 5.5 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts` | コントローラ | スティッキースクロール制御 |
| `src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts` | ウィジェット | UI描画 |
| `src/vs/editor/contrib/stickyScroll/browser/stickyScrollProvider.ts` | プロバイダ | スティッキー候補取得 |
| `src/vs/editor/contrib/stickyScroll/browser/stickyScrollElement.ts` | データ | StickyRange等の定義 |
| `src/vs/editor/contrib/folding/browser/folding.ts` | 連携 | フォールディング連携 |
| `src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts` | ユーティリティ | クリックジェスチャ検出 |

## 6. 非機能要件

### 6.1 パフォーマンス
- スクロールイベントで効率的に再計算
- 変更された行のみ再レンダリング
- 最大表示行数の制限でメモリ使用量を抑制

### 6.2 エラーハンドリング
- モデルが大きすぎる場合は機能を無効化
- シンボルプロバイダがない場合はフォールディングにフォールバック

## 7. 設計上の考慮事項

### 7.1 拡張性
- DocumentSymbolProviderとの連携
- FoldingRangeProviderとの連携
- カスタムスティッキー候補の提供が可能

### 7.2 依存関係
- `ILanguageFeaturesService`を通じてシンボル情報にアクセス
- `FoldingController`でフォールディング連携
- `IContextMenuService`でコンテキストメニュー表示
- `IContextKeyService`でフォーカス状態管理
