From 57b403054bc41bd1ebec8b7ca2fec3efac9ef70a Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Sat, 21 Sep 2024 17:21:59 -0600 Subject: [PATCH] command palatte has results --- Cargo.lock | 46 ++++++++++++++++-- Cargo.toml | 8 +++- examples/keyboard_driven.rs | 2 +- src/widgets/browser_view.rs | 4 +- src/widgets/command_window.rs | 34 +++++++++++-- src/widgets/mod.rs | 89 +++++++++++++++++++++++------------ src/widgets/nav_bar.rs | 14 ++++-- 7 files changed, 153 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebaca28..01634ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1574,6 +1574,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1909,9 +1915,9 @@ dependencies = [ [[package]] name = "iced_widget" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23eef161bcd216f3472916570919dc3542647285da9cc81085b8d5cb434dc870" +checksum = "81429e1b950b0e4bca65be4c4278fea6678ea782030a411778f26fa9f8983e1d" dependencies = [ "iced_renderer", "iced_runtime", @@ -1956,6 +1962,8 @@ dependencies = [ "serde", "serde_json", "smol_str", + "strum", + "strum_macros", "tempfile", "ul-next", "url", @@ -2858,7 +2866,7 @@ version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39b0deead1528fd0e5947a8546a9642a9777c25f6e1e26f34c97b204bbb465bd" dependencies = [ - "heck", + "heck 0.4.1", "itertools 0.12.1", "proc-macro2", "proc-macro2-diagnostics", @@ -3438,6 +3446,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "rustybuzz" version = "0.14.1" @@ -3519,9 +3533,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3805,6 +3819,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + [[package]] name = "subtle" version = "2.6.1" diff --git a/Cargo.toml b/Cargo.toml index dfa39c1..a50e88c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,13 +33,19 @@ ultralight = ["ul-next"] [dependencies] env_home = "0.1.0" iced = { version = "0.13", features = ["advanced", "image", "tokio", "lazy"] } -iced_aw = { version = "0.10", features = ["tab_bar", "icons"] } +iced_aw = { version = "0.10", features = [ + "tab_bar", + "icons", + "selection_list", +] } iced_on_focus_widget = "0.1.1" rand = "0.8.5" reqwest = "0.12.5" serde = "1.0.207" serde_json = "1.0.124" smol_str = "0.2.2" +strum = { version = "0.26.3", features = ["derive"] } +strum_macros = "0.26.4" tempfile = "3.12.0" ul-next = { version = "0.4", optional = true } url = "2.5.2" diff --git a/examples/keyboard_driven.rs b/examples/keyboard_driven.rs index 6cbabd5..1fd4b63 100644 --- a/examples/keyboard_driven.rs +++ b/examples/keyboard_driven.rs @@ -65,7 +65,7 @@ impl Browser { Message::Update => self.widgets.force_update().map(Message::BrowserWidget), Message::Event(event) => self .widgets - .update(widgets::Message::Event(event)) + .update(widgets::Message::Event(Some(event))) .map(Message::BrowserWidget), } } diff --git a/src/widgets/browser_view.rs b/src/widgets/browser_view.rs index d885220..ac11234 100644 --- a/src/widgets/browser_view.rs +++ b/src/widgets/browser_view.rs @@ -96,11 +96,11 @@ where match event { Event::Keyboard(event) => { - shell.publish(Message::SendKeyboardEvent(event)); + shell.publish(Message::SendKeyboardEvent(Some(event))); } Event::Mouse(event) => { if let Some(point) = cursor.position_in(layout.bounds()) { - shell.publish(Message::SendMouseEvent(point, event)); + shell.publish(Message::SendMouseEvent(point, Some(event))); } } _ => (), diff --git a/src/widgets/command_window.rs b/src/widgets/command_window.rs index ccda3bb..7ac4f8d 100644 --- a/src/widgets/command_window.rs +++ b/src/widgets/command_window.rs @@ -1,14 +1,42 @@ use iced::widget::{center, column, container, mouse_area, opaque, stack, text_input}; -use iced::{border, Color, Element, Theme}; +use iced::{border, Color, Element, Font, Length, Theme}; +use iced_aw::SelectionList; +use strum::IntoEnumIterator; use super::Message; +pub struct CommandWindowState { + pub query: String, + actions: Vec, + pub selected_action: String, + pub selected_index: usize, +} + +impl CommandWindowState { + pub fn new() -> Self { + Self { + query: String::new(), + actions: Message::iter().map(|e| e.clone().to_string()).collect(), + selected_action: String::new(), + selected_index: 0, + } + } +} + pub fn command_window<'a>( base: impl Into>, - query: &str, + state: &'a CommandWindowState, ) -> Element<'a, Message> { let window = container(column![ - text_input("Command Menu", query).on_input(Message::QueryChanged), + text_input("Command Menu", &state.query).on_input(Message::QueryChanged), + SelectionList::new(&state.actions, Message::CommandSelectionChanged) + .width(Length::Fill) + .height(Length::Fill) + .style(|theme: &Theme, _| iced_aw::style::selection_list::Style { + text_color: theme.palette().text.into(), + background: theme.palette().background.into(), + ..Default::default() + }), ]) .padding(10) .center(600) diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 70d1cae..993fd37 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,7 +1,11 @@ +use command_window::CommandWindowState; use iced::keyboard::{self, key}; use iced::widget::{self, column}; use iced::{event::Event, mouse, Element, Point, Size, Task}; use iced_on_focus_widget::hoverable; +use nav_bar::NavBarState; +use std::string::ToString; +use strum_macros::{Display, EnumIter}; use url::Url; mod browser_view; @@ -18,27 +22,43 @@ pub use command_window::command_window; use crate::{engines::BrowserEngine, shortcut::check_shortcut, to_url, ImageInfo, Shortcuts}; -#[derive(Debug, Clone, PartialEq)] +// Options exist only to have defaults for EnumIter +#[derive(Debug, Clone, PartialEq, Display, EnumIter)] pub enum Message { + // Commands + #[strum(to_string = "Go Backward")] GoBackward, + #[strum(to_string = "Go Forward")] GoForward, Refresh, + #[strum(to_string = "Go Home")] GoHome, + #[strum(to_string = "Go To Url")] GoToUrl(String), + #[strum(to_string = "Change Tab")] ChangeTab(TabSelectionType), + #[strum(to_string = "Close Tab")] CloseTab(TabSelectionType), + #[strum(to_string = "Close Tab")] CloseCurrentTab, + #[strum(to_string = "New Tab")] CreateTab, + #[strum(to_string = "Toggle Command Palatte")] + ToggleOverlay, + #[strum(to_string = "Show Command Palatte")] + ShowOverlay, + #[strum(to_string = "Hide Command Palatte")] + HideOverlay, + + // Internal only - for widgets UrlChanged(String), UpdateUrl, QueryChanged(String), - SendKeyboardEvent(keyboard::Event), - SendMouseEvent(Point, mouse::Event), + CommandSelectionChanged(usize, String), + SendKeyboardEvent(Option), + SendMouseEvent(Point, Option), UpdateViewSize(Size), - Event(Event), - ToggleOverlay, - ShowOverlay, - HideOverlay, + Event(Option), } /// Allows different widgets to interact in their native way @@ -47,12 +67,17 @@ pub enum TabSelectionType { Id(u32), Index(usize), } +impl Default for TabSelectionType { + fn default() -> Self { + TabSelectionType::Index(0) + } +} pub struct BrowserWidget { engine: Option, home: Url, - url: String, // State of url bar - query: String, // State of Command window + nav_bar_state: NavBarState, + command_window_state: CommandWindowState, with_tab_bar: bool, with_nav_bar: bool, show_overlay: bool, @@ -69,8 +94,8 @@ where Self { engine: None, home, - url: String::new(), - query: String::new(), + nav_bar_state: NavBarState::new(), + command_window_state: CommandWindowState::new(), with_tab_bar: false, with_nav_bar: false, show_overlay: false, @@ -201,11 +226,13 @@ where Task::none() } Message::SendKeyboardEvent(event) => { - self.engine().handle_keyboard_event(event); + self.engine() + .handle_keyboard_event(event.expect("Value cannot be none")); Task::none() } Message::SendMouseEvent(point, event) => { - self.engine_mut().handle_mouse_event(point, event); + self.engine_mut() + .handle_mouse_event(point, event.expect("Value cannot be none")); Task::none() } Message::ChangeTab(index_type) => { @@ -216,7 +243,7 @@ where } }; self.engine_mut().get_tabs_mut().set_current_id(id); - self.url = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); Task::none() } Message::CloseCurrentTab => Task::done(Message::CloseTab(TabSelectionType::Id( @@ -235,11 +262,11 @@ where } }; self.engine_mut().get_tabs_mut().remove(id); - self.url = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); Task::none() } Message::CreateTab => { - self.url = self.home.to_string(); + self.nav_bar_state.0 = self.home.to_string(); let home = self.home.clone(); let bounds = self.view_size; let tab = self.engine_mut().new_tab( @@ -255,12 +282,12 @@ where } Message::GoBackward => { self.engine().go_back(); - self.url = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); Task::none() } Message::GoForward => { self.engine().go_forward(); - self.url = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); Task::none() } Message::Refresh => { @@ -276,24 +303,27 @@ where Task::none() } Message::UpdateUrl => { - self.url = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); Task::none() } Message::UrlChanged(url) => { - self.url = url; + self.nav_bar_state.0 = url; Task::none() } Message::QueryChanged(query) => { - self.query = query; + self.command_window_state.query = query; + Task::none() + } + Message::CommandSelectionChanged(index, name) => { + self.command_window_state.selected_index = index; + self.command_window_state.selected_action = name; Task::none() } Message::ToggleOverlay => { if self.show_overlay { - self.show_overlay = false; - widget::focus_next() + Task::done(Message::HideOverlay) } else { - self.show_overlay = true; - widget::focus_next() + Task::done(Message::ShowOverlay) } } Message::ShowOverlay => { @@ -302,11 +332,11 @@ where } Message::HideOverlay => { self.show_overlay = false; - Task::none() + widget::focus_next() } Message::Event(event) => { match event { - Event::Keyboard(key) => { + Some(Event::Keyboard(key)) => { if let iced::keyboard::Event::KeyPressed { key, modified_key: _, @@ -349,7 +379,8 @@ where column = column.push(tab_bar(self.engine().get_tabs())) } if self.with_nav_bar { - column = column.push(hoverable(nav_bar(&self.url)).on_focus_change(Message::UpdateUrl)) + column = column + .push(hoverable(nav_bar(&self.nav_bar_state)).on_focus_change(Message::UpdateUrl)) } let browser_view = browser_view( @@ -358,7 +389,7 @@ where !self.show_overlay, ); if self.show_overlay { - column = column.push(command_window(browser_view, &self.query)) + column = column.push(command_window(browser_view, &self.command_window_state)) } else { column = column.push(browser_view); } diff --git a/src/widgets/nav_bar.rs b/src/widgets/nav_bar.rs index 17974fc..7af8258 100644 --- a/src/widgets/nav_bar.rs +++ b/src/widgets/nav_bar.rs @@ -4,7 +4,15 @@ use iced_aw::core::icons::bootstrap::{icon_to_text, Bootstrap}; use super::Message; -pub fn nav_bar(url: &str) -> Element { +/// Holds the state of infomation in nav_bar +pub struct NavBarState(pub String); +impl NavBarState { + pub fn new() -> Self { + NavBarState(String::new()) + } +} + +pub fn nav_bar(state: &NavBarState) -> Element { let back = tooltip_helper( Button::new(icon_to_text(Bootstrap::ChevronBarLeft)) .on_press(Message::GoBackward) @@ -31,10 +39,10 @@ pub fn nav_bar(url: &str) -> Element { ); let space_left = Space::new(Length::Fill, Length::Shrink); let space_right = Space::new(Length::Fill, Length::Shrink); - let search = text_input("https://site.com", url) + let search = text_input("https://site.com", &state.0) .on_input(Message::UrlChanged) .on_paste(Message::GoToUrl) - .on_submit(Message::GoToUrl(url.to_string())) + .on_submit(Message::GoToUrl(state.0.to_string())) .line_height(LineHeight::Relative(2.0)); row!(