Skip to content
Snippets Groups Projects
focus.rs 3.03 KiB
Newer Older
//! Manages the [`FocusedWidget`] resource
//!
//! Makes sure that the focused widget has a [`CosmicEditor`] component
//! if its focused

use crate::prelude::*;
/// System set for focus systems. Runs in `PostUpdate`
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
Caleb Yates's avatar
Caleb Yates committed
pub(crate) struct FocusSet;
pub(crate) struct FocusPlugin;

impl Plugin for FocusPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(
            PostUpdate,
            (drop_editor_unfocused, add_editor_to_focused)
                .chain()
                .in_set(FocusSet),
        .init_resource::<FocusedWidget>()
        .register_type::<FocusedWidget>();
sam edelsten's avatar
sam edelsten committed
/// Resource struct that keeps track of the currently active editor entity.
Caleb Yates's avatar
Caleb Yates committed
///
/// The focussed entity must have a [`CosmicEditBuffer`], and should have a
/// [`CosmicEditor`] component as well if it can be mutated (i.e. isn't [`Readonly`]).
#[derive(Resource, Reflect, Default, Deref, DerefMut)]
#[reflect(Resource)]
sam edelsten's avatar
sam edelsten committed
pub struct FocusedWidget(pub Option<Entity>);

Caleb Yates's avatar
Caleb Yates committed
/// Adds [`CosmicEditor`] by copying from existing [`CosmicEditBuffer`].
sam edelsten's avatar
sam edelsten committed
pub(crate) fn add_editor_to_focused(
    mut commands: Commands,
    active_editor: Res<FocusedWidget>,
Caleb Yates's avatar
Caleb Yates committed
    q: Query<&CosmicEditBuffer, Without<CosmicEditor>>,
sam edelsten's avatar
sam edelsten committed
) {
    if let Some(e) = active_editor.0 {
        let Ok(buffer) = q.get(e) else {
sam edelsten's avatar
sam edelsten committed
            return;
        };
        let editor = CosmicEditor::clone_from_buffer(buffer);
        trace!("Adding editor to focused widget");
        commands.entity(e).insert(editor);
Caleb Yates's avatar
Caleb Yates committed
/// Removes [`CosmicEditor`]
sam edelsten's avatar
sam edelsten committed
pub(crate) fn drop_editor_unfocused(
    mut commands: Commands,
    active_editor: Res<FocusedWidget>,
Caleb Yates's avatar
Caleb Yates committed
    mut q: Query<(Entity, &mut CosmicEditBuffer, &CosmicEditor)>,
sam edelsten's avatar
sam edelsten committed
) {
    match active_editor.0 {
        None => {
            for (e, mut buffer, editor) in q.iter_mut() {
                // buffer.lines = editor.with_buffer(|buf| buf.lines.clone());
                // buffer.set_redraw(true);
                *buffer = CosmicEditBuffer::from_downgrading_editor(editor);
                trace!("Removing editor from all entities as there is no focussed widget",);
sam edelsten's avatar
sam edelsten committed
                commands.entity(e).remove::<CosmicEditor>();
            }
        }
        Some(focused) => {
            for (e, mut b, editor) in q.iter_mut() {
                if e != focused {
                    *b = CosmicEditBuffer::from_downgrading_editor(editor);
                    trace!("Removing editor from entity as its not focussed anymore",);
                    commands.entity(e).remove::<CosmicEditor>();
                }
            }
        }
    }
}

/// Placed as on_remove hook for [`CosmicEditBuffer`] and [`CosmicEditor`]
pub(crate) fn remove_focus_from_entity(
    mut world: bevy::ecs::world::DeferredWorld,
    entity: Entity,
    _: bevy::ecs::component::ComponentId,
) {
    if let Some(mut focused_widget) = world.get_resource_mut::<FocusedWidget>() {
        if let Some(focused) = focused_widget.0 {
            if focused == entity {
                focused_widget.0 = None;
            }
        }