diff --git a/crates/ewwii/src/window_initiator.rs b/crates/ewwii/src/window_initiator.rs index 4bd747f..2cf9a99 100644 --- a/crates/ewwii/src/window_initiator.rs +++ b/crates/ewwii/src/window_initiator.rs @@ -89,7 +89,7 @@ fn parse_geometry(val: &Dynamic, args: &WindowArguments, override_geom: bool) -> Ok(geom) } -fn get_coords_from_map(map: &rhai::Map, x_key: &str, y_key: &str) -> Result { +fn get_coords_from_map(map: &rhai::Map, x_key: &str, y_key: &str, default_val: &str) -> Result { let raw_key1 = map .get(x_key) .ok_or_else(|| anyhow!("Missing field {}", x_key))? diff --git a/crates/iirhai/src/module_resolver.rs b/crates/iirhai/src/module_resolver.rs index 0882e20..bee3f3f 100644 --- a/crates/iirhai/src/module_resolver.rs +++ b/crates/iirhai/src/module_resolver.rs @@ -46,6 +46,24 @@ impl ModuleResolver for SimpleFileResolver { } } +pub struct ChainedResolver { + pub first: Res1, + pub second: Res2, +} + +impl ModuleResolver for ChainedResolver { + fn resolve( + &self, + engine: &Engine, + source_path: Option<&str>, + path: &str, + pos: Position, + ) -> Result, Box> { + self.first.resolve(engine, source_path, path, pos).or_else(|_| self.second.resolve(engine, source_path, path, pos)) + } +} + + #[cfg(test)] mod test { use super::*; @@ -68,21 +86,4 @@ mod test { Ok(()) } -} - -pub struct ChainedResolver { - pub first: Res1, - pub second: Res2, -} - -impl ModuleResolver for ChainedResolver { - fn resolve( - &self, - engine: &Engine, - source_path: Option<&str>, - path: &str, - pos: Position, - ) -> Result, Box> { - self.first.resolve(engine, source_path, path, pos).or_else(|_| self.second.resolve(engine, source_path, path, pos)) - } -} +} \ No newline at end of file diff --git a/crates/iirhai/src/providers/stdlib/mod.rs b/crates/iirhai/src/providers/stdlib/mod.rs index 2a3e5e8..52e405f 100644 --- a/crates/iirhai/src/providers/stdlib/mod.rs +++ b/crates/iirhai/src/providers/stdlib/mod.rs @@ -11,8 +11,6 @@ pub fn register_stdlib(engine: &mut Engine) { let mut resolver = StaticModuleResolver::new(); - let chained = ChainedResolver { first: SimpleFileResolver, second: resolver.clone() }; - // adding modules let text_mod = exported_module!(text); let env_mod = exported_module!(env); @@ -21,7 +19,9 @@ pub fn register_stdlib(engine: &mut Engine) { // inserting modules resolver.insert("std::text", text_mod); resolver.insert("std::env", env_mod); - resolver.insert("std::env", monitor_mod); + resolver.insert("std::monitor", monitor_mod); + + let chained = ChainedResolver { first: SimpleFileResolver, second: resolver.clone() }; // Register the resolver engine.set_module_resolver(chained); diff --git a/crates/iirhai/src/providers/stdlib/monitor.rs b/crates/iirhai/src/providers/stdlib/monitor.rs index 92ade65..93bc87e 100644 --- a/crates/iirhai/src/providers/stdlib/monitor.rs +++ b/crates/iirhai/src/providers/stdlib/monitor.rs @@ -12,25 +12,56 @@ pub mod monitor { get_primary_monitor_resolution() } + pub fn primary_resolution_str() -> String { + let (w, h) = get_primary_monitor_resolution(); + format!("{w}x{h}") + } + pub fn all_resolutions() -> Vec<(i64, i64)> { get_all_monitor_resolutions() } + pub fn all_resolutions_str() -> String { + get_all_monitor_resolutions() + .into_iter() + .map(|(w, h)| format!("{w}x{h}")) + .collect::>() + .join(", ") + } + pub fn dimensions(index: i64) -> (i64, i64, i64, i64) { get_monitor_dimensions(index as usize) } + pub fn dimensions_str(index: i64) -> String { + let (x, y, w, h) = get_monitor_dimensions(index as usize); + format!("{x},{y} - {w}x{h}") + } + pub fn dpi(index: i64) -> f64 { get_monitor_dpi(index as usize) } + + pub fn dpi_str(index: i64) -> String { + format!("{:.1}", get_monitor_dpi(index as usize)) + } +} + +fn ensure_gdk_init() { + if gtk::is_initialized_main_thread() { + return; + } + gtk::init().expect("Failed to initialize GTK"); } fn get_monitor_count() -> i64 { + ensure_gdk_init(); let display = gdk::Display::default().expect("No display found"); display.n_monitors() as i64 } fn get_primary_monitor_resolution() -> (i64, i64) { + ensure_gdk_init(); let display = gdk::Display::default().expect("No display found"); if let Some(primary) = display.primary_monitor() { let rect = primary.geometry(); @@ -41,6 +72,7 @@ fn get_primary_monitor_resolution() -> (i64, i64) { } fn get_all_monitor_resolutions() -> Vec<(i64, i64)> { + ensure_gdk_init(); let display = gdk::Display::default().expect("No display found"); (0..display.n_monitors()) .filter_map(|i| display.monitor(i)) @@ -52,6 +84,7 @@ fn get_all_monitor_resolutions() -> Vec<(i64, i64)> { } fn get_monitor_dimensions(index: usize) -> (i64, i64, i64, i64) { + ensure_gdk_init(); let display = gdk::Display::default().expect("No display found"); if let Some(m) = display.monitor(index as i32) { let geom = m.geometry(); @@ -67,6 +100,7 @@ fn get_monitor_dimensions(index: usize) -> (i64, i64, i64, i64) { } fn get_monitor_dpi(index: usize) -> f64 { + ensure_gdk_init(); let display = gdk::Display::default().expect("No display found"); if let Some(m) = display.monitor(index as i32) { m.scale_factor() as f64 * 96.0 // base DPI * scale factor diff --git a/crates/iirhai/src/providers/stdlib/text.rs b/crates/iirhai/src/providers/stdlib/text.rs index f5b3f97..39655d4 100644 --- a/crates/iirhai/src/providers/stdlib/text.rs +++ b/crates/iirhai/src/providers/stdlib/text.rs @@ -36,8 +36,8 @@ pub mod text { camel } - pub fn truncate_chars(text: String, max_chars: usize) -> String { - match text.char_indices().nth(max_chars) { + pub fn truncate_chars(text: String, max_chars: i64) -> String { + match text.char_indices().nth(max_chars.try_into().unwrap()) { None => text, Some((idx, _)) => text[..idx].to_string(), } diff --git a/examples/modules/ewwii.rhai b/examples/modules/ewwii.rhai new file mode 100644 index 0000000..1fbeb88 --- /dev/null +++ b/examples/modules/ewwii.rhai @@ -0,0 +1,81 @@ +import "std::monitor" as std_monitor; +import "std::text" as std_text; + +fn text_mod() { + return box(#{ + orientation: "v", + }, [ + label(#{ text: "Text heading", class: "heading", halign: "start" }), + label(#{ + text: "'Hello World!' to slug: " + std_text::to_slug("Hello World!"), + halign: "start" + }), + label(#{ + text: "'Hello World!' to camel case: " + std_text::to_camel_case("Hello World!"), + halign: "start" + }), + label(#{ + text: "'Hello World!' truncated to 10: " + + std_text::truncate_chars("Hello World!", 10), + halign: "start" + }), + label(#{ + text: "'Hello World!' to lower case: " + std_text::to_lower("Hello World!"), + halign: "start" + }), + label(#{ + text: "'Hello World!' to upper case: " + std_text::to_upper("Hello World!"), + halign: "start" + }), + seperator() + ]); +} + +fn monitor_mod() { + return box(#{ + orientation: "v", + }, [ + label(#{ text: "Monitor module", class: "heading", halign: "start" }), + label(#{ text: "Number of Monitors: " + std_monitor::count(), halign: "start" }), + // also has primary_resolution variant which returns a (i64, i64) + label(#{ text: "Primary monitor resolution: " + std_monitor::primary_resolution_str(), halign: "start" }), + // also has all_resolutions variant which returns a Vec<(i64, i64)> + label(#{ text: "All monitor resolutions: " + std_monitor::all_resolutions_str(), halign: "start" }), + // also has dimensions variant which returns a (i64, i64, i64, i64) + label(#{ text: "Dimensions of monitor 0: " + std_monitor::dimensions_str(0), halign: "start" }), + label(#{ text: "DPI of monitor 0: " + std_monitor::dpi_str(0), halign: "start" }), + ]); +} + +fn seperator() { + return box(#{ margin: "0 4px", class: "separator" }, []); +} + +fn window() { + return box(#{}, [ + scroll(#{ + hscroll: false, + }, [ + box(#{ + orientation: "v" + }, [ + text_mod(), + monitor_mod(), + ]) + ]), + ]); +} + +enter([ + defwindow("modules-example", #{ + monitor: 0, + windowtype: "normal", + geometry: #{ + x: "0%", + y: "0%", + width: "400px", + height: "400px", + anchor: "center", + }, + }, window()) +]) \ No newline at end of file diff --git a/examples/modules/ewwii.scss b/examples/modules/ewwii.scss new file mode 100644 index 0000000..61b8b67 --- /dev/null +++ b/examples/modules/ewwii.scss @@ -0,0 +1,9 @@ +.modules-example { + padding: 20px; +} + +.heading { + font-weight: 600; + font-size: 1.8rem; + color: #4facfe; /* explicitly set */ +}