ewwii_plugin_api/
lib.rs

1//! # ewwii_plugin_api - A plugin interface for ewwii
2//!
3//! `ewwii_plguin_api` is a shared list of traits
4//! that both ewwii and its plugins can use.
5//! This crate simplifies and provides a safe way for building
6//! plugins for ewwii.
7//!
8//! ## Example
9//!
10//! The following example shows how this crate shall be used to build ewwii plugins:
11//!
12//! ```rust
13//! use ewwii_plugin_api::{EwwiiAPI, Plugin, export_plugin};
14//!
15//! pub struct DummyStructure;
16//!
17//! impl Plugin for DummyStructure {
18//!     // critical for ewwii to launch the plugin
19//!     fn init(&self, host: &dyn EwwiiAPI) {
20//!         // will be printed by the host
21//!         host.log("Plugin says Hello!");
22//!     }
23//! }
24//!
25//! // Critical for ewwii to load the plugin
26//! export_plugin!(DummyStructure);
27//! ```
28
29mod export_macros;
30
31pub mod example;
32pub mod rhai_backend;
33pub mod widget_backend;
34
35#[cfg(feature = "include-rhai")]
36pub use rhai;
37
38#[cfg(feature = "include-gtk4")]
39pub use gtk4;
40
41/// The shared trait defining the Ewwii plugin API
42pub trait EwwiiAPI: Send + Sync {
43    // == General Stuff == //
44    /// Print a message from the host
45    fn print(&self, msg: &str);
46    /// Log a message from the host
47    fn log(&self, msg: &str);
48    /// Log a warning from the host
49    fn warn(&self, msg: &str);
50    /// Log an error from the host
51    fn error(&self, msg: &str);
52
53    // == Rhai Manipulation Stuff == //
54    /// _(include-rhai)_ Perform actions on the latest rhai engine.
55    ///
56    /// # Example
57    ///
58    /// ```rust
59    /// use ewwii_plugin_api::{EwwiiAPI, Plugin};
60    ///
61    /// pub struct DummyStructure;
62    ///
63    /// impl Plugin for DummyStructure {
64    ///     fn init(&self, host: &dyn EwwiiAPI) {
65    ///         host.rhai_engine_action(Box::new(|eng| {
66    ///             // eng = rhai::Engine
67    ///             eng.set_max_expr_depths(128, 128);
68    ///         }));
69    ///     }
70    /// }
71    /// ```
72    #[cfg(feature = "include-rhai")]
73    fn rhai_engine_action(
74        &self,
75        f: Box<dyn FnOnce(&mut rhai::Engine) + Send>,
76    ) -> Result<(), String>;
77
78    /// _(include-rhai)_ Expose a function that rhai configuration can call.
79    ///
80    /// **NOTE:***
81    ///
82    /// Due to TypeID mismatches, methods like `register_type`, `register_fn`,
83    /// etc. won't work on the engine and may cause a crash. It is recommended
84    /// to use the `register_function` API to register a funtion which `api::slib`
85    /// can call to in rhai.
86    ///
87    /// # Example
88    ///
89    /// ```rust
90    /// use ewwii_plugin_api::{EwwiiAPI, Plugin};
91    /// use rhai::Dynamic;
92    ///
93    /// pub struct DummyStructure;
94    ///
95    /// impl Plugin for DummyStructure {
96    ///     fn init(&self, host: &dyn EwwiiAPI) {
97    ///         host.register_function("my_func".to_string(), Box::new(|args| {
98    ///             // Do stuff
99    ///             // - Perform things on the args (if needed)
100    ///             // - And return a value
101    ///             
102    ///             Dynamic::default() // return empty
103    ///         }));
104    ///     }
105    /// }
106    /// ```
107    ///
108    /// This example will register a function with signature "my_func(Array)" in rhai.
109    ///
110    /// ## Example use in rhai
111    ///
112    /// ```js
113    /// print(my_func(["param1", "param2"]));
114    /// ```
115    #[cfg(feature = "include-rhai")]
116    fn register_function(
117        &self,
118        name: String,
119        namespace: rhai_backend::RhaiFnNamespace,
120        f: Box<
121            dyn Fn(rhai::Array) -> Result<rhai::Dynamic, Box<rhai::EvalAltResult>> + Send + Sync,
122        >,
123    ) -> Result<(), String>;
124
125    // == Widget Rendering & Logic == //
126    /// Get the list of all widget id's
127    fn list_widget_ids(&self) -> Result<Vec<u64>, String>;
128
129    /// _(include-gtk4)_ Perform actions on the latest widget registry.
130    ///
131    /// # Example
132    ///
133    /// ```rust
134    /// use ewwii_plugin_api::{EwwiiAPI, Plugin};
135    ///
136    /// pub struct DummyStructure;
137    ///
138    /// impl Plugin for DummyStructure {
139    ///     fn init(&self, host: &dyn EwwiiAPI) {
140    ///         host.widget_reg_action(Box::new(|wrg| {
141    ///             // wrg = widget_backend::WidgetRegistryRepr
142    ///             // The gtk4::Widget can be modified here.
143    ///         }));
144    ///     }
145    /// }
146    /// ```
147    #[cfg(feature = "include-gtk4")]
148    fn widget_reg_action(
149        &self,
150        f: Box<dyn FnOnce(&mut widget_backend::WidgetRegistryRepr) + Send>,
151    ) -> Result<(), String>;
152}
153
154/// The API format that the plugin should follow.
155/// This trait should be implemented for a structure and
156/// that structure should be exported via FFI.
157///
158/// ## Example
159///
160/// ```rust
161/// use ewwii_plugin_api::{Plugin, EwwiiAPI, export_plugin};
162///
163/// struct MyStruct;
164///
165/// impl Plugin for MyStruct {
166///     fn init(&self, host: &dyn EwwiiAPI) {
167///         /* Implementation Skipped */   
168///      }
169/// }
170///
171/// // Automatically does all the FFI related exports
172/// export_plugin!(MyStruct);
173/// ```
174pub trait Plugin: Send + Sync {
175    /// Function ran by host to startup plugin (and its a must-have for plugin loading)
176    fn init(&self, host: &dyn EwwiiAPI);
177}