# 画面設計書 11-Log

## 概要

本ドキュメントは、Dear ImGuiのサンプルアプリケーション「Log」画面の設計仕様を定義する。本画面はログ出力・フィルタリング機能を持つログビューアのサンプル実装である。

### 本画面の処理概要

本画面は、アプリケーション内で発生するログメッセージを収集し、効率的に表示・管理するためのログビューア機能を提供する。

**業務上の目的・背景**：アプリケーション開発において、デバッグ情報やシステムメッセージを効率的に確認することは不可欠である。本画面は、大量のログデータを効率的にフィルタリング・表示し、開発者が問題の特定と解決を迅速に行えるようにすることを目的としている。ImGuiListClipperを使用した仮想スクロール機能により、大量のログエントリを高速に表示できる。

**画面へのアクセス方法**：Demo Windowのメニューバーから「Examples」メニューを選択し、「Log」を選択することで表示される。または、アプリケーションコード内で`ShowExampleAppLog(&show_app_log)`を呼び出すことで直接表示可能。

**主要な操作・処理内容**：
1. ログメッセージの時系列表示（自動スクロール対応）
2. テキストフィルタによるログのリアルタイム絞り込み
3. ログバッファのクリア操作
4. ログ内容のクリップボードへのコピー
5. オートスクロール機能の有効/無効切り替え

**画面遷移**：本画面はDemo Windowの「Examples」メニューから呼び出される。独立したウィンドウとして表示され、他の画面への直接的な遷移機能は持たない。ウィンドウの閉じるボタンまたはp_open変数を通じてウィンドウを閉じることができる。

**権限による表示制御**：本画面は権限による表示制御を持たない。すべてのユーザーが同一の機能にアクセス可能である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Begin | 主機能 | ログウィンドウの開始処理 |
| 25 | End | 主機能 | ログウィンドウの終了処理 |
| 26 | BeginChild | 主機能 | スクロール可能なログ領域の作成 |
| 27 | EndChild | 主機能 | 子ウィンドウの終了 |
| 84 | TextUnformatted | 主機能 | ログテキストの効率的な表示 |
| 92 | Button | 補助機能 | クリアボタン・コピーボタン等の操作ボタン |
| 96 | Checkbox | 補助機能 | オートスクロールの有効/無効切り替え |

## 画面種別

ログ表示（リアルタイムビューア）

## URL/ルーティング

N/A（ImGuiはURLベースのルーティングを持たない。`ShowExampleAppLog()`関数呼び出しによりウィンドウを表示）

## 入出力項目

| 項目名 | 型 | I/O | 必須 | 説明 |
|--------|-----|-----|------|------|
| p_open | bool* | I/O | No | ウィンドウの表示状態を制御するポインタ |
| Filter | ImGuiTextFilter | I | No | ログのフィルタリング文字列 |
| AutoScroll | bool | I | No | オートスクロールの有効/無効 |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ログテキスト | string | タイムスタンプ付きのログメッセージ（複数行） |
| フィルタ入力 | string | ログを絞り込むためのフィルタ文字列 |
| バッファ情報 | string | 現在のバッファ内の行数とバイト数 |

## イベント仕様

### 1-Optionsボタン押下

Optionsボタンをクリックするとポップアップメニューが開き、「Auto-scroll」チェックボックスが表示される。チェックボックスの状態を切り替えることでオートスクロール機能を有効/無効にできる。

### 2-Clearボタン押下

ログバッファをクリアし、すべてのログメッセージを削除する。LineOffsetsベクターもリセットされ、先頭のオフセット0のみが残る。

### 3-Copyボタン押下

`ImGui::LogToClipboard()`を呼び出し、現在表示されているログ内容をシステムクリップボードにコピーする。

### 4-フィルタ入力

Filter入力欄にテキストを入力すると、リアルタイムでログメッセージがフィルタリングされる。フィルタに一致する行のみが表示される。

### 5-デバッグエントリ追加

「[Debug] Add 5 entries」ボタンを押下すると、サンプルのログエントリが5件追加される。カテゴリ（info, warn, error）とランダムな単語を含むログメッセージが生成される。

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

本画面はデータベースを使用しない。ログデータはメモリ上のImGuiTextBufferに保持される。

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

N/A（データベースアクセスなし）

### メモリバッファ操作詳細

| 操作 | 対象バッファ | 操作種別 | 概要 |
|-----|-------------|---------|------|
| AddLog | Buf (ImGuiTextBuffer) | APPEND | ログメッセージをバッファ末尾に追加 |
| AddLog | LineOffsets (ImVector<int>) | APPEND | 改行位置のオフセットを記録 |
| Clear | Buf | CLEAR | バッファ全体をクリア |
| Clear | LineOffsets | RESET | オフセット配列をリセット（先頭0のみ） |

## メッセージ仕様

本画面は固定のメッセージを表示しない。ログメッセージはAddLog()メソッドを通じて動的に追加される。

## 例外処理

| 状態 | 処理内容 |
|------|----------|
| ウィンドウ非表示時 | Begin()がfalseを返した場合、End()を呼び出して即座にリターン |
| フィルタ有効時 | ImGuiListClipperを使用せず、全行をスキャンしてフィルタに一致する行のみを表示 |
| 大量ログ表示時 | ImGuiListClipperによる仮想スクロールで表示行のみをレンダリング |

## 備考

- ExampleAppLogクラスは再利用可能なログ表示コンポーネントとして設計されている
- ImGuiTextBufferは動的に拡張可能なテキストバッファで、大量のログデータを効率的に保持できる
- ImGuiListClipperを使用することで、数万行のログでも高速に表示できる
- フィルタ使用時はランダムアクセスができないため、クリッパーを使用せずに全行をスキャンする

---

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

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

### 推奨読解順序

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

まず、ログデータを管理するExampleAppLog構造体を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAppLog構造体（9213-9334行）のメンバ変数とメソッドを確認 |

**読解のコツ**: ImGuiTextBufferはchar配列を内部で管理し、appendfv()で書式付き文字列を追加できる。LineOffsetsは各行の開始オフセットを保持し、効率的な行単位アクセスを可能にする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_demo.cpp | `imgui_demo.cpp` | ShowExampleAppLog()関数（9337-9365行）がエントリーポイント |

**主要処理フロー**:
1. **9344行**: SetNextWindowSizeでウィンドウの初期サイズを設定
2. **9345行**: Begin()でウィンドウを開始（追加呼び出しで同一ウィンドウに内容を追加）
3. **9347-9355行**: デバッグ用のログ追加ボタン処理
4. **9358行**: log.Draw()を呼び出してログの描画を委譲

#### Step 3: ログ描画処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAppLog::Draw()メソッド（9245-9333行） |

**主要処理フロー**:
- **9247-9251行**: ウィンドウが非表示の場合は早期リターン
- **9254-9258行**: オプションポップアップメニューの処理
- **9261-9268行**: 操作ボタン（Options, Clear, Copy）とフィルタ入力の配置
- **9272-9331行**: スクロール可能な子ウィンドウでログを表示
- **9282-9323行**: フィルタの有無で表示ロジックを分岐（ListClipper使用/不使用）

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

```
ShowExampleAppLog(bool* p_open)
    |
    +-- ImGui::SetNextWindowSize()
    |
    +-- ImGui::Begin("Example: Log", p_open)
    |
    +-- ImGui::SmallButton("[Debug] Add 5 entries")
    |       |
    |       +-- log.AddLog()  // 5回呼び出し
    |
    +-- log.Draw("Example: Log", p_open)
            |
            +-- ImGui::Begin() / ImGui::End()
            |
            +-- ImGui::BeginPopup("Options")
            |       +-- ImGui::Checkbox("Auto-scroll")
            |
            +-- ImGui::Button("Options") -> ImGui::OpenPopup()
            +-- ImGui::Button("Clear") -> Clear()
            +-- ImGui::Button("Copy") -> ImGui::LogToClipboard()
            +-- Filter.Draw("Filter")
            |
            +-- ImGui::BeginChild("scrolling")
                    |
                    +-- [フィルタ有効時]
                    |       +-- Filter.PassFilter() で各行チェック
                    |       +-- ImGui::TextUnformatted() で表示
                    |
                    +-- [フィルタ無効時]
                            +-- ImGuiListClipper で表示範囲を限定
                            +-- ImGui::TextUnformatted() で表示
```

### データフロー図

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

ログメッセージ ---------> AddLog()
(const char* fmt, ...)    |
                          +-> Buf.appendfv()  ----------> テキストバッファに追加
                          +-> LineOffsets更新 ---------> オフセット配列に追加

フィルタ文字列 ---------> Filter.PassFilter()
                          |
                          +-> 行単位でマッチング -------> 表示/非表示判定

表示要求 ---------------> Draw()
                          |
                          +-> BeginChild() ------------> スクロール領域作成
                          +-> TextUnformatted() -------> 画面にログ表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | ExampleAppLog構造体とShowExampleAppLog()関数を含むデモ実装 |
| imgui.h | `imgui.h` | ヘッダー | ImGuiTextBuffer, ImGuiTextFilter, ImGuiListClipperの定義 |
| imgui.cpp | `imgui.cpp` | ソース | ImGui::Begin/End, BeginChild/EndChild, TextUnformattedの実装 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | Button, Checkbox等のウィジェット実装 |
