Struct EditorEngine

Source
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.

Source

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);
Source

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();
Source

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);
Source

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 { .. })));
Source

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());
Source

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);
Source

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);
Source

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);
Source

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);
Source

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));
Source

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);
Source

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));
Source

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));
Source

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));
Source

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

Source§

fn clone(&self) -> EditorEngine

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EditorEngine

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for EditorEngine

Source§

fn default() -> EditorEngine

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> ErasedDestructor for T
where T: 'static,