From 423cb244b238d71a22f7c60bb28eaa9060ac4c23 Mon Sep 17 00:00:00 2001
From: sam edelsten <samedelsten1@gmail.com>
Date: Mon, 29 Apr 2024 19:22:34 +0100
Subject: [PATCH] restructure everything into plugins

---
 examples/basic_sprite.rs                      |   2 +-
 examples/basic_ui.rs                          |   2 +-
 examples/password.rs                          |   4 +-
 src/buffer.rs                                 |  21 +++
 src/cursor.rs                                 |  27 ++-
 src/focus.rs                                  |  17 ++
 src/input.rs                                  |  22 ++-
 src/lib.rs                                    | 167 +++++-------------
 src/{plugins/password/mod.rs => password.rs}  |   8 +-
 .../placeholder/mod.rs => placeholder.rs}     |  10 +-
 src/plugins/mod.rs                            |   2 -
 src/render.rs                                 |  22 ++-
 src/{layout.rs => widget.rs}                  |  29 ++-
 util/src/lib.rs                               |   2 +-
 14 files changed, 193 insertions(+), 142 deletions(-)
 rename src/{plugins/password/mod.rs => password.rs} (95%)
 rename src/{plugins/placeholder/mod.rs => placeholder.rs} (96%)
 delete mode 100644 src/plugins/mod.rs
 rename src/{layout.rs => widget.rs} (87%)

diff --git a/examples/basic_sprite.rs b/examples/basic_sprite.rs
index 09073d0..5c37182 100644
--- a/examples/basic_sprite.rs
+++ b/examples/basic_sprite.rs
@@ -1,5 +1,5 @@
 use bevy::{prelude::*, window::PrimaryWindow};
-use bevy_cosmic_edit::*;
+use bevy_cosmic_edit::{focus::FocusedWidget, *};
 use util::{change_active_editor_sprite, deselect_editor_on_esc, print_editor_text};
 
 fn setup(
diff --git a/examples/basic_ui.rs b/examples/basic_ui.rs
index 94eb841..ef01735 100644
--- a/examples/basic_ui.rs
+++ b/examples/basic_ui.rs
@@ -1,5 +1,5 @@
 use bevy::prelude::*;
-use bevy_cosmic_edit::*;
+use bevy_cosmic_edit::{focus::FocusedWidget, *};
 use util::{change_active_editor_ui, deselect_editor_on_esc, print_editor_text};
 
 fn setup(mut commands: Commands, mut font_system: ResMut<CosmicFontSystem>) {
diff --git a/examples/password.rs b/examples/password.rs
index 0539f39..cfff358 100644
--- a/examples/password.rs
+++ b/examples/password.rs
@@ -1,5 +1,5 @@
 use bevy::prelude::*;
-use bevy_cosmic_edit::{password::Password, placeholder::Placeholder, *};
+use bevy_cosmic_edit::*;
 use util::{change_active_editor_sprite, deselect_editor_on_esc, print_editor_text};
 
 fn setup(mut commands: Commands) {
@@ -40,7 +40,7 @@ fn main() {
             (
                 change_active_editor_sprite,
                 deselect_editor_on_esc,
-                print_editor_text.after(KbInput),
+                print_editor_text.after(InputSet),
             ),
         )
         .run();
diff --git a/src/buffer.rs b/src/buffer.rs
index 1244e35..422c605 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -1,6 +1,27 @@
 use crate::*;
 use bevy::{prelude::*, window::PrimaryWindow};
 
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BufferSet;
+
+pub struct BufferPlugin;
+
+impl Plugin for BufferPlugin {
+    fn build(&self, app: &mut App) {
+        app.add_systems(
+            First,
+            (
+                add_font_system,
+                set_initial_scale,
+                set_redraw,
+                set_editor_redraw,
+                swap_target_handle,
+            )
+                .chain(),
+        );
+    }
+}
+
 pub trait BufferExtras {
     fn get_text(&self) -> String;
 }
diff --git a/src/cursor.rs b/src/cursor.rs
index a044bcf..b7dc8eb 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -1,10 +1,35 @@
 use bevy::{input::mouse::MouseMotion, prelude::*, window::PrimaryWindow};
 
-use crate::{CosmicBuffer, CosmicSource, CosmicTextChanged};
+use crate::{CosmicBuffer, CosmicSource, CosmicTextChanged, CursorConfig};
 
 #[cfg(feature = "multicam")]
 use crate::CosmicPrimaryCamera;
 
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CursorSet;
+
+pub struct CursorPlugin {
+    pub change_cursor: CursorConfig,
+}
+
+impl Plugin for CursorPlugin {
+    fn build(&self, app: &mut App) {
+        match self.change_cursor {
+            CursorConfig::Default => {
+                app.add_systems(Update, (hover_sprites, hover_ui, change_cursor))
+                    .add_event::<TextHoverIn>()
+                    .add_event::<TextHoverOut>();
+            }
+            CursorConfig::Events => {
+                app.add_systems(Update, (hover_sprites, hover_ui))
+                    .add_event::<TextHoverIn>()
+                    .add_event::<TextHoverOut>();
+            }
+            CursorConfig::None => {}
+        }
+    }
+}
+
 /// For use with custom cursor control; Event is emitted when cursor enters a text widget
 #[derive(Event)]
 pub struct TextHoverIn;
diff --git a/src/focus.rs b/src/focus.rs
index 6520f0d..edef5dc 100644
--- a/src/focus.rs
+++ b/src/focus.rs
@@ -3,6 +3,23 @@ use cosmic_text::{Edit, Editor};
 
 use crate::{CosmicBuffer, CosmicEditor};
 
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FocusSet;
+
+pub 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>();
+    }
+}
+
 /// Resource struct that keeps track of the currently active editor entity.
 #[derive(Resource, Default, Deref, DerefMut)]
 pub struct FocusedWidget(pub Option<Entity>);
diff --git a/src/input.rs b/src/input.rs
index be89f1f..53481ca 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -21,11 +21,29 @@ use wasm_bindgen_futures::JsFuture;
 
 use crate::{
     buffer::{get_x_offset_center, get_y_offset_center, BufferExtras},
+    focus::FocusedWidget,
     get_node_cursor_pos, CosmicBuffer, CosmicEditor, CosmicFontSystem, CosmicMaxChars,
-    CosmicMaxLines, CosmicSource, CosmicTextChanged, CosmicTextPosition, FocusedWidget, ReadOnly,
-    XOffset,
+    CosmicMaxLines, CosmicSource, CosmicTextChanged, CosmicTextPosition, ReadOnly, XOffset,
 };
 
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct InputSet;
+
+pub struct InputPlugin;
+
+impl Plugin for InputPlugin {
+    fn build(&self, app: &mut App) {
+        app.add_systems(PreUpdate, input_mouse.in_set(InputSet))
+            .add_systems(
+                Update,
+                (kb_move_cursor, kb_input_text, kb_clipboard)
+                    .chain()
+                    .in_set(InputSet),
+            )
+            .insert_resource(ClickTimer(Timer::from_seconds(0.5, TimerMode::Once)));
+    }
+}
+
 #[derive(Resource)]
 pub struct ClickTimer(pub Timer);
 
diff --git a/src/lib.rs b/src/lib.rs
index 1cc13e0..f877f2a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,36 +4,64 @@ mod buffer;
 mod cursor;
 pub mod focus;
 mod input;
-mod layout;
+pub mod password;
+pub mod placeholder;
 mod render;
-
-mod plugins;
-pub use plugins::*;
+mod widget;
 
 use std::{path::PathBuf, time::Duration};
 
 use bevy::{prelude::*, transform::TransformSystem};
 
-use buffer::{
-    add_font_system, set_editor_redraw, set_initial_scale, set_redraw, swap_target_handle,
-};
-pub use buffer::{get_x_offset_center, get_y_offset_center, CosmicBuffer};
+pub use buffer::*;
 pub use cosmic_text::{
-    Action, Attrs, AttrsOwned, Color as CosmicColor, Cursor, Edit, Family, Metrics, Shaping,
-    Style as FontStyle, Weight as FontWeight,
+    Action, Attrs, AttrsOwned, Buffer, Color as CosmicColor, Cursor, Edit, Editor, Family,
+    FontSystem, Metrics, Shaping, Style as FontStyle, Weight as FontWeight,
 };
-use cosmic_text::{Buffer, Editor, FontSystem, SwashCache};
-use cursor::{change_cursor, hover_sprites, hover_ui};
-pub use cursor::{TextHoverIn, TextHoverOut};
+pub use cursor::*;
 pub use focus::*;
-use input::{input_mouse, kb_clipboard, kb_input_text, kb_move_cursor, ClickTimer};
+pub use input::*;
 #[cfg(target_arch = "wasm32")]
 use input::{poll_wasm_paste, WasmPaste, WasmPasteAsyncChannel};
-use layout::{
-    new_image_from_default, reshape, set_buffer_size, set_padding, set_sprite_size_from_ui,
-    set_widget_size, set_x_offset, CosmicPadding, CosmicWidgetSize,
-};
-use render::{blink_cursor, render_texture, SwashCacheState};
+pub use password::*;
+pub use placeholder::*;
+pub use render::*;
+pub use widget::*;
+
+/// Plugin struct that adds systems and initializes resources related to cosmic edit functionality.
+#[derive(Default)]
+pub struct CosmicEditPlugin {
+    pub font_config: CosmicFontConfig,
+    pub change_cursor: CursorConfig,
+}
+
+impl Plugin for CosmicEditPlugin {
+    fn build(&self, app: &mut App) {
+        let font_system = create_cosmic_font_system(self.font_config.clone());
+
+        app.add_plugins((
+            BufferPlugin,
+            RenderPlugin,
+            WidgetPlugin,
+            InputPlugin,
+            FocusPlugin,
+            CursorPlugin {
+                change_cursor: self.change_cursor.clone(),
+            },
+            PlaceholderPlugin,
+            PasswordPlugin,
+        ))
+        .insert_resource(CosmicFontSystem(font_system))
+        .add_event::<CosmicTextChanged>();
+
+        #[cfg(target_arch = "wasm32")]
+        {
+            let (tx, rx) = crossbeam_channel::bounded::<WasmPaste>(1);
+            app.insert_resource(WasmPasteAsyncChannel { tx, rx })
+                .add_systems(Update, poll_wasm_paste);
+        }
+    }
+}
 
 #[cfg(feature = "multicam")]
 #[derive(Component)]
@@ -46,7 +74,7 @@ pub enum CosmicMode {
     Wrap,
 }
 
-#[derive(Default)]
+#[derive(Default, Clone)]
 pub enum CursorConfig {
     #[default]
     Default,
@@ -200,105 +228,6 @@ impl Default for CosmicFontConfig {
     }
 }
 
-#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
-pub struct KbInput;
-
-#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Render;
-
-/// Plugin struct that adds systems and initializes resources related to cosmic edit functionality.
-#[derive(Default)]
-pub struct CosmicEditPlugin {
-    pub font_config: CosmicFontConfig,
-    pub change_cursor: CursorConfig,
-}
-
-impl Plugin for CosmicEditPlugin {
-    fn build(&self, app: &mut App) {
-        let font_system = create_cosmic_font_system(self.font_config.clone());
-
-        let layout_systems = (
-            (new_image_from_default, set_sprite_size_from_ui),
-            set_widget_size,
-            set_buffer_size,
-            set_padding,
-            set_x_offset,
-        )
-            .chain();
-
-        app.add_systems(
-            First,
-            (
-                add_font_system,
-                set_initial_scale,
-                set_redraw,
-                set_editor_redraw,
-                swap_target_handle,
-            )
-                .chain(),
-        )
-        .add_systems(PreUpdate, (input_mouse,).chain())
-        .add_systems(
-            Update,
-            (
-                (kb_move_cursor, kb_input_text, kb_clipboard, reshape)
-                    .chain()
-                    .in_set(KbInput),
-                blink_cursor,
-            ),
-        )
-        .add_systems(
-            PostUpdate,
-            (
-                layout_systems,
-                drop_editor_unfocused,
-                add_editor_to_focused,
-                render_texture,
-            )
-                .chain()
-                .in_set(Render)
-                .after(TransformSystem::TransformPropagate),
-        )
-        .init_resource::<FocusedWidget>()
-        .insert_resource(SwashCacheState {
-            swash_cache: SwashCache::new(),
-        })
-        .insert_resource(CosmicFontSystem(font_system))
-        .insert_resource(ClickTimer(Timer::from_seconds(0.5, TimerMode::Once)))
-        .add_event::<CosmicTextChanged>();
-
-        match self.change_cursor {
-            CursorConfig::Default => {
-                app.add_systems(Update, (hover_sprites, hover_ui, change_cursor))
-                    .add_event::<TextHoverIn>()
-                    .add_event::<TextHoverOut>();
-            }
-            CursorConfig::Events => {
-                app.add_systems(Update, (hover_sprites, hover_ui))
-                    .add_event::<TextHoverIn>()
-                    .add_event::<TextHoverOut>();
-            }
-            CursorConfig::None => {}
-        }
-
-        #[cfg(target_arch = "wasm32")]
-        {
-            let (tx, rx) = crossbeam_channel::bounded::<WasmPaste>(1);
-            app.insert_resource(WasmPasteAsyncChannel { tx, rx })
-                .add_systems(Update, poll_wasm_paste);
-        }
-
-        add_feature_plugins(app);
-    }
-}
-
-fn add_feature_plugins(app: &mut App) -> &mut App {
-    app.add_plugins(plugins::placeholder::PlaceholderPlugin);
-    app.add_plugins(plugins::password::PasswordPlugin);
-
-    app
-}
-
 fn create_cosmic_font_system(cosmic_font_config: CosmicFontConfig) -> FontSystem {
     let locale = sys_locale::get_locale().unwrap_or_else(|| String::from("en-US"));
     let mut db = cosmic_text::fontdb::Database::new();
diff --git a/src/plugins/password/mod.rs b/src/password.rs
similarity index 95%
rename from src/plugins/password/mod.rs
rename to src/password.rs
index a36109c..fcfac40 100644
--- a/src/plugins/password/mod.rs
+++ b/src/password.rs
@@ -1,11 +1,11 @@
-use crate::{buffer::BufferExtras, placeholder::Placeholder};
+use crate::{buffer::BufferExtras, placeholder::Placeholder, render::RenderSet};
 use bevy::prelude::*;
 use cosmic_text::{Cursor, Edit, Selection, Shaping};
 use unicode_segmentation::UnicodeSegmentation;
 
 use crate::{
     input::{input_mouse, kb_input_text, kb_move_cursor},
-    CosmicBuffer, CosmicEditor, CosmicFontSystem, DefaultAttrs, Render,
+    CosmicBuffer, CosmicEditor, CosmicFontSystem, DefaultAttrs,
 };
 
 pub struct PasswordPlugin;
@@ -25,8 +25,8 @@ impl Plugin for PasswordPlugin {
             .add_systems(
                 PostUpdate,
                 (
-                    hide_password_text.before(Render).in_set(PasswordSet),
-                    restore_password_text.after(Render),
+                    hide_password_text.before(RenderSet).in_set(PasswordSet),
+                    restore_password_text.after(RenderSet),
                 ),
             );
     }
diff --git a/src/plugins/placeholder/mod.rs b/src/placeholder.rs
similarity index 96%
rename from src/plugins/placeholder/mod.rs
rename to src/placeholder.rs
index a180779..f38a94b 100644
--- a/src/plugins/placeholder/mod.rs
+++ b/src/placeholder.rs
@@ -1,10 +1,8 @@
-use crate::{buffer::BufferExtras, Render};
+use crate::{buffer::BufferExtras, input::InputSet, render::RenderSet};
 use bevy::prelude::*;
 use cosmic_text::{Attrs, Edit};
 
-use crate::{
-    CosmicBuffer, CosmicEditor, CosmicFontSystem, CosmicTextChanged, DefaultAttrs, KbInput,
-};
+use crate::{CosmicBuffer, CosmicEditor, CosmicFontSystem, CosmicTextChanged, DefaultAttrs};
 
 #[derive(Component)]
 pub struct Placeholder {
@@ -40,8 +38,8 @@ impl Plugin for PlaceholderPlugin {
                 remove_placeholder_on_input,
             )
                 .chain()
-                .after(KbInput)
-                .before(Render),
+                .after(InputSet)
+                .before(RenderSet),
         );
     }
 }
diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs
deleted file mode 100644
index 08a7f60..0000000
--- a/src/plugins/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod password;
-pub mod placeholder;
diff --git a/src/render.rs b/src/render.rs
index 78e376e..6283d54 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -3,11 +3,29 @@ use cosmic_text::{Color, Edit, SwashCache};
 use image::{imageops::FilterType, GenericImageView};
 
 use crate::{
-    layout::{CosmicPadding, CosmicWidgetSize},
+    widget::{CosmicPadding, CosmicWidgetSize, WidgetSet},
     CosmicBackground, CosmicBuffer, CosmicEditor, CosmicFontSystem, CosmicTextPosition,
     CursorColor, DefaultAttrs, FillColor, ReadOnly, SelectionColor, XOffset,
 };
 
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct RenderSet;
+
+pub struct RenderPlugin;
+
+impl Plugin for RenderPlugin {
+    fn build(&self, app: &mut App) {
+        app.insert_resource(SwashCacheState {
+            swash_cache: SwashCache::new(),
+        })
+        .add_systems(Update, blink_cursor)
+        .add_systems(
+            PostUpdate,
+            (render_texture,).in_set(RenderSet).after(WidgetSet),
+        );
+    }
+}
+
 #[derive(Resource)]
 pub(crate) struct SwashCacheState {
     pub swash_cache: SwashCache,
@@ -63,7 +81,7 @@ fn draw_pixel(buffer: &mut [u8], width: i32, height: i32, x: i32, y: i32, color:
     buffer[offset + 3] = (out.a() * 255.0) as u8;
 }
 
-pub(crate) fn render_texture(
+fn render_texture(
     mut query: Query<(
         Option<&mut CosmicEditor>,
         &mut CosmicBuffer,
diff --git a/src/layout.rs b/src/widget.rs
similarity index 87%
rename from src/layout.rs
rename to src/widget.rs
index f5d0bce..e20047a 100644
--- a/src/layout.rs
+++ b/src/widget.rs
@@ -2,7 +2,34 @@ use crate::*;
 use bevy::{prelude::*, window::PrimaryWindow};
 use cosmic_text::Affinity;
 
-use self::buffer::{get_x_offset_center, get_y_offset_center};
+use self::{
+    buffer::{get_x_offset_center, get_y_offset_center},
+    input::InputSet,
+};
+
+#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct WidgetSet;
+
+pub struct WidgetPlugin;
+
+impl Plugin for WidgetPlugin {
+    fn build(&self, app: &mut App) {
+        app.add_systems(Update, reshape.in_set(WidgetSet).after(InputSet))
+            .add_systems(
+                PostUpdate,
+                (
+                    (new_image_from_default, set_sprite_size_from_ui),
+                    set_widget_size,
+                    set_buffer_size,
+                    set_padding,
+                    set_x_offset,
+                )
+                    .chain()
+                    .in_set(WidgetSet)
+                    .after(TransformSystem::TransformPropagate),
+            );
+    }
+}
 
 #[derive(Component, Default, Deref, DerefMut, Debug)]
 pub struct CosmicPadding(pub Vec2);
diff --git a/util/src/lib.rs b/util/src/lib.rs
index 405152c..e1e1dd1 100644
--- a/util/src/lib.rs
+++ b/util/src/lib.rs
@@ -1,6 +1,6 @@
 // Common functions for examples
 use bevy::{prelude::*, window::PrimaryWindow};
-use bevy_cosmic_edit::*;
+use bevy_cosmic_edit::{focus::FocusedWidget, *};
 
 pub fn deselect_editor_on_esc(i: Res<ButtonInput<KeyCode>>, mut focus: ResMut<FocusedWidget>) {
     if i.just_pressed(KeyCode::Escape) {
-- 
GitLab