| Crates.io | e_window_api |
| lib.rs | e_window_api |
| version | 0.1.3 |
| created_at | 2025-10-11 16:26:58.025296+00 |
| updated_at | 2025-10-12 04:44:29.77169+00 |
| description | A Rust API wrapper for e_window providing high-level abstraction |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1878338 |
| size | 248,139 |
A high-level Rust API for controlling e_window instances programmatically, including comprehensive message box functionality.
e_window_api provides a convenient Rust interface for launching and controlling e_window processes. Instead of manually spawning processes and writing to stdin, this crate offers a structured API for window management, content updates, real-time control, and modern message box functionality.
Add this to your Cargo.toml:
[dependencies]
e_window_api = "0.1.0"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
use e_window_api::msgbox::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Show an information message
info("Welcome", "Welcome to e_window_api!")?;
// Ask a yes/no question
if ask_yes_no("Confirmation", "Do you want to continue?")? {
println!("User chose to continue");
}
// Get text input from user
if let MessageBoxResult::Text(name) = input_text("Name", "What's your name?")? {
println!("Hello, {}!", name);
}
Ok(())
}
use e_window_api::msgbox::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Async notification
notify_async("Info", "Processing...", MessageBoxIcon::Information, Some(3)).await?;
// Async question
let result = message_box_async("Question", "Continue?",
MessageBoxType::YesNo,
MessageBoxIcon::Question,
None).await?;
println!("User responded: {:?}", result);
Ok(())
}
use e_window_api::{EWindow, WindowConfig, Card};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure the window
let config = WindowConfig::new()
.title("My Window")
.size(800, 600)
.position(100, 100);
// Launch the window
let mut window = EWindow::launch(config).await?;
// Create and show a card using the new structured API
let card = Card::new()
.window_title("Demo Window")
.field("name", "Example")
.typed_field("version", "1.0", "string")
.card_title("Welcome!")
.header("Getting Started")
.caption("Status: Ready")
.body_line("This demonstrates the structured card API.")
.body_line("You can set title, header, caption, and body separately.");
window.show_card(card).await?;
// Close the window
window.close().await?;
Ok(())
}
For quick demos, use the convenience show() method:
use e_window_api::Card;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let card = Card::new()
.window_title("Quick Demo")
.card_title("Hello World")
.body("This is a simple demo using the show() method.");
card.show_blocking()?; // Blocks until window is closed
Ok(())
}
The e_window_api includes a comprehensive message box system that provides both blocking and async variants, supporting all standard message box types with emoji icons and automatic sizing.
use e_window_api::msgbox::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Simple info message (3 seconds auto-close)
info("Information", "Operation completed successfully!")?;
// Warning message (5 seconds auto-close)
warn("Warning", "This action cannot be undone.")?;
// Error message (7 seconds auto-close)
error("Error", "Failed to save file.")?;
// Yes/No question
let result = ask_yes_no("Confirmation", "Do you want to continue?")?;
if result {
println!("User chose Yes");
}
// OK/Cancel confirmation
let confirmed = confirm("Save Changes", "Save before closing?")?;
if confirmed {
println!("User confirmed");
}
Ok(())
}
The API supports all standard Windows message box types:
use e_window_api::msgbox::*;
// Single button types
message_box("Title", "Message", MessageBoxType::Ok, None)?;
// Two button types
let result = message_box("Title", "Continue?", MessageBoxType::OkCancel, None)?;
let result = message_box("Title", "Proceed?", MessageBoxType::YesNo, None)?;
// Three button types
let result = message_box("Title", "Save changes?", MessageBoxType::YesNoCancel, None)?;
// Default button variants
let result = message_box("Title", "Delete file?", MessageBoxType::YesNoDefNo, None)?;
let result = message_box("Title", "Retry?", MessageBoxType::RetryCancel, None)?;
// Special input types
let text = input_text("Input", "Enter your name:")?;
let file = select_file("File Selection", "Choose a configuration file:")?;
Message boxes return typed results that match the button configuration:
use e_window_api::msgbox::MessageBoxResult;
let result = message_box("Question", "Save changes?", MessageBoxType::YesNoCancel, None)?;
match result {
MessageBoxResult::Yes => println!("Saving..."),
MessageBoxResult::No => println!("Discarding changes..."),
MessageBoxResult::Cancel => println!("Operation cancelled"),
_ => {} // Other variants not possible for YesNoCancel
}
// Text input returns the entered text
if let MessageBoxResult::Text(user_input) = input_text("Name", "Enter name:")? {
println!("User entered: {}", user_input);
}
// File selection returns the selected file path
if let MessageBoxResult::File(path) = select_file("Open", "Select file:")? {
println!("Selected file: {}", path);
}
Notifications automatically close after a specified duration and show a visual countdown:
use e_window_api::msgbox::*;
// Built-in notification types with standard durations
info("Success", "File saved successfully!"); // 3 seconds
warn("Warning", "Disk space low"); // 5 seconds
error("Error", "Network connection failed"); // 7 seconds
// Custom notification with specific duration
notify("Custom", "This will close in 10 seconds",
MessageBoxIcon::Information, Some(10))?;
// Persistent notification (no auto-close)
notify("Important", "Click OK to continue",
MessageBoxIcon::Warning, None)?;
Full async support for non-blocking operations:
use e_window_api::msgbox::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Async notifications
notify_async("Info", "Processing...",
MessageBoxIcon::Information, Some(3)).await?;
// Async message boxes
let result = message_box_async("Question", "Continue processing?",
MessageBoxType::YesNo,
MessageBoxIcon::Question,
Some(5)).await?;
if result == MessageBoxResult::Yes {
println!("Continuing...");
}
// Async input
if let MessageBoxResult::Text(name) =
input_text_async("Name", "Enter your name:").await? {
println!("Hello, {}!", name);
}
Ok(())
}
Visual icons are automatically added based on the message type:
// Icons are automatically selected based on function used
info("Title", "Message"); // Uses ℹ️ Information icon
warn("Title", "Message"); // Uses ⚠️ Warning icon
error("Title", "Message"); // Uses ❌ Error icon
ask_yes_no("Title", "Q?"); // Uses ❓ Question icon
// Or specify explicitly
message_box("Custom", "Message", MessageBoxType::Ok,
MessageBoxIcon::Warning, None)?;
// Message box with 10-second timeout
let result = message_box_ex("Question", "Decide quickly!",
MessageBoxType::YesNo,
MessageBoxIcon::Question,
Some(10))?;
if result == MessageBoxResult::Timeout {
println!("User didn't respond in time");
}
// Text input with validation
loop {
if let MessageBoxResult::Text(input) =
input_text("Email", "Enter your email address:")? {
if input.contains('@') {
println!("Valid email: {}", input);
break;
} else {
error("Invalid Email", "Please enter a valid email address")?;
}
} else {
break; // User cancelled
}
}
// Quick yes/no question
if ask_yes_no("Confirmation", "Delete all files?")? {
println!("Deleting files...");
}
// Quick confirmation
if confirm("Save", "Save changes before closing?")? {
println!("Saving...");
}
// Quick info with custom duration
notify_timed("Status", "Operation completed!", 5)?;
The e_window application uses a specific document format protocol for displaying content. This crate provides a structured API that automatically generates the correct format.
A valid e_window document follows this structure:
--title "Window Title" --width 800 --height 600 --x 100 --y 100
field1 | value1 | type1
field2 | value2 | type2
Card Title
Header Text
Caption Text
Body line 1
Body line 2
...
CLI Arguments Line (optional): Window configuration parameters
--title "text" - Window title--width N - Window width in pixels--height N - Window height in pixels--x N - Window X position--y N - Window Y position--follow-hwnd 0xHEX - Follow parent windowFields Section (optional): Key-value pairs in key | value | type format
string, number, boolean, dateBlank Line Separator (crucial!): Required between configuration/fields and content
Content Section: Structured content after the blank line
--title "Project Status" --width 600 --height 400
project | e_window | string
version | 1.0.1 | string
status | active | string
Project Dashboard
Development Progress Report
Last Updated: 2025-10-11
We have made significant progress on the e_window project.
Key accomplishments:
- Implemented structured Card API
- Fixed positioning issues
- Added document protocol support
- Created comprehensive examples
Next steps:
- Add more animation options
- Improve error handling
- Write documentation
Instead of manually constructing document strings, use the structured Card API:
use e_window_api::Card;
let card = Card::new()
// Window configuration
.window_title("My Window") // Sets window title
.size(800, 600) // Sets window size
.position(100, 100) // Sets window position
// Fields (key-value pairs)
.field("name", "value") // String field
.typed_field("count", "42", "number") // Typed field
// Structured content
.card_title("Main Title") // Line 1 after blank separator
.header("Header Text") // Line 2
.caption("Caption Text") // Line 3
.body_line("Body line 1") // Body content (line 4+)
.body_line("Body line 2")
.body("Multi-line\ncontent"); // Or set all body at once
.window_title("text") // Window title bar
.size(width, height) // Window dimensions
.position(x, y) // Window position
.field("key", "value") // String field
.typed_field("key", "value", "type") // Typed field
.card_title("title") // Card title (line 1)
.header("header") // Header (line 2)
.caption("caption") // Caption (line 3)
.body_line("line") // Add single body line
.body_lines(vec!["line1", "line2"]) // Set body from vector
.body("line1\nline2") // Set body from string (splits on \n)
.show_blocking() // Show card and wait (blocking)
.show().await // Show card and wait (async)
The old content-based API is deprecated but still supported:
// OLD (deprecated)
let card = Card::new()
.title("Window Title") // ❌ Deprecated - use window_title()
.content("Main content") // ❌ Deprecated - use card_title(), header(), etc.
.add_content("More content"); // ❌ Deprecated - use body_line()
// NEW (recommended)
let card = Card::new()
.window_title("Window Title") // ✅ Clear window title
.card_title("Main content") // ✅ Structured content title
.body_line("More content"); // ✅ Structured body content
use e_window_api::Card;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let card = Card::new()
// Window configuration
.window_title("Task Manager")
.size(500, 400)
.position(200, 150)
// Fields section
.field("project", "e_window")
.field("language", "Rust")
.typed_field("tasks_completed", "15", "number")
.typed_field("progress", "75%", "percentage")
// Content section
.card_title("Daily Progress Report")
.header("Development Status")
.caption("Status: On Track")
.body_line("Today's accomplishments:")
.body_line("✅ Fixed positioning bugs")
.body_line("✅ Implemented structured API")
.body_line("✅ Updated documentation")
.body_line("")
.body_line("Tomorrow's goals:")
.body_line("🎯 Add animation features")
.body_line("🎯 Improve error messages")
.body_line("🎯 Write more examples");
// Display the card
card.show_blocking()?;
Ok(())
}
// Close the window
window.close().await?;
Ok(())
}
## API Reference
### WindowConfig
Configure window properties before launching:
```rust
let config = WindowConfig::new()
.title("My App") // Window title
.size(800, 600) // Window size
.position(100, 100) // Window position
.decode_debug(true) // Enable debug output
.add_arg("--custom-flag"); // Add custom CLI argument
Create structured content for display using the new API:
let card = Card::new()
// Window configuration
.window_title("Card Window") // Window title bar
.size(400, 300) // Window size
.position(200, 200) // Window position
// Fields section (displayed as table)
.field("author", "John Doe") // String field
.typed_field("count", "42", "number") // Typed field
// Structured content (after blank line separator)
.card_title("Main Title") // Content title (line 1)
.header("Subtitle/Header") // Header text (line 2)
.caption("Status/Caption") // Caption text (line 3)
.body_line("Body content line 1") // Body content (lines 4+)
.body_line("Body content line 2")
.body("Multi-line\nbody content"); // Or set body all at once
The old content-based API is still supported but deprecated:
// ⚠️ DEPRECATED - Use structured API above instead
let card = Card::new()
.title("Card Title") // ❌ Use window_title() instead
.size(400, 300)
.position(200, 200)
.field("author", "John Doe")
.typed_field("count", "42", "number")
.content("Main content goes here") // ❌ Use card_title(), header(), etc.
.add_content("Additional line 1") // ❌ Use body_line() instead
.add_content("Additional line 2");
Control a running window instance:
// Launch window
let mut window = EWindow::launch(config).await?;
// Show content
window.show_card(card).await?;
// Control window
window.set_title("New Title").await?;
window.set_rect(100, 100, 800, 600).await?;
window.set_rect_animated(200, 200, 400, 300, 1000, AnimationEasing::EaseInOut).await?;
// Wait and close
window.delay(2000).await?;
window.close().await?;
Supported easing types for animated operations:
AnimationEasing::LinearAnimationEasing::EaseInAnimationEasing::EaseOutAnimationEasing::EaseInOutAnimationEasing::BounceAnimationEasing::ElasticAnimationEasing::BackAnimationEasing::Custom("custom-easing")The crate includes several comprehensive examples demonstrating different features:
cargo run --example msgbox_demo
Comprehensive demonstration of the message box API:
cargo run --example simple_msgbox_demo
Quick examples of common message box patterns:
cargo run --example enhanced_msgbox_demo
Advanced message box features:
cargo run --example simple_structured_demo
Demonstrates the new structured Card API with:
cargo run --example structured_card_demo
Shows advanced structured content features:
cargo run --example test_positioning
Tests explicit window positioning functionality:
cargo run --example simple_demo
A basic usage demonstration:
cargo run --example realtime_control_api
Demonstrates dynamic window control with animated positioning:
cargo run --example panic_card_api
Shows how to display error/panic information:
cargo run --example demo_ewindow_grid
or demo_ewindow_grid if you installed it.
Demonstrates precise positioning in a grid layout:
The crate provides comprehensive error handling through the EWindowError type:
use e_window_api::{EWindow, EWindowError};
match EWindow::launch_default().await {
Ok(window) => { /* use window */ }
Err(EWindowError::ExecutableNotFound) => {
eprintln!("e_window executable not found in PATH");
}
Err(EWindowError::ProcessSpawnError(e)) => {
eprintln!("Failed to spawn process: {}", e);
}
Err(e) => {
eprintln!("Other error: {}", e);
}
}
e_window executable must be available in PATH or built in the workspaceThe crate has evolved from a content-based API to a structured API that better reflects the e_window document protocol:
// Old approach - manual content construction
let card = Card::new()
.title("My Window") // ❌ Ambiguous - window or content title?
.content("Title\nHeader\nCaption\nBody line 1\nBody line 2"); // ❌ Hard to manage
// New approach - structured fields
let card = Card::new()
.window_title("My Window") // ✅ Clear window title
.card_title("Title") // ✅ Clear content title
.header("Header") // ✅ Structured header
.caption("Caption") // ✅ Structured caption
.body_line("Body line 1") // ✅ Structured body
.body_line("Body line 2");
// Manual process management and document construction
let mut child = Command::new("e_window")
.args(&["--title", "Demo", "--width", "800"])
.stdin(Stdio::piped())
.spawn()?;
let stdin = child.stdin.as_mut().unwrap();
// Manual document format construction
stdin.write_all(b"!control: BeginDocument\n")?;
stdin.write_all(b"!control: Content --title \"Demo\" --width 800\n")?;
stdin.write_all(b"!control: Content field | value | string\n")?;
stdin.write_all(b"!control: Content \n")?; // Blank line separator
stdin.write_all(b"!control: Content Title\n")?;
stdin.write_all(b"!control: Content Header\n")?;
stdin.write_all(b"!control: Content Caption\n")?;
stdin.write_all(b"!control: Content Body\n")?;
stdin.write_all(b"!control: EndDocument\n")?;
// Structured API with automatic document generation
let card = Card::new()
.window_title("Demo")
.size(800, 600)
.field("field", "value")
.card_title("Title")
.header("Header")
.caption("Caption")
.body("Body");
card.show_blocking()?; // Handles all the complexity automatically
The structured API automatically generates the correct e_window document format:
let card = Card::new()
.window_title("Demo")
.field("version", "1.0")
.card_title("Hello")
.header("World")
.body("Welcome!");
println!("{}", card.to_document());
Output:
--title "Demo"
version | 1.0 | string
Hello
World
Welcome!
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.