pub struct EditorEngine { /* private fields */ }Expand description
UI-agnostic editor engine for cached layout, frame production, and hit tests.
One engine retains unbounded per-paragraph layout/metrics maps, the last complete frame, and a wrapping frame counter. It is not synchronized for concurrent use and should normally be owned by one editor view.
§Examples
use ailloli_ui_editor::EditorEngine;
let mut engine = EditorEngine::new();
engine.clear_caches();Implementations§
Source§impl EditorEngine
Produces frames and queries their retained geometry.
impl EditorEngine
Produces frames and queries their retained geometry.
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty engine with frame counter zero.
§Examples
use ailloli_ui_editor::EditorEngine;
let engine = EditorEngine::new();
assert_eq!(format!("{engine:?}").contains("frame_id: 0"), true);Sourcepub fn clear_caches(&mut self)
pub fn clear_caches(&mut self)
Clears paragraph layout and metric caches.
The retained last frame, wrapping frame ID, and the caller-owned
[TextSystem] cache are not cleared.
§Examples
use ailloli_ui_editor::EditorEngine;
let mut engine = EditorEngine::new();
engine.clear_caches();Sourcepub fn frame(
&mut self,
session: &EditorSession,
bounds: Rect,
focused: bool,
text_system: &mut TextSystem,
) -> EditorFrame
pub fn frame( &mut self, session: &EditorSession, bounds: Rect, focused: bool, text_system: &mut TextSystem, ) -> EditorFrame
Builds a generic editor frame at blink time zero.
A focused caret is therefore in its visible phase. The returned frame is cloned into the engine as its only cached frame, and its ID increments with wrapping arithmetic.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = EditorSession::new(TextBuffer::from_string("hello"));
let bounds = Rect::new(0.0, 0.0, 100.0, 50.0);
let frame = EditorEngine::new().frame(&session, bounds, true, &mut TextSystem::new());
assert_eq!(frame.viewport.bounds, bounds);
assert_eq!(frame.debug_metrics.frame_id, 1);Sourcepub fn frame_at(
&mut self,
session: &EditorSession,
bounds: Rect,
focused: bool,
frame_time_ms: u128,
text_system: &mut TextSystem,
) -> EditorFrame
pub fn frame_at( &mut self, session: &EditorSession, bounds: Rect, focused: bool, frame_time_ms: u128, text_system: &mut TextSystem, ) -> EditorFrame
Builds a generic frame at an explicit millisecond blink time.
frame_time_ms controls only caret blink phase. Layout timing is measured
independently in microseconds and saturates at u64::MAX.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{EditorEngine, EditorPaintItem, EditorSession};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = EditorSession::new(TextBuffer::from_string("x"));
let frame = EditorEngine::new().frame_at(&session, Rect::new(0.0, 0.0, 80.0, 40.0), true, 500, &mut TextSystem::new());
assert!(!frame.paint_items.iter().any(|item| matches!(item, EditorPaintItem::Caret { .. })));Sourcepub fn code_frame(
&mut self,
session: &CodeEditorSession,
bounds: Rect,
focused: bool,
text_system: &mut TextSystem,
) -> EditorFrame
pub fn code_frame( &mut self, session: &CodeEditorSession, bounds: Rect, focused: bool, text_system: &mut TextSystem, ) -> EditorFrame
Builds a code-editor frame at blink time zero.
The engine consumes the session’s current tokens, folds, search results, and diagnostics without refreshing them. It adds the configured gutter, code layers, and enabled scrollbars to the generic paint model.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{CodeEditorConfig, CodeEditorSession, Document, DocumentId, EditorEngine};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = CodeEditorSession::new(Document::new(DocumentId(1), TextBuffer::from_string("code")), CodeEditorConfig::default());
let frame = EditorEngine::new().code_frame(&session, Rect::new(0.0, 0.0, 140.0, 60.0), false, &mut TextSystem::new());
assert!(frame.viewport.gutter_rect.is_some());Sourcepub fn code_frame_at(
&mut self,
session: &CodeEditorSession,
bounds: Rect,
focused: bool,
frame_time_ms: u128,
text_system: &mut TextSystem,
) -> EditorFrame
pub fn code_frame_at( &mut self, session: &CodeEditorSession, bounds: Rect, focused: bool, frame_time_ms: u128, text_system: &mut TextSystem, ) -> EditorFrame
Builds a code-editor frame at an explicit millisecond blink time.
Gutter fold markers control whether folded lines are filtered at all;
other crate::CodeEditorFeatureFlags are descriptive configuration and
are not consulted by this frame builder.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{CodeEditorConfig, CodeEditorSession, Document, DocumentId, EditorEngine};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = CodeEditorSession::new(Document::new(DocumentId(1), TextBuffer::from_string("x")), CodeEditorConfig::default());
let frame = EditorEngine::new().code_frame_at(&session, Rect::new(0.0, 0.0, 140.0, 60.0), true, 0, &mut TextSystem::new());
assert_eq!(frame.debug_metrics.frame_id, 1);Sourcepub fn hit_test(
&mut self,
session: &EditorSession,
bounds: Rect,
pos: Point,
text_system: &mut TextSystem,
) -> EditorHitTest
pub fn hit_test( &mut self, session: &EditorSession, bounds: Rect, pos: Point, text_system: &mut TextSystem, ) -> EditorHitTest
Builds a fresh unfocused frame and hit-tests a screen point.
The new frame replaces last_frame. The returned byte is clamped to the
source buffer and follows shaped caret geometry; points outside visible
runs fall back according to crate::input::hit_test::byte_at_point.
§Examples
use ailloli_ui_core::{Point, Rect};
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = EditorSession::new(TextBuffer::from_string("abc"));
let hit = EditorEngine::new().hit_test(&session, Rect::new(0.0, 0.0, 100.0, 50.0), Point::new(12.0, 12.0), &mut TextSystem::new());
assert!(hit.byte <= 3);Sourcepub fn fold_region_hit_test_cached(
&self,
bounds: Rect,
pos: Point,
) -> Option<usize>
pub fn fold_region_hit_test_cached( &self, bounds: Rect, pos: Point, ) -> Option<usize>
Hit-tests fold markers in the retained frame.
A cached frame is eligible when every bounds component differs by less
than 0.5 logical pixel. The first marker rectangle containing the point
returns its fold-region slice index. No frame, mismatched bounds, or no
marker returns None; session identity is not part of the cache key.
§Examples
use ailloli_ui_core::{Point, Rect};
use ailloli_ui_editor::EditorEngine;
assert_eq!(EditorEngine::new().fold_region_hit_test_cached(Rect::new(0.0, 0.0, 10.0, 10.0), Point::new(1.0, 1.0)), None);Sourcepub fn hit_test_cached(
&self,
session: &EditorSession,
bounds: Rect,
pos: Point,
) -> EditorHitTest
pub fn hit_test_cached( &self, session: &EditorSession, bounds: Rect, pos: Point, ) -> EditorHitTest
Hit-tests text using the retained frame when bounds approximately match.
Cache matching ignores session identity and configuration. If no eligible
frame exists, the fallback byte is exactly session.buffer.len_bytes().
§Examples
use ailloli_ui_core::{Point, Rect};
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::from_string("abc"));
let hit = EditorEngine::new().hit_test_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0), Point::new(0.0, 0.0));
assert_eq!(hit.byte, 3);Sourcepub fn hit_test_zone_cached(
&self,
session: &EditorSession,
bounds: Rect,
pos: Point,
) -> EditorZoneHitTest
pub fn hit_test_zone_cached( &self, session: &EditorSession, bounds: Rect, pos: Point, ) -> EditorZoneHitTest
Hit-tests gutter/text/outside zone using an approximately matching frame.
Without one, returns crate::EditorHitZone::Outside at the source-buffer
end. Cache matching ignores session identity and configuration.
§Examples
use ailloli_ui_core::{Point, Rect};
use ailloli_ui_editor::{EditorEngine, EditorHitZone, EditorSession};
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::from_string("abc"));
let hit = EditorEngine::new().hit_test_zone_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0), Point::new(0.0, 0.0));
assert_eq!((hit.zone, hit.byte), (EditorHitZone::Outside, 3));Sourcepub fn caret_rect(
&mut self,
session: &EditorSession,
bounds: Rect,
text_system: &mut TextSystem,
) -> Rect
pub fn caret_rect( &mut self, session: &EditorSession, bounds: Rect, text_system: &mut TextSystem, ) -> Rect
Builds a fresh focused frame and returns display-buffer caret geometry.
IME preedit projection is included. The new frame replaces last_frame;
the returned rectangle is in screen-space logical pixels.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::{TextBuffer, TextSystem};
let session = EditorSession::new(TextBuffer::from_string("abc"));
let caret = EditorEngine::new().caret_rect(&session, Rect::new(0.0, 0.0, 100.0, 50.0), &mut TextSystem::new());
assert_eq!(caret.w, 1.0);
assert!(caret.h > 0.0);Sourcepub fn caret_rect_cached(&self, session: &EditorSession, bounds: Rect) -> Rect
pub fn caret_rect_cached(&self, session: &EditorSession, bounds: Rect) -> Rect
Returns generic caret geometry from an approximately matching frame.
Without a frame, returns a one-logical-pixel caret at the text origin with
height px_size + 2. Cache matching ignores session identity/configuration
beyond the supplied bounds.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::new());
let caret = EditorEngine::new().caret_rect_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0));
assert_eq!((caret.x, caret.y, caret.w, caret.h), (10.0, 10.0, 1.0, 15.0));Sourcepub fn code_caret_rect_cached(
&self,
session: &CodeEditorSession,
bounds: Rect,
) -> Rect
pub fn code_caret_rect_cached( &self, session: &CodeEditorSession, bounds: Rect, ) -> Rect
Returns code-editor caret geometry from an approximately matching frame.
The no-frame fallback accounts for the configured gutter and otherwise
uses the generic one-pixel, px_size + 2 caret. Cached frame matching uses
only approximate bounds, not session identity.
§Examples
use ailloli_ui_core::Rect;
use ailloli_ui_editor::{CodeEditorConfig, CodeEditorSession, Document, DocumentId, EditorEngine};
use ailloli_ui_text::TextBuffer;
let session = CodeEditorSession::new(Document::new(DocumentId(1), TextBuffer::new()), CodeEditorConfig::default());
let caret = EditorEngine::new().code_caret_rect_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0));
assert_eq!((caret.x, caret.y, caret.w, caret.h), (58.0, 10.0, 1.0, 15.0));Sourcepub fn scroll_metrics_cached(
&self,
session: &EditorSession,
bounds: Rect,
) -> ScrollMetrics
pub fn scroll_metrics_cached( &self, session: &EditorSession, bounds: Rect, ) -> ScrollMetrics
Returns generic text-viewport/content scroll metrics from the cached frame.
With no approximately matching frame, content equals viewport and the maximum offset is zero. The viewport excludes editor padding.
§Examples
use ailloli_ui_core::{Offset, Rect, Size};
use ailloli_ui_editor::{EditorEngine, EditorSession};
use ailloli_ui_text::TextBuffer;
let session = EditorSession::new(TextBuffer::new());
let metrics = EditorEngine::new().scroll_metrics_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0));
assert_eq!(metrics.viewport, Size::new(80.0, 30.0));
assert_eq!(metrics.max_offset(), Offset::new(0.0, 0.0));Sourcepub fn code_scroll_metrics_cached(
&self,
session: &CodeEditorSession,
bounds: Rect,
) -> ScrollMetrics
pub fn code_scroll_metrics_cached( &self, session: &CodeEditorSession, bounds: Rect, ) -> ScrollMetrics
Returns code text-viewport/content metrics from the cached frame.
The viewport excludes both padding and the configured gutter. With no approximately matching frame, content equals viewport.
§Examples
use ailloli_ui_core::{Rect, Size};
use ailloli_ui_editor::{CodeEditorConfig, CodeEditorSession, Document, DocumentId, EditorEngine};
use ailloli_ui_text::TextBuffer;
let session = CodeEditorSession::new(Document::new(DocumentId(1), TextBuffer::new()), CodeEditorConfig::default());
let metrics = EditorEngine::new().code_scroll_metrics_cached(&session, Rect::new(0.0, 0.0, 100.0, 50.0));
assert_eq!(metrics.viewport, Size::new(32.0, 30.0));
assert_eq!(metrics.content, metrics.viewport);Trait Implementations§
Source§impl Clone for EditorEngine
impl Clone for EditorEngine
Source§fn clone(&self) -> EditorEngine
fn clone(&self) -> EditorEngine
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more