🎯 empfohlene Sammlungen
Balanced sample collections from various categories for you to explore
Web Rust Desktop-Funktionsbeispiele
Web Rust Desktop-Funktionsbeispiele einschließlich Dateidialoge, Meldungsfelder und Systemintegration
💻 Meldungsfeld rust
🟢 simple
⭐⭐
Alert-, Bestätigungs- und Eingabedialoge mit Browser-APIs anzeigen
⏱️ 15 min
🏷️ rust, web, desktop features
Prerequisites:
Basic Rust, Understanding of Web APIs
// Web Rust Message Box Examples
// Alert, confirm, and prompt dialogs using browser Web APIs
//
// This demonstrates message box functionality that would work in WebAssembly (WASM) context
//
// For actual desktop message boxes, consider using:
// - Tauri (https://tauri.app/) for desktop apps
// - egui for custom modal dialogs
use serde::{Deserialize, Serialize};
// 1. Message Box Types
/// Types of message boxes
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MessageBoxType {
Info,
Warning,
Error,
Question,
Success,
}
/// Message box buttons
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MessageBoxButtons {
Ok,
OkCancel,
YesNo,
YesNoCancel,
AbortRetryIgnore,
}
/// Message box result
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MessageBoxResult {
Ok,
Cancel,
Yes,
No,
Abort,
Retry,
Ignore,
}
// 2. Message Box Options
/// Options for message box
#[derive(Debug, Clone)]
struct MessageBoxOptions {
title: String,
message: String,
box_type: MessageBoxType,
buttons: MessageBoxButtons,
default_button: MessageBoxResult,
}
impl MessageBoxOptions {
fn new(title: &str, message: &str) -> Self {
MessageBoxOptions {
title: title.to_string(),
message: message.to_string(),
box_type: MessageBoxType::Info,
buttons: MessageBoxButtons::Ok,
default_button: MessageBoxResult::Ok,
}
}
fn with_type(mut self, box_type: MessageBoxType) -> Self {
self.box_type = box_type;
self
}
fn with_buttons(mut self, buttons: MessageBoxButtons) -> Self {
self.buttons = buttons;
self
}
fn with_default(mut self, default: MessageBoxResult) -> Self {
self.default_button = default;
self
}
}
// 3. Message Box Implementation (WASM-compatible)
/// Show alert dialog (simple info message)
fn show_alert(title: &str, message: &str) {
// In WASM, this would call: window.alert(message)
println!("[ALERT] {}: {}", title, message);
}
/// Show confirm dialog (yes/no)
fn show_confirm(title: &str, message: &str) -> bool {
// In WASM, this would call: window.confirm(message)
println!("[CONFIRM] {}: {}", title, message);
true // Simulated user response
}
/// Show prompt dialog (input field)
fn show_prompt(title: &str, message: &str, default: &str) -> Option<String> {
// In WASM, this would call: window.prompt(message, default)
println!("[PROMPT] {}: {} (default: {})", title, message, default);
Some(default.to_string()) // Simulated user input
}
/// Show custom message box
fn show_message_box(options: &MessageBoxOptions) -> MessageBoxResult {
// In WASM, this would create a custom modal dialog
println!("[{} - {}]: {}",
match options.box_type {
MessageBoxType::Info => "INFO",
MessageBoxType::Warning => "WARNING",
MessageBoxType::Error => "ERROR",
MessageBoxType::Question => "QUESTION",
MessageBoxType::Success => "SUCCESS",
},
options.title,
options.message
);
println!("Buttons: {:?}", options.buttons);
options.default_button
}
// 4. Common Message Box Helpers
/// Show information message
fn show_info(title: &str, message: &str) {
show_alert(title, message);
}
/// Show warning message
fn show_warning(title: &str, message: &str) {
let options = MessageBoxOptions::new(title, message)
.with_type(MessageBoxType::Warning);
show_message_box(&options);
}
/// Show error message
fn show_error(title: &str, message: &str) {
let options = MessageBoxOptions::new(title, message)
.with_type(MessageBoxType::Error);
show_message_box(&options);
}
/// Show success message
fn show_success(title: &str, message: &str) {
let options = MessageBoxOptions::new(title, message)
.with_type(MessageBoxType::Success);
show_message_box(&options);
}
/// Show question dialog
fn show_question(title: &str, message: &str) -> MessageBoxResult {
let options = MessageBoxOptions::new(title, message)
.with_type(MessageBoxType::Question)
.with_buttons(MessageBoxButtons::YesNo)
.with_default(MessageBoxResult::Yes);
show_message_box(&options)
}
/// Show confirmation dialog
fn show_confirmation(title: &str, message: &str) -> bool {
matches!(show_question(title, message), MessageBoxResult::Yes)
}
// 5. Progress Dialog
/// Progress dialog state
struct ProgressDialog {
title: String,
message: String,
progress: f64,
}
impl ProgressDialog {
fn new(title: &str, message: &str) -> Self {
ProgressDialog {
title: title.to_string(),
message: message.to_string(),
progress: 0.0,
}
}
fn set_message(&mut self, message: &str) {
self.message = message.to_string();
println!("[PROGRESS] {} - {} ({}%)", self.title, message, self.progress);
}
fn set_progress(&mut self, progress: f64) {
self.progress = progress.max(0.0).min(100.0);
println!("[PROGRESS] {} - {} ({}%)", self.title, self.message, self.progress);
}
fn increment(&mut self, amount: f64) {
self.set_progress(self.progress + amount);
}
fn close(self) {
println!("[PROGRESS] Closed: {}", self.title);
}
}
// 6. Input Dialog
/// Input dialog result
enum InputResult {
Text(String),
Cancelled,
}
/// Show input dialog
fn show_input_dialog(title: &str, message: &str) -> InputResult {
match show_prompt(title, message, "") {
Some(input) => InputResult::Text(input),
None => InputResult::Cancelled,
}
}
/// Show password input dialog
fn show_password_dialog(title: &str, message: &str) -> InputResult {
// In real implementation, this would use a password field
match show_prompt(title, message, "") {
Some(input) => InputResult::Text(input),
None => InputResult::Cancelled,
}
}
// 7. Selection Dialog
/// Show selection dialog
fn show_selection_dialog(title: &str, message: &str, options: &[&str]) -> Option<usize> {
println!("[SELECTION] {}: {}", title, message);
for (i, option) in options.iter().enumerate() {
println!(" {}. {}", i + 1, option);
}
Some(0) // Simulated selection
}
// 8. Toast Notifications
/// Toast notification type
#[derive(Debug, Clone, Copy)]
enum ToastType {
Info,
Success,
Warning,
Error,
}
/// Show toast notification
fn show_toast(message: &str, toast_type: ToastType) {
println!("[TOAST - {:?}] {}", toast_type, message);
}
/// Show info toast
fn toast_info(message: &str) {
show_toast(message, ToastType::Info);
}
/// Show success toast
fn toast_success(message: &str) {
show_toast(message, ToastType::Success);
}
/// Show warning toast
fn toast_warning(message: &str) {
show_toast(message, ToastType::Warning);
}
/// Show error toast
fn toast_error(message: &str) {
show_toast(message, ToastType::Error);
}
// 9. Dialog Builder
/// Builder for message box
struct MessageBoxBuilder {
options: MessageBoxOptions,
}
impl MessageBoxBuilder {
fn new(title: &str, message: &str) -> Self {
MessageBoxBuilder {
options: MessageBoxOptions::new(title, message),
}
}
fn info(mut self) -> Self {
self.options.box_type = MessageBoxType::Info;
self
}
fn warning(mut self) -> Self {
self.options.box_type = MessageBoxType::Warning;
self
}
fn error(mut self) -> Self {
self.options.box_type = MessageBoxType::Error;
self
}
fn question(mut self) -> Self {
self.options.box_type = MessageBoxType::Question;
self
}
fn success(mut self) -> Self {
self.options.box_type = MessageBoxType::Success;
self
}
fn ok_cancel(mut self) -> Self {
self.options.buttons = MessageBoxButtons::OkCancel;
self
}
fn yes_no(mut self) -> Self {
self.options.buttons = MessageBoxButtons::YesNo;
self
}
fn show(self) -> MessageBoxResult {
show_message_box(&self.options)
}
}
// 10. Batch Operations
/// Show multiple confirmations
fn show_multiple_confirmations(messages: &[(&str, &str)]) -> Vec<bool> {
messages.iter()
.map(|(title, msg)| show_confirmation(title, msg))
.collect()
}
/// Chain of dialogs
fn show_dialog_chain(dialogs: Vec<MessageBoxOptions>) -> Vec<MessageBoxResult> {
dialogs.iter()
.map(|options| show_message_box(options))
.collect()
}
// Usage Examples
fn main() {
println!("=== Web Rust Message Box Examples ===\n");
// 1. Simple alert
println!("--- 1. Simple Alert ---");
show_alert("Welcome", "Application started successfully");
// 2. Confirm dialog
println!("
--- 2. Confirm Dialog ---");
let confirmed = show_confirm("Confirm", "Do you want to continue?");
println!("User confirmed: {}", confirmed);
// 3. Prompt dialog
println!("
--- 3. Prompt Dialog ---");
match show_prompt("Input", "Enter your name:", "John") {
Some(name) => println!("User entered: {}", name),
None => println!("User cancelled"),
}
// 4. Different message types
println!("
--- 4. Message Types ---");
show_info("Info", "This is an information message");
show_warning("Warning", "This is a warning message");
show_error("Error", "This is an error message");
show_success("Success", "Operation completed successfully");
// 5. Question dialog
println!("
--- 5. Question Dialog ---");
let answer = show_question("Question", "Do you agree to the terms?");
println!("Answer: {:?}", answer);
// 6. Confirmation
println!("
--- 6. Confirmation ---");
let proceed = show_confirmation("Confirm Action", "Delete selected files?");
println!("Proceed: {}", proceed);
// 7. Progress dialog
println!("
--- 7. Progress Dialog ---");
let mut progress = ProgressDialog::new("Downloading", "Initializing...");
for i in 0..=10 {
progress.set_progress((i * 10) as f64);
progress.set_message(&format!("Downloading file {}...", i));
}
progress.close();
// 8. Toast notifications
println!("
--- 8. Toast Notifications ---");
toast_info("Application started");
toast_success("File saved successfully");
toast_warning("Low disk space");
toast_error("Connection failed");
// 9. Input dialog
println!("
--- 9. Input Dialog ---");
match show_input_dialog("Name", "Enter your name:") {
InputResult::Text(name) => println!("Name: {}", name),
InputResult::Cancelled => println!("Cancelled"),
}
// 10. Selection dialog
println!("
--- 10. Selection Dialog ---");
let options = vec!["Option 1", "Option 2", "Option 3"];
match show_selection_dialog("Choose", "Select an option:", &options) {
Some(index) => println!("Selected: {}", options[index]),
None => println!("Cancelled"),
}
// 11. Builder pattern
println!("
--- 11. Builder Pattern ---");
let result = MessageBoxBuilder::new("Delete", "Are you sure?")
.question()
.yes_no()
.show();
println!("Result: {:?}", result);
println!("
=== Note ===");
println!("For actual desktop message boxes in Rust, consider:");
println!("- Tauri: https://tauri.app/");
println!("- egui: https://github.com/emilk/egui");
println!("- native-dialog: https://github.com/babdul/national");
println!("
=== All Message Box Examples Completed ===");
}
💻 Dateidialog rust
🟡 intermediate
⭐⭐⭐
Dateidialoge öffnen und speichern mit Web APIs (mit WASM)
⏱️ 20 min
🏷️ rust, web, desktop features
Prerequisites:
Intermediate Rust, Understanding of Web APIs
// Web Rust File Dialog Examples
// File open/save dialogs using browser Web APIs
//
// This demonstrates file dialog functionality that would work in WebAssembly (WASM) context
//
// For actual desktop file dialogs, consider using:
// - Tauri (https://tauri.app/) for desktop apps
// - egui + rfd (https://github.com/PolyMeilex/rfd) for native dialogs
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
// 1. File Selection Result
/// Result of file selection
#[derive(Debug, Clone, Serialize, Deserialize)]
struct FileSelection {
name: String,
size: u64,
content_type: Option<String>,
}
// 2. File Dialog Simulation
// Note: In WASM, you would use JavaScript interop for actual file dialogs
/// Simulated file dialog options
#[derive(Debug, Clone)]
struct FileDialogOptions {
title: String,
filters: Vec<FileFilter>,
multi_select: bool,
directory: bool,
}
impl Default for FileDialogOptions {
fn default() -> Self {
FileDialogOptions {
title: "Select File".to_string(),
filters: Vec::new(),
multi_select: false,
directory: false,
}
}
}
/// File filter for dialog
#[derive(Debug, Clone)]
struct FileFilter {
name: String,
extensions: Vec<String>,
}
impl FileFilter {
fn new(name: &str, extensions: &[&str]) -> Self {
FileFilter {
name: name.to_string(),
extensions: extensions.iter().map(|s| s.to_string()).collect(),
}
}
}
// 3. File Dialog Functions (WASM-compatible)
/// Open file dialog (returns selected file paths)
/// In WASM, this would call JavaScript's File API
fn open_file_dialog(options: &FileDialogOptions) -> Result<Vec<PathBuf>, String> {
// Simulated implementation
// In real WASM, you would use wasm-bindgen with web-sys
let mut selected = Vec::new();
// This is a placeholder - actual implementation requires JS interop
if options.directory {
// Would use <input type="file" webkitdirectory>
} else if options.multi_select {
// Would use <input type="file" multiple>
} else {
// Would use <input type="file">
}
if selected.is_empty() {
Err("No file selected".to_string())
} else {
Ok(selected)
}
}
/// Save file dialog
fn save_file_dialog(options: &FileDialogOptions) -> Result<PathBuf, String> {
// In WASM, this would trigger browser download
Ok(PathBuf::from("saved_file.txt"))
}
// 4. File Reading
/// Read file content as text
fn read_file_text(path: &PathBuf) -> Result<String, String> {
std::fs::read_to_string(path).map_err(|e| e.to_string())
}
/// Read file content as bytes
fn read_file_bytes(path: &PathBuf) -> Result<Vec<u8>, String> {
std::fs::read(path).map_err(|e| e.to_string())
}
// 5. File Writing
/// Write text to file
fn write_file_text(path: &PathBuf, content: &str) -> Result<(), String> {
std::fs::write(path, content).map_err(|e| e.to_string())
}
/// Write bytes to file
fn write_file_bytes(path: &PathBuf, content: &[u8]) -> Result<(), String> {
std::fs::write(path, content).map_err(|e| e.to_string())
}
// 6. File Validation
/// Check if file exists
fn file_exists(path: &PathBuf) -> bool {
path.exists()
}
/// Get file metadata
fn get_file_info(path: &PathBuf) -> Result<FileSelection, String> {
let metadata = std::fs::metadata(path).map_err(|e| e.to_string())?;
let name = path.file_name()
.and_then(|n| n.to_str())
.unwrap_or("unknown")
.to_string();
Ok(FileSelection {
name,
size: metadata.len(),
content_type: None, // Would detect from extension
})
}
// 7. File Type Detection
/// Get file extension
fn get_file_extension(path: &PathBuf) -> Option<String> {
path.extension()
.and_then(|ext| ext.to_str())
.map(|s| s.to_string())
}
/// Get MIME type from extension
fn get_mime_type(path: &PathBuf) -> Option<&'static str> {
match get_file_extension(path)?.as_str() {
"txt" => Some("text/plain"),
"html" => Some("text/html"),
"css" => Some("text/css"),
"js" => Some("application/javascript"),
"json" => Some("application/json"),
"png" => Some("image/png"),
"jpg" | "jpeg" => Some("image/jpeg"),
"gif" => Some("image/gif"),
"pdf" => Some("application/pdf"),
"zip" => Some("application/zip"),
_ => Some("application/octet-stream"),
}
}
// 8. Common File Filters
/// Create image file filter
fn image_filter() -> FileFilter {
FileFilter::new("Images", &["png", "jpg", "jpeg", "gif", "bmp", "webp"])
}
/// Create text file filter
fn text_filter() -> FileFilter {
FileFilter::new("Text Files", &["txt", "md", "csv", "json", "xml"])
}
/// Create document file filter
fn document_filter() -> FileFilter {
FileFilter::new("Documents", &["pdf", "doc", "docx", "odt"])
}
/// Create all files filter
fn all_files_filter() -> FileFilter {
FileFilter::new("All Files", &["*"])
}
// 9. File Dialog Builder
/// Builder for file dialog options
struct FileDialogBuilder {
options: FileDialogOptions,
}
impl FileDialogBuilder {
fn new() -> Self {
FileDialogBuilder {
options: FileDialogOptions::default(),
}
}
fn title(mut self, title: &str) -> Self {
self.options.title = title.to_string();
self
}
fn add_filter(mut self, filter: FileFilter) -> Self {
self.options.filters.push(filter);
self
}
fn multi_select(mut self, multi: bool) -> Self {
self.options.multi_select = multi;
self
}
fn directory(mut self, dir: bool) -> Self {
self.options.directory = dir;
self
}
fn build(self) -> FileDialogOptions {
self.options
}
}
impl Default for FileDialogBuilder {
fn default() -> Self {
Self::new()
}
}
// 10. File Operations
/// Batch file reading
fn read_multiple_files(paths: &[PathBuf]) -> Vec<Result<String, String>> {
paths.iter().map(|p| read_file_text(p)).collect()
}
/// Batch file writing
fn write_multiple_files(data: &[(PathBuf, String)]) -> Vec<Result<(), String>> {
data.iter().map(|(path, content)| write_file_text(path, content)).collect()
}
// 11. File Dialog Result Processing
/// Process selected files
fn process_selected_files(paths: Vec<PathBuf>) -> Vec<FileSelection> {
paths.into_iter()
.filter_map(|path| {
if file_exists(&path) {
get_file_info(&path).ok()
} else {
None
}
})
.collect()
}
/// Validate file types
fn validate_file_type(path: &PathBuf, allowed_extensions: &[&str]) -> bool {
if let Some(ext) = get_file_extension(path) {
allowed_extensions.contains(&ext.as_str())
} else {
false
}
}
// Usage Examples
fn main() {
println!("=== Web Rust File Dialog Examples ===\n");
// 1. Create file dialog options
println!("--- 1. File Dialog Options ---");
let options = FileDialogBuilder::new()
.title("Open Image")
.add_filter(image_filter())
.add_filter(all_files_filter())
.multi_select(true)
.build();
println!("Dialog options: {:?}", options);
// 2. Simulate file dialog
println!("
--- 2. Open File Dialog ---");
match open_file_dialog(&options) {
Ok(paths) => println!("Selected {} files", paths.len()),
Err(e) => println!("Error: {}", e),
}
// 3. Save file dialog
println!("
--- 3. Save File Dialog ---");
let save_options = FileDialogBuilder::new()
.title("Save Document")
.add_filter(text_filter())
.build();
match save_file_dialog(&save_options) {
Ok(path) => println!("Save path: {:?}", path),
Err(e) => println!("Error: {}", e),
}
// 4. File filters
println!("
--- 4. File Filters ---");
println!("Image filter: {:?}", image_filter());
println!("Text filter: {:?}", text_filter());
println!("Document filter: {:?}", document_filter());
// 5. File type detection
println!("
--- 5. File Type Detection ---");
let test_path = PathBuf::from("test.png");
println!("Extension: {:?}", get_file_extension(&test_path));
println!("MIME type: {:?}", get_mime_type(&test_path));
// 6. File validation
println!("
--- 6. File Validation ---");
let allowed = vec!["png", "jpg", "jpeg"];
println!("Is valid image: {}", validate_file_type(&test_path, &allowed));
let invalid_path = PathBuf::from("test.txt");
println!("Is valid image: {}", validate_file_type(&invalid_path, &allowed));
println!("
=== Note ===");
println!("For actual desktop file dialogs in Rust, consider:");
println!("- Tauri: https://tauri.app/");
println!("- rfd: https://github.com/PolyMeilex/rfd");
println!("- egui: https://github.com/emilk/egui");
println!("
=== All File Dialog Examples Completed ===");
}
💻 Systemleiste rust
🔴 complex
⭐⭐⭐⭐
Systemleisten-Symbole und Menüs (Desktop-Frameworks)
⏱️ 30 min
🏷️ rust, web, desktop features
Prerequisites:
Advanced Rust, Desktop Framework Knowledge
// Web Rust System Tray Examples
// System tray icons and menu functionality
//
// This demonstrates system tray patterns. Note: System tray is NOT available in web browsers.
// For actual system tray functionality, you need desktop frameworks like:
// - Tauri (https://tauri.app/) - Desktop apps with web technologies
// - Tray-icon crate (https://github.com/tauri-apps/tray-icon) - Rust tray library
//
// The following examples show the API patterns for desktop framework integration
use std::sync::{Arc, Mutex};
// 1. Tray Icon Types
/// Tray icon state
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum TrayIconState {
Normal,
Active,
Disabled,
Busy,
}
/// Tray icon theme
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum TrayIconTheme {
Light,
Dark,
Auto,
}
// 2. Tray Menu Items
/// Menu item type
#[derive(Debug, Clone)]
enum MenuItemType {
Separator,
Action(String),
Checkbox(String, bool),
Submenu(String, Vec<MenuItem>),
}
/// Menu item
#[derive(Debug, Clone)]
struct MenuItem {
id: String,
item_type: MenuItemType,
enabled: bool,
visible: bool,
}
impl MenuItem {
fn separator() -> Self {
MenuItem {
id: format!("sep_{}", std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()),
item_type: MenuItemType::Separator,
enabled: true,
visible: true,
}
}
fn action(id: &str, label: &str) -> Self {
MenuItem {
id: id.to_string(),
item_type: MenuItemType::Action(label.to_string()),
enabled: true,
visible: true,
}
}
fn checkbox(id: &str, label: &str, checked: bool) -> Self {
MenuItem {
id: id.to_string(),
item_type: MenuItemType::Checkbox(label.to_string(), checked),
enabled: true,
visible: true,
}
}
fn submenu(id: &str, label: &str, items: Vec<MenuItem>) -> Self {
MenuItem {
id: id.to_string(),
item_type: MenuItemType::Submenu(label.to_string(), items),
enabled: true,
visible: true,
}
}
fn set_enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
fn set_visible(mut self, visible: bool) -> Self {
self.visible = visible;
self
}
}
// 3. Tray Icon Configuration
/// Tray icon configuration
#[derive(Debug, Clone)]
struct TrayIconConfig {
icon_path: String,
tooltip: String,
theme: TrayIconTheme,
state: TrayIconState,
}
impl TrayIconConfig {
fn new(icon_path: &str, tooltip: &str) -> Self {
TrayIconConfig {
icon_path: icon_path.to_string(),
tooltip: tooltip.to_string(),
theme: TrayIconTheme::Auto,
state: TrayIconState::Normal,
}
}
fn with_theme(mut self, theme: TrayIconTheme) -> Self {
self.theme = theme;
self
}
fn with_state(mut self, state: TrayIconState) -> Self {
self.state = state;
self
}
}
// 4. System Tray Implementation (Mock)
/// System tray (mock implementation for API demonstration)
struct SystemTray {
config: TrayIconConfig,
menu: Vec<MenuItem>,
on_click: Option<Box<dyn Fn()>>,
on_double_click: Option<Box<dyn Fn()>>,
}
impl SystemTray {
fn new(config: TrayIconConfig) -> Self {
SystemTray {
config,
menu: Vec::new(),
on_click: None,
on_double_click: None,
}
}
fn set_menu(&mut self, menu: Vec<MenuItem>) {
self.menu = menu;
println!("Tray menu updated with {} items", menu.len());
}
fn set_tooltip(&mut self, tooltip: &str) {
self.config.tooltip = tooltip.to_string();
println!("Tray tooltip updated: {}", tooltip);
}
fn set_icon(&mut self, icon_path: &str) {
self.config.icon_path = icon_path.to_string();
println!("Tray icon updated: {}", icon_path);
}
fn set_state(&mut self, state: TrayIconState) {
self.config.state = state;
println!("Tray state updated: {:?}", state);
}
fn show(&self) {
println!("Tray icon shown: {}", self.config.tooltip);
}
fn hide(&self) {
println!("Tray icon hidden");
}
fn on_click<F: Fn() + 'static>(mut self, callback: F) -> Self {
self.on_click = Some(Box::new(callback));
self
}
fn on_double_click<F: Fn() + 'static>(mut self, callback: F) -> Self {
self.on_double_click = Some(Box::new(callback));
self
}
fn handle_menu_action(&self, item_id: &str) {
println!("Menu action triggered: {}", item_id);
// Would dispatch to event handler
}
}
// 5. Tray Menu Builder
/// Builder for tray menu
struct TrayMenuBuilder {
items: Vec<MenuItem>,
}
impl TrayMenuBuilder {
fn new() -> Self {
TrayMenuBuilder {
items: Vec::new(),
}
}
fn add_item(mut self, item: MenuItem) -> Self {
self.items.push(item);
self
}
fn add_separator(mut self) -> Self {
self.items.push(MenuItem::separator());
self
}
fn add_action(mut self, id: &str, label: &str) -> Self {
self.items.push(MenuItem::action(id, label));
self
}
fn add_checkbox(mut self, id: &str, label: &str, checked: bool) -> Self {
self.items.push(MenuItem::checkbox(id, label, checked));
self
}
fn add_submenu(mut self, id: &str, label: &str, items: Vec<MenuItem>) -> Self {
self.items.push(MenuItem::submenu(id, label, items));
self
}
fn build(self) -> Vec<MenuItem> {
self.items
}
}
impl Default for TrayMenuBuilder {
fn default() -> Self {
Self::new()
}
}
// 6. Notification Handler
/// Tray notification
#[derive(Debug, Clone)]
struct TrayNotification {
title: String,
body: String,
icon: Option<String>,
timeout: Option<u32>,
}
impl TrayNotification {
fn new(title: &str, body: &str) -> Self {
TrayNotification {
title: title.to_string(),
body: body.to_string(),
icon: None,
timeout: None,
}
}
fn with_icon(mut self, icon: &str) -> Self {
self.icon = Some(icon.to_string());
self
}
fn with_timeout(mut self, seconds: u32) -> Self {
self.timeout = Some(seconds);
self
}
}
// 7. Tray State Manager
/// Manages tray icon state
struct TrayStateManager {
state: Arc<Mutex<TrayIconState>>,
}
impl TrayStateManager {
fn new() -> Self {
TrayStateManager {
state: Arc::new(Mutex::new(TrayIconState::Normal)),
}
}
fn set_state(&self, new_state: TrayIconState) {
let mut state = self.state.lock().unwrap();
*state = new_state;
println!("Tray state changed to: {:?}", new_state);
}
fn get_state(&self) -> TrayIconState {
*self.state.lock().unwrap()
}
}
// 8. Common Tray Menu Patterns
/// Create default application menu
fn create_app_menu() -> Vec<MenuItem> {
TrayMenuBuilder::new()
.add_action("show", "Show")
.add_action("hide", "Hide")
.add_separator()
.add_action("settings", "Settings")
.add_action("about", "About")
.add_separator()
.add_action("quit", "Quit")
.build()
}
/// Create status toggle menu
fn create_status_menu(is_active: bool) -> Vec<MenuItem> {
TrayMenuBuilder::new()
.add_checkbox("status", "Active", is_active)
.add_separator()
.add_action("refresh", "Refresh Status")
.add_separator()
.add_action("quit", "Quit")
.build()
}
/// Create media player menu
fn create_media_menu() -> Vec<MenuItem> {
TrayMenuBuilder::new()
.add_action("play_pause", "Play/Pause")
.add_action("next", "Next Track")
.add_action("prev", "Previous Track")
.add_separator()
.add_submenu("playlist", "Playlist", vec![
MenuItem::action("shuffle", "Shuffle"),
MenuItem::action("repeat", "Repeat"),
])
.add_separator()
.add_action("quit", "Quit")
.build()
}
// 9. Tray Event Handler
/// Tray events
#[derive(Debug, Clone)]
enum TrayEvent {
Click,
DoubleClick,
MenuAction(String),
BalloonClick,
}
/// Handle tray events
fn handle_tray_event(event: TrayEvent) {
match event {
TrayEvent::Click => println!("Tray icon clicked"),
TrayEvent::DoubleClick => println!("Tray icon double-clicked"),
TrayEvent::MenuAction(id) => println!("Menu action: {}", id),
TrayEvent::BalloonClick => println!("Balloon notification clicked"),
}
}
// 10. Dynamic Menu Updates
/// Update menu item dynamically
fn update_menu_item(menu: &mut Vec<MenuItem>, id: &str, updater: impl FnOnce(&mut MenuItem)) {
if let Some(item) = menu.iter_mut().find(|i| i.id == id) {
updater(item);
}
}
/// Toggle checkbox in menu
fn toggle_menu_checkbox(menu: &mut Vec<MenuItem>, id: &str) -> bool {
if let Some(item) = menu.iter_mut().find(|i| i.id == id) {
if let MenuItemType::Checkbox(label, checked) = &mut item.item_type {
*checked = !*checked;
return *checked;
}
}
false
}
// Usage Examples
fn main() {
println!("=== Web Rust System Tray Examples ===\n");
// 1. Create tray icon
println!("--- 1. Create Tray Icon ---");
let config = TrayIconConfig::new("icon.png", "My Application")
.with_state(TrayIconState::Normal);
let mut tray = SystemTray::new(config);
tray.show();
// 2. Set up menu
println!("
--- 2. Set Up Menu ---");
let menu = create_app_menu();
tray.set_menu(menu);
for item in &tray.menu {
println!(" - {:?}", item.item_type);
}
// 3. Update tooltip
println!("
--- 3. Update Tooltip ---");
tray.set_tooltip("Application running - 3 notifications");
// 4. Change state
println!("
--- 4. Change State ---");
tray.set_state(TrayIconState::Busy);
// 5. Menu builder
println!("
--- 5. Menu Builder ---");
let custom_menu = TrayMenuBuilder::new()
.add_action("file_open", "Open File")
.add_action("file_save", "Save File")
.add_separator()
.add_submenu("recent", "Recent Files", vec![
MenuItem::action("recent_1", "document1.txt"),
MenuItem::action("recent_2", "document2.txt"),
])
.build();
// 6. Status menu
println!("
--- 6. Status Menu ---");
let status_menu = create_status_menu(true);
println!("Status menu items: {}", status_menu.len());
// 7. Media menu
println!("
--- 7. Media Player Menu ---");
let media_menu = create_media_menu();
println!("Media menu items: {}", media_menu.len());
// 8. Menu updates
println!("
--- 8. Dynamic Menu Updates ---");
let mut menu = create_app_menu();
update_menu_item(&mut menu, "show", |item| {
item.enabled = false;
});
println!("Updated 'show' item: enabled={}",
menu.iter().find(|i| i.id == "show").map(|i| i.enabled).unwrap_or(false)
);
// 9. Toggle checkbox
println!("
--- 9. Toggle Checkbox ---");
let mut menu = create_status_menu(false);
let new_state = toggle_menu_checkbox(&mut menu, "status");
println!("Checkbox toggled to: {}", new_state);
// 10. Event handling
println!("
--- 10. Event Handling ---");
handle_tray_event(TrayEvent::Click);
handle_tray_event(TrayEvent::MenuAction("quit".to_string()));
// 11. Notification
println!("
--- 11. Notification ---");
let notification = TrayNotification::new("Update Available", "Version 2.0 is ready to install")
.with_icon("update-icon.png")
.with_timeout(10);
println!("Notification: {:?} - {:?}", notification.title, notification.body);
// 12. State manager
println!("
--- 12. State Manager ---");
let state_manager = TrayStateManager::new();
state_manager.set_state(TrayIconState::Active);
println!("Current state: {:?}", state_manager.get_state());
println!("
=== IMPORTANT NOTE ===");
println!("System tray functionality is NOT available in web browsers.");
println!("This code demonstrates API patterns for desktop frameworks.");
println!("");
println!("For actual system tray implementation in Rust:");
println!("- Tauri: https://tauri.app/ (recommended for web developers)");
println!("- tray-icon: https://github.com/tauri-apps/tray-icon");
println!("- egui: https://github.com/emilk/egui (with tray-icon)");
println!("
=== All System Tray Examples Completed ===");
}