From ab4bddf408e38bd062fbb91837bc3a807ed32547 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Thu, 18 Feb 2016 12:54:15 -0700
Subject: [PATCH] Application chooser

---
 src/launcher/main.rs    | 106 +++++++++++++++++++++++++++++++++-------
 src/launcher/package.rs |   6 +--
 2 files changed, 92 insertions(+), 20 deletions(-)

diff --git a/src/launcher/main.rs b/src/launcher/main.rs
index 75e2c22..e030c13 100644
--- a/src/launcher/main.rs
+++ b/src/launcher/main.rs
@@ -11,7 +11,21 @@ use package::Package;
 
 pub mod package;
 
-fn draw(window: &mut Window, packages: &Vec<Box<Package>>, shutdown: &BmpFile, mouse_x: i32, mouse_y: i32){
+fn get_packages() -> Vec<Package> {
+    let mut packages: Vec<Package> = Vec::new();
+
+    //TODO: Use a directory walk
+    for entry_result in fs::read_dir("/apps/").unwrap() {
+        let entry = entry_result.unwrap();
+        if entry.file_type().unwrap().is_dir() {
+            packages.push(Package::from_path(&("/apps/".to_string() + entry.file_name().to_str().unwrap())));
+        }
+    }
+
+    packages
+}
+
+fn draw(window: &mut Window, packages: &Vec<Package>, shutdown: &BmpFile, mouse_x: i32, mouse_y: i32){
     window.set(Color::rgba(0, 0, 0, 0));
     let w = window.width();
     window.rect(0, 16, w, 32, Color::rgba(0, 0, 0, 128));
@@ -65,41 +79,99 @@ fn draw(window: &mut Window, packages: &Vec<Box<Package>>, shutdown: &BmpFile, m
     window.sync();
 }
 
-fn main() {
-    let mut packages: Vec<Box<Package>> = Vec::new();
+fn draw_chooser(window: &mut Window, packages: &Vec<Package>, mouse_x: i32, mouse_y: i32){
+    let w = window.width();
 
-    //TODO: Use a directory walk
-    for entry_result in fs::read_dir("/apps/").unwrap() {
-        let entry = entry_result.unwrap();
-        if entry.file_type().unwrap().is_dir() {
-            packages.push(Package::from_path(&("/apps/".to_string() + entry.file_name().to_str().unwrap())));
+    window.set(Color::rgb(255, 255, 255));
+
+    let mut y = 0;
+    for package in packages.iter() {
+        if mouse_y >= y as i32 && mouse_y < y + 32 {
+            window.rect(0, y, w, 32, Color::rgb(128, 128, 128));
         }
+
+        if package.icon.has_data() {
+            window.image(0, y, package.icon.width() as u32, package.icon.height() as u32, &package.icon);
+        }
+
+        let mut c_x = 40;
+        for c in package.name.chars() {
+            window.char(c_x as i32, y + 8, c, Color::rgb(0, 0, 0));
+            c_x += 8;
+        }
+
+        y += 32;
     }
 
+    window.sync();
+}
+
+fn main() {
     let paths = env::args().skip(1);
     if paths.len() > 0 {
         for ref path in paths {
-            for package in packages.iter() {
-                let mut accepted = false;
+            let mut packages = get_packages();
+
+            packages.retain(|package| -> bool {
                 for accept in package.accepts.iter() {
                     if (accept.starts_with('*') && path.ends_with(&accept[1 ..])) ||
                        (accept.ends_with('*') && path.starts_with(&accept[.. accept.len() - 1])) {
-                        accepted = true;
-                        break;
+                        return true;
                     }
                 }
-                if accepted {
-                    if let Err(err) = Command::new(&package.binary).arg(&path).spawn() {
-                        println!("launcher: failed to launch '{}': {}", package.binary, err);
+                false
+            });
+
+            if packages.len() > 1 {
+                for package in packages.iter() {
+                    println!("{:?}: {}", package.binary, package.icon.has_data());
+                }
+
+                let mut window = Window::new(-1, -1, 400, packages.len() as u32 * 32, path).unwrap();
+
+                draw_chooser(&mut window, &packages, -1, -1);
+                'choosing: loop {
+                    for event in window.events() {
+                        match event.to_option() {
+                            EventOption::Mouse(mouse_event) => {
+                                draw_chooser(&mut window, &packages, mouse_event.x, mouse_event.y);
+
+                                if mouse_event.left_button {
+                                    let mut y = 0;
+                                    for package in packages.iter() {
+                                        if package.icon.has_data() {
+                                            if mouse_event.y >= y && mouse_event.y < y + 32 {
+                                                if let Err(err) = Command::new(&package.binary).arg(path).spawn() {
+                                                    println!("{}: Failed to launch: {}", package.binary, err);
+                                                }
+                                                break 'choosing;
+                                            }
+                                            y += 32;
+                                        }
+                                    }
+                                }
+                            },
+                            EventOption::Quit(_) => break 'choosing,
+                            _ => ()
+                        }
                     }
-                    break;
+
+                    thread::yield_now();
                 }
+            } else if let Some(package) = packages.get(0) {
+                if let Err(err) = Command::new(&package.binary).arg(&path).spawn() {
+                    println!("launcher: failed to launch '{}': {}", package.binary, err);
+                }
+            } else {
+                println!("launcher: no application found for '{}'", path);
             }
         }
     } else {
+        let packages = get_packages();
+
         let shutdown = BmpFile::from_path("/ui/actions/system-shutdown.bmp");
         if ! shutdown.has_data() {
-            println!("Failed to read shutdown icon");
+            println!("launcher: failed to read shutdown icon");
         }
 
         let mut window = Window::new(0, 600 - 48, 800, 48, "").unwrap();
diff --git a/src/launcher/package.rs b/src/launcher/package.rs
index fe6ddab..1e004b7 100644
--- a/src/launcher/package.rs
+++ b/src/launcher/package.rs
@@ -25,8 +25,8 @@ pub struct Package {
 
 impl Package {
     /// Create package from URL
-    pub fn from_path(url: &str) -> Box<Self> {
-        let mut package = Box::new(Package {
+    pub fn from_path(url: &str) -> Self {
+        let mut package = Package {
             url: url.to_string(),
             id: String::new(),
             name: String::new(),
@@ -35,7 +35,7 @@ impl Package {
             accepts: Vec::new(),
             authors: Vec::new(),
             descriptions: Vec::new(),
-        });
+        };
 
         for part in url.rsplit('/') {
             if !part.is_empty() {
-- 
GitLab