- Replace gtx.Event(nil) with key.Filter{Focus: focusedID} and
key.FocusFilter{Target: focusedID} so Gio correctly routes key
and edit events to the focused editor text field.
- Convert EditorState.CursorPosition (byte offset) to line/column
coordinates for accurate cursor rendering.
- Add debug logging in HandleKeyDown and HandleCursorMove.
86 lines
4.1 KiB
Markdown
86 lines
4.1 KiB
Markdown
# Editor Implementation Plan
|
|
|
|
## 1. Design Principles
|
|
|
|
- **Single-Owner Pattern**: The logic goroutine is the exclusive authority for modifying the editor buffer, cursor, and selection state.
|
|
- **Asynchronous I/O**: File saving and loading operations are delegated to the worker pool. The UI never blocks on disk operations.
|
|
- **Buffer-Based Editing**: For performance, the editor will eventually utilize a gap buffer or rope data structure. For MVP, string manipulation is acceptable if performance targets are met.
|
|
- **Event-Driven**: Keyboard input, mouse interactions, and menu actions are passed through the existing `inputChan` to the logic goroutine.
|
|
|
|
## 2. Core State Structure
|
|
|
|
The `State` struct in `internal/editor/state.go` will be extended to track active editing session data:
|
|
|
|
```go
|
|
type EditorState struct {
|
|
Buffer string // Document content (or gap buffer)
|
|
CursorPosition int // Byte offset
|
|
SelectionStart int // -1 if no selection
|
|
SelectionEnd int // -1 if no selection
|
|
UndoStack []EditCommand // For undo/redo
|
|
Dirty bool // Needs save
|
|
}
|
|
```
|
|
|
|
## 3. Implementation Phases
|
|
|
|
### Phase 1: Basic Buffer Management & Cursor
|
|
- [ ] Define `EditorState` (Cursor, Selection, Dirty flag).
|
|
- [ ] Implement cursor navigation (Arrow keys: Left, Right, Up, Down).
|
|
- [ ] Implement basic buffer updates (Insert character, Delete/Backspace).
|
|
- [ ] Implement cursor display and blink animation.
|
|
- [ ] Update `EditorLayout` to display cursor and selection highlight.
|
|
|
|
### Phase 2: File IO Integration
|
|
- [ ] Implement `SaveFile` handler: Dispatch `WriteFileTask` to worker pool.
|
|
- [ ] Implement `LoadFile` handler: Dispatch `ReadFileTask` to worker pool (existing in `logic.go`).
|
|
- [ ] Status bar integration: Show "Saving..." indicator, "Modified" status.
|
|
|
|
### Phase 3: Text Editing Operations
|
|
- [ ] Implement Cut/Copy/Paste interactions.
|
|
- [ ] Implement multi-line text navigation (Home/End, PageUp/PageDown).
|
|
- [ ] Implement text selection display and mouse interaction.
|
|
- [ ] Implement soft-wrap toggle (already exists, need to verify logic).
|
|
|
|
### Phase 4: Polish & Advanced Features
|
|
- [ ] Undo/Redo stack implementation.
|
|
- [ ] Performance testing with large files (>1MB).
|
|
|
|
---
|
|
|
|
## 4. Interaction Flow (Example: Keyboard/Mouse Input)
|
|
|
|
1. **User** performs an action (types a character, taps an icon).
|
|
2. **UI (Renderer)** registers the element's interaction (`event.Op` for keys, `gesture.Add` for mouse) within its clip context.
|
|
3. **Main Loop** captures the event (using `key.Filter` for keys, `gesture.Update` for mouse).
|
|
4. **Main Loop** generates an `InputEvent` and sends it to `inputChan`.
|
|
5. **Logic Goroutine** receives the event, triggers the corresponding `Handler` in `TheState`.
|
|
6. **Logic Goroutine** modifies state, and sends updated elements back through `frameChan`.
|
|
7. **Renderer** paints the new frame.
|
|
|
|
---
|
|
|
|
## 5. Performance Targets
|
|
|
|
| Operation | Target | Mechanism |
|
|
|---|---|---|
|
|
| Typing latency | < 16ms | Single-owner logic update, immediate frame redraw |
|
|
| File Load (1MB) | < 100ms | Async worker pool read, background loading |
|
|
| File Save | < 100ms | Async worker pool write |
|
|
| Undo/Redo | < 10ms | O(1) or O(N) memory-based buffer update |
|
|
|
|
---
|
|
|
|
## 7. Input Handling Mechanism
|
|
|
|
### 7.1 Mouse/Touch Input
|
|
- Uses `gesture.Click` and `gesture.Scroll`.
|
|
- Registered via `event.Op` and gesture `Add()` within the clip context of the element.
|
|
- Processed by `Renderer.CheckGestures` and dispatched via `InputEvent` to the logic goroutine.
|
|
|
|
### 7.2 Keyboard Input
|
|
- **Registration**: Elements register as input handlers using `event.Op(gtx.Ops, elementID)`. This tags the current clip context for input routing.
|
|
- **Focus**: Focus is managed by the logic goroutine. When an element is focused, `key.FocusCmd{Tag: elementID}` is submitted to the operation stack.
|
|
- **Filtering**: Keyboard events are processed in the main loop using `key.Filter{Focus: focusedElementID}` to ensure events are only routed to the active element.
|
|
- **Routing**: `key.Event` (for key presses) and `key.EditEvent` (for text input) are converted into `InputEvent` structs and sent to the logic goroutine via `inputChan` for state updates.
|