freya-edit 0.4.0-rc.17

Text Editing APIs for Freya
use std::time::Duration;

use freya_core::prelude::*;

use crate::{
    EditableConfig,
    EditableEvent,
    TextDragging,
    editor_history::EditorHistory,
    rope_editor::RopeEditor,
    text_editor::TextSelection,
};

/// Manage an editable text.
#[derive(Clone, Copy, PartialEq)]
pub struct UseEditable {
    pub(crate) editor: State<RopeEditor>,
    pub(crate) dragging: State<TextDragging>,
    pub(crate) config: EditableConfig,
}

impl UseEditable {
    /// Manually create an editable content instead of using [use_editable].
    pub fn create(content: String, config: EditableConfig) -> Self {
        let editor = State::create(RopeEditor::new(
            content,
            TextSelection::new_cursor(0),
            config.indentation,
            EditorHistory::new(Duration::from_millis(10)),
        ));
        let dragging = State::create(TextDragging::default());

        UseEditable {
            editor,
            dragging,
            config,
        }
    }

    /// Reference to the editor.
    pub fn editor(&self) -> &State<RopeEditor> {
        &self.editor
    }

    /// Mutable reference to the editor.
    pub fn editor_mut(&mut self) -> &mut State<RopeEditor> {
        &mut self.editor
    }

    /// Process a [`EditableEvent`] event.
    pub fn process_event(&mut self, edit_event: EditableEvent) {
        edit_event.process(
            self.editor.into_writable(),
            self.dragging.into_writable(),
            &self.config,
        );
    }
}

/// Hook to create an editable text.
///
/// For manual creation use [UseEditable::create].
///
/// **This is a low level hook and is not expected to be used by the common user, in fact,
/// you might be looking for something like the `Input` component instead.**
pub fn use_editable(
    content: impl FnOnce() -> String,
    config: impl FnOnce() -> EditableConfig,
) -> UseEditable {
    use_hook(|| UseEditable::create(content(), config()))
}