|
| 1 | +# Components |
| 2 | +<!-- metadata: type=components, audience=ai-agents, scope=all-modules --> |
| 3 | + |
| 4 | +## Application Core |
| 5 | + |
| 6 | +### MecalinApplication (`src/application.rs`) |
| 7 | +- **Parent**: `adw::Application` |
| 8 | +- **Role**: Application entry point. Registers GResource base path, loads CSS, sets keyboard shortcuts (`Ctrl+Q` quit, `Ctrl+W` close), creates the main window on activation. |
| 9 | +- **Key behavior**: `startup()` loads global CSS provider; `activate()` creates and presents `MecalinWindow`. |
| 10 | + |
| 11 | +### MecalinWindow (`src/window.rs`) |
| 12 | +- **Parent**: `adw::ApplicationWindow` |
| 13 | +- **Role**: Main window and navigation hub. Contains `adw::NavigationView` with `ActionRow` entries for each feature. |
| 14 | +- **Template children**: `header_bar`, `window_title`, `navigation_view`, plus rows for lessons, speed test, falling keys, scrolling lanes, preferences, about. |
| 15 | +- **Key behavior**: Each row's `activated` signal pushes the corresponding navigation page by tag. Persists window size/maximized state via GSettings. |
| 16 | + |
| 17 | +## Feature Views |
| 18 | + |
| 19 | +### LessonView (`src/lesson_view.rs`) |
| 20 | +- **Parent**: `adw::NavigationPage` |
| 21 | +- **Role**: Structured typing lessons with step-by-step progression. The most complex view. |
| 22 | +- **Contains**: `TypingRow`, `KeyboardWidget`, `HandWidget` |
| 23 | +- **Key behavior**: Loads a `Course` based on locale, tracks current lesson/step/repetition via GSettings, highlights relevant keys on the keyboard, shows hand position guidance, advances through steps on completion, shows `CourseCompletionView` when all lessons are done. |
| 24 | +- **Properties**: `current_lesson` (boxed), `current_step_index` (u32) |
| 25 | + |
| 26 | +### SpeedTestView (`src/speed_test_view.rs`) |
| 27 | +- **Parent**: `adw::NavigationPage` |
| 28 | +- **Role**: Timed typing speed tests with configurable duration. |
| 29 | +- **Contains**: `SpeedTestTextView`, `SpeedTestResultsView` |
| 30 | +- **Key behavior**: Generates random text via `text_generation`, starts a timer, tracks progress, shows results (WPM, accuracy, duration) on completion or timeout. |
| 31 | + |
| 32 | +### FallingKeysGame (`src/falling_keys_game.rs`) |
| 33 | +- **Parent**: `adw::NavigationPage` |
| 34 | +- **Role**: Gamified typing practice where keys fall from the top of the screen. |
| 35 | +- **Contains**: `FallingKeysWidget` (custom painted widget), `KeyboardWidget` |
| 36 | +- **Key behavior**: Game loop spawns falling key characters, player must type them before they reach the bottom. Tracks score and lives. Uses `glib::timeout_add_local` for the game loop. |
| 37 | +- **Inner types**: `FallingKey` (position, character, speed), `FallingKeysWidget` (custom snapshot rendering) |
| 38 | + |
| 39 | +### ScrollingLanesGame (`src/scrolling_lanes_game.rs`) |
| 40 | +- **Parent**: `adw::NavigationPage` |
| 41 | +- **Role**: Gamified typing practice with text scrolling across lanes. |
| 42 | +- **Contains**: `LaneWidget` (custom painted widget), `KeyboardWidget` |
| 43 | +- **Key behavior**: Multiple lanes with scrolling text that must be typed. Uses `glib::timeout_add_local` for animation. Tracks score and lives. |
| 44 | +- **Inner types**: `ScrollingText` (text, position, lane), `LaneWidget` (custom snapshot rendering) |
| 45 | + |
| 46 | +### PreferencesView (`src/preferences_view.rs`) |
| 47 | +- **Parent**: `adw::NavigationPage` |
| 48 | +- **Role**: User settings for hand widget visibility, keyboard widget visibility, finger colors, and lesson selection. |
| 49 | +- **Key behavior**: Binds `adw::SwitchRow` widgets directly to GSettings keys. Populates lesson combo from `Course` data. |
| 50 | + |
| 51 | +### AboutView (`src/about_view.rs`) |
| 52 | +- **Parent**: `adw::NavigationPage` |
| 53 | +- **Role**: Application information, credits, and links. |
| 54 | + |
| 55 | +### CourseCompletionView (`src/course_completion_view.rs`) |
| 56 | +- **Parent**: `adw::NavigationPage` |
| 57 | +- **Role**: Congratulatory view shown when all lessons in a course are completed. |
| 58 | + |
| 59 | +## Reusable Widgets |
| 60 | + |
| 61 | +### TypingRow (`src/typing_row.rs`) |
| 62 | +- **Parent**: `adw::PreferencesRow` |
| 63 | +- **Role**: Core text input widget used in `LessonView`. Shows target text, captures typed input, validates character-by-character. |
| 64 | +- **Signals**: `mistake-made(bool)`, `step-completed`, `next-char-changed(String)`, `dead-key-started` |
| 65 | +- **Key behavior**: Locks cursor to end position, validates each keystroke against target text, draws custom cursor overlay, detects dead key input (for accented characters). |
| 66 | + |
| 67 | +### KeyboardWidget (`src/keyboard_widget.rs`) |
| 68 | +- **Parent**: `gtk::Widget` |
| 69 | +- **Role**: Visual on-screen keyboard that highlights the current key to press and shows finger assignments. |
| 70 | +- **Key behavior**: Loads keyboard layout from JSON, custom `snapshot()` rendering of keys with color-coded fingers, supports dead key sequences (accent → base char), handles modifier keys (Shift, AltGr). |
| 71 | +- **Inner types**: `KeyboardLayout`, `KeyInfo`, `Finger`, `ModifierKey` |
| 72 | + |
| 73 | +### HandWidget (`src/hand_widget.rs`) |
| 74 | +- **Parent**: `gtk::Widget` |
| 75 | +- **Role**: Visual hand position guide showing which finger to use. |
| 76 | +- **Key behavior**: Custom `snapshot()` rendering of left/right hands with highlighted current finger. Caches theme colors and responds to dark/light mode changes. |
| 77 | + |
| 78 | +### SpeedTestTextView (`src/speed_test_text_view.rs`) |
| 79 | +- **Parent**: `adw::Bin` (composite template) |
| 80 | +- **Role**: Rich text display for speed tests with color-coded correct/incorrect characters, animated caret, and scrolling. |
| 81 | +- **Sub-modules**: `accessibility.rs`, `caret.rs`, `colors.rs`, `input.rs`, `scrolling.rs` |
| 82 | +- **Key behavior**: Manages original vs typed text comparison, renders colored text via GTK TextBuffer tags, animates caret position, handles IME input, auto-scrolls as user types. |
| 83 | +- **Signals**: `typed-text-changed`, `push-original-text`, `set-original-text` |
| 84 | + |
| 85 | +### SpeedTestResultsView (`src/speed_test_results_view.rs`) |
| 86 | +- **Parent**: `adw::NavigationPage` |
| 87 | +- **Role**: Displays speed test results (WPM, accuracy, duration). |
| 88 | +- **Signals**: `retry-clicked` |
| 89 | + |
| 90 | +## Data & Utility Modules |
| 91 | + |
| 92 | +### Course (`src/course.rs`) |
| 93 | +- **Role**: Data model for structured typing lessons. Loads lesson JSON files based on language. |
| 94 | +- **Types**: `Course`, `Lesson`, `LessonStep`, `LessonsData` |
| 95 | +- **Key behavior**: `new_with_language()` loads embedded JSON via `include_str!`. Falls back to US English for unknown languages. |
| 96 | + |
| 97 | +### text_generation (`src/text_generation.rs`) |
| 98 | +- **Role**: Generates random typing text from embedded word lists. |
| 99 | +- **Types**: `Language` (enum with 30+ variants), `Punctuation` |
| 100 | +- **Key behavior**: Loads word lists via `include_dir!`, generates text with configurable difficulty (simple/advanced), supports punctuation insertion, uppercase, and wrapping. |
| 101 | + |
| 102 | +### text_utils (`src/text_utils.rs`) |
| 103 | +- **Role**: Text validation, WPM calculation, and character comparison utilities. |
| 104 | +- **Types**: `GraphemeState` (Correct/Unfinished/Mistake) |
| 105 | +- **Key behavior**: Grapheme-level validation with Unicode support, handles character aliases (æ→ae, guillemets→quotes, non-breaking spaces), calculates WPM from correct graphemes. |
| 106 | + |
| 107 | +### typing_test_utils (`src/typing_test_utils.rs`) |
| 108 | +- **Role**: Speed test configuration and result summary types. |
| 109 | +- **Types**: `TestConfig`, `TestDuration`, `TestSummary`, `GeneratedTestDifficulty` |
| 110 | + |
| 111 | +### utils (`src/utils.rs`) |
| 112 | +- **Role**: Locale detection, Unicode decomposition, and key extraction utilities. |
| 113 | +- **Key functions**: `language_from_locale()` (maps LANG env var to language code), `decompose_with_spacing_accent()` (for dead key handling), `extract_keys()` (unique characters from text). |
0 commit comments