use azul_core::{
dom::DomNodeId,
selection::{OptionSelectionRange, SelectionRange},
task::Instant,
window::CursorPosition,
};
use azul_css::AzString;
use crate::managers::selection::ClipboardContent;
pub type ChangesetId = usize;
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextChangeset {
pub id: ChangesetId,
pub target: DomNodeId,
pub operation: TextOperation,
pub timestamp: Instant,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpInsertText {
pub text: AzString,
pub position: CursorPosition,
pub new_cursor: CursorPosition,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpDeleteText {
pub range: SelectionRange,
pub deleted_text: AzString,
pub new_cursor: CursorPosition,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpReplaceText {
pub range: SelectionRange,
pub old_text: AzString,
pub new_text: AzString,
pub new_cursor: CursorPosition,
}
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct TextOpSetSelection {
pub old_range: OptionSelectionRange,
pub new_range: SelectionRange,
}
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct TextOpExtendSelection {
pub old_range: SelectionRange,
pub new_range: SelectionRange,
pub direction: SelectionDirection,
}
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct TextOpClearSelection {
pub old_range: SelectionRange,
}
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct TextOpMoveCursor {
pub old_position: CursorPosition,
pub new_position: CursorPosition,
pub movement: CursorMovement,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpCopy {
pub range: SelectionRange,
pub content: ClipboardContent,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpCut {
pub range: SelectionRange,
pub content: ClipboardContent,
pub new_cursor: CursorPosition,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct TextOpPaste {
pub content: ClipboardContent,
pub position: CursorPosition,
pub new_cursor: CursorPosition,
}
#[derive(Copy, Debug, Clone)]
#[repr(C)]
pub struct TextOpSelectAll {
pub old_range: OptionSelectionRange,
pub new_range: SelectionRange,
}
#[derive(Debug, Clone)]
#[repr(C, u8)]
pub enum TextOperation {
InsertText(TextOpInsertText),
DeleteText(TextOpDeleteText),
ReplaceText(TextOpReplaceText),
SetSelection(TextOpSetSelection),
ExtendSelection(TextOpExtendSelection),
ClearSelection(TextOpClearSelection),
MoveCursor(TextOpMoveCursor),
Copy(TextOpCopy),
Cut(TextOpCut),
Paste(TextOpPaste),
SelectAll(TextOpSelectAll),
}
pub use azul_core::events::SelectionDirection;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum CursorMovement {
Left,
Right,
Up,
Down,
WordLeft,
WordRight,
LineStart,
LineEnd,
DocumentStart,
DocumentEnd,
Absolute,
}
impl TextChangeset {
pub fn new(target: DomNodeId, operation: TextOperation, timestamp: Instant) -> Self {
use std::sync::atomic::{AtomicUsize, Ordering};
static CHANGESET_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
Self {
id: CHANGESET_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
target,
operation,
timestamp,
}
}
#[must_use] pub const fn mutates_text(&self) -> bool {
matches!(
self.operation,
TextOperation::InsertText { .. }
| TextOperation::DeleteText { .. }
| TextOperation::ReplaceText { .. }
| TextOperation::Cut { .. }
| TextOperation::Paste { .. }
)
}
#[must_use] pub const fn changes_selection(&self) -> bool {
matches!(
self.operation,
TextOperation::SetSelection { .. }
| TextOperation::ExtendSelection { .. }
| TextOperation::ClearSelection { .. }
| TextOperation::MoveCursor { .. }
| TextOperation::SelectAll { .. }
)
}
#[must_use] pub const fn uses_clipboard(&self) -> bool {
matches!(
self.operation,
TextOperation::Copy { .. } | TextOperation::Cut { .. } | TextOperation::Paste { .. }
)
}
#[must_use] pub const fn resulting_cursor_position(&self) -> Option<CursorPosition> {
match &self.operation {
TextOperation::InsertText(op) => Some(op.new_cursor),
TextOperation::DeleteText(op) => Some(op.new_cursor),
TextOperation::ReplaceText(op) => Some(op.new_cursor),
TextOperation::Cut(op) => Some(op.new_cursor),
TextOperation::Paste(op) => Some(op.new_cursor),
TextOperation::MoveCursor(op) => Some(op.new_position),
_ => None,
}
}
#[must_use] pub const fn resulting_selection_range(&self) -> Option<SelectionRange> {
match &self.operation {
TextOperation::SetSelection(op) => Some(op.new_range),
TextOperation::ExtendSelection(op) => Some(op.new_range),
TextOperation::SelectAll(op) => Some(op.new_range),
_ => None,
}
}
}