diff --git a/Cargo.lock b/Cargo.lock index 8bdd055..2602ed5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,7 +259,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -328,9 +328,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -500,9 +500,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -840,7 +840,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -906,7 +906,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -1256,6 +1256,15 @@ dependencies = [ "xxhash-rust", ] +[[package]] +name = "iced_on_focus_widget" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554f3ca9708bebb6c42674cff8cbf9f5cd83809d5a7dabd6bbf1d7953a380b5e" +dependencies = [ + "iced", +] + [[package]] name = "iced_renderer" version = "0.12.1" @@ -1378,6 +1387,7 @@ version = "0.1.0" dependencies = [ "iced", "iced_aw", + "iced_on_focus_widget", "smol_str", "ul-next", ] @@ -1815,7 +1825,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -1984,9 +1994,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -2028,7 +2038,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2061,7 +2071,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2154,7 +2164,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2199,9 +2209,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", @@ -2209,7 +2219,7 @@ dependencies = [ "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2250,7 +2260,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", "version_check", "yansi", ] @@ -2483,22 +2493,22 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2710,9 +2720,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -2754,7 +2764,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -2889,7 +2899,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] @@ -3043,7 +3053,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", "wasm-bindgen-shared", ] @@ -3077,7 +3087,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3745,9 +3755,9 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d491ee231a51ae64a5b762114c3ac2104b967aadba1de45c86ca42cf051513b7" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xkbcommon-dl" @@ -3815,7 +3825,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.74", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b929810..fb84c80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,9 @@ panic = "abort" rustflags = ["-Z", "threads=8"] [dependencies] -iced = { version = "0.12.1", features = ["advanced", "image", "tokio", "lazy"] } +iced = { version = "0.12.1", features = ["advanced", "image", "tokio", "lazy"]} iced_aw = { version = "0.9.3", features = ["tab_bar", "icons"] } +iced_on_focus_widget = "0.1.0" # reqwest = { version = "0.12.5", features = ["blocking"] } smol_str = "0.2.2" ul-next = { version = "0.2.0", optional = true } diff --git a/examples/basic_browser.rs b/examples/basic_browser.rs index da94ef3..1814121 100644 --- a/examples/basic_browser.rs +++ b/examples/basic_browser.rs @@ -4,7 +4,7 @@ use iced::{executor, Command, Subscription}; use iced::{widget::column, Application, Settings, Theme}; use iced_aw::BOOTSTRAP_FONT_BYTES; -use icy_browser::{browser_view, nav_bar, tab_bar, State, Ultralight}; +use icy_browser::{browser_view, nav_bar, tab_bar, BrowserView, NavBar, State, TabBar, Ultralight}; use std::borrow::Borrow; use std::time::Duration; @@ -18,10 +18,18 @@ fn main() -> Result<(), iced::Error> { Browser::run(settings) } -struct Browser(State); +struct Browser { + state: State, + tab_bar: TabBar, + nav_bar: NavBar, + browser_view: BrowserView, +} -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub enum Message { + TabBar(tab_bar::Message), + NavBar(nav_bar::Message), + BrowserView(browser_view::Message), DoWork, } @@ -32,7 +40,20 @@ impl Application for Browser { type Theme = Theme; fn new(_flags: Self::Flags) -> (Self, Command) { - (Self(State::new_ultralight()), Command::none()) + let state = State::new_ultralight(); + let tab_bar = tab_bar(state.clone()); + let nav_bar = nav_bar(state.clone()); + let browser_view = browser_view(state.clone()); + + ( + Self { + state, + tab_bar, + nav_bar, + browser_view, + }, + Command::none(), + ) } fn title(&self) -> String { @@ -49,15 +70,24 @@ impl Application for Browser { fn update(&mut self, message: Self::Message) -> Command { match message { - Message::DoWork => self.0.borrow().do_work(), + Message::DoWork => self.state.borrow().do_work(), + Message::NavBar(nav_bar_message) => match self.nav_bar.update(nav_bar_message) { + nav_bar::Action::None => {} + }, + Message::TabBar(tab_bar_message) => match self.tab_bar.update(tab_bar_message) { + tab_bar::Action::None => {} + }, + Message::BrowserView(browser_view) => match self.browser_view.update(browser_view) { + browser_view::Action::None => {} + }, } Command::none() } fn view(&self) -> iced::Element<'_, Self::Message> { - let tab_bar = tab_bar(self.0.clone()); - let nav_bar = nav_bar(self.0.clone()); - let browser_view = browser_view(self.0.clone()); + let tab_bar = self.tab_bar.view().map(Message::TabBar); + let nav_bar = self.nav_bar.view().map(Message::NavBar); + let browser_view = self.browser_view.view().map(Message::BrowserView); column!(tab_bar, nav_bar, browser_view).into() } diff --git a/src/engines/ultralight.rs b/src/engines/ultralight.rs index 5e0f68d..f156fe2 100644 --- a/src/engines/ultralight.rs +++ b/src/engines/ultralight.rs @@ -537,51 +537,48 @@ fn iced_key_to_ultralight_key( _ => return None, }, #[cfg(unix)] - keyboard::Key::Character(key) => { - println!("key: '{}'", key); - match key.as_str() { - "1" => (VirtualKeyCode::Key1, 2), - "2" => (VirtualKeyCode::Key2, 3), - "3" => (VirtualKeyCode::Key3, 4), - "4" => (VirtualKeyCode::Key4, 5), - "5" => (VirtualKeyCode::Key5, 6), - "6" => (VirtualKeyCode::Key6, 7), - "7" => (VirtualKeyCode::Key7, 8), - "8" => (VirtualKeyCode::Key8, 9), - "9" => (VirtualKeyCode::Key9, 10), - "0" => (VirtualKeyCode::Key0, 11), - "a" => (VirtualKeyCode::A, 30), - "b" => (VirtualKeyCode::B, 48), - "c" => (VirtualKeyCode::C, 46), - "d" => (VirtualKeyCode::D, 32), - "e" => (VirtualKeyCode::E, 18), - "f" => (VirtualKeyCode::F, 33), - "g" => (VirtualKeyCode::G, 34), - "h" => (VirtualKeyCode::H, 35), - "i" => (VirtualKeyCode::I, 23), - "j" => (VirtualKeyCode::J, 36), - "k" => (VirtualKeyCode::K, 37), - "l" => (VirtualKeyCode::L, 38), - "m" => (VirtualKeyCode::M, 50), - "n" => (VirtualKeyCode::N, 49), - "o" => (VirtualKeyCode::O, 24), - "p" => (VirtualKeyCode::P, 25), - "q" => (VirtualKeyCode::Q, 16), - "r" => (VirtualKeyCode::R, 19), - "s" => (VirtualKeyCode::S, 31), - "t" => (VirtualKeyCode::T, 20), - "u" => (VirtualKeyCode::U, 22), - "v" => (VirtualKeyCode::V, 47), - "w" => (VirtualKeyCode::W, 17), - "x" => (VirtualKeyCode::X, 47), - "y" => (VirtualKeyCode::Y, 21), - "z" => (VirtualKeyCode::Z, 44), - "," => (VirtualKeyCode::OemComma, 51), - "." => (VirtualKeyCode::OemPeriod, 52), - ";" => (VirtualKeyCode::OemPeriod, 39), - _ => return None, - } - } + keyboard::Key::Character(key) => match key.as_str() { + "1" => (VirtualKeyCode::Key1, 2), + "2" => (VirtualKeyCode::Key2, 3), + "3" => (VirtualKeyCode::Key3, 4), + "4" => (VirtualKeyCode::Key4, 5), + "5" => (VirtualKeyCode::Key5, 6), + "6" => (VirtualKeyCode::Key6, 7), + "7" => (VirtualKeyCode::Key7, 8), + "8" => (VirtualKeyCode::Key8, 9), + "9" => (VirtualKeyCode::Key9, 10), + "0" => (VirtualKeyCode::Key0, 11), + "a" => (VirtualKeyCode::A, 30), + "b" => (VirtualKeyCode::B, 48), + "c" => (VirtualKeyCode::C, 46), + "d" => (VirtualKeyCode::D, 32), + "e" => (VirtualKeyCode::E, 18), + "f" => (VirtualKeyCode::F, 33), + "g" => (VirtualKeyCode::G, 34), + "h" => (VirtualKeyCode::H, 35), + "i" => (VirtualKeyCode::I, 23), + "j" => (VirtualKeyCode::J, 36), + "k" => (VirtualKeyCode::K, 37), + "l" => (VirtualKeyCode::L, 38), + "m" => (VirtualKeyCode::M, 50), + "n" => (VirtualKeyCode::N, 49), + "o" => (VirtualKeyCode::O, 24), + "p" => (VirtualKeyCode::P, 25), + "q" => (VirtualKeyCode::Q, 16), + "r" => (VirtualKeyCode::R, 19), + "s" => (VirtualKeyCode::S, 31), + "t" => (VirtualKeyCode::T, 20), + "u" => (VirtualKeyCode::U, 22), + "v" => (VirtualKeyCode::V, 47), + "w" => (VirtualKeyCode::W, 17), + "x" => (VirtualKeyCode::X, 47), + "y" => (VirtualKeyCode::Y, 21), + "z" => (VirtualKeyCode::Z, 44), + "," => (VirtualKeyCode::OemComma, 51), + "." => (VirtualKeyCode::OemPeriod, 52), + ";" => (VirtualKeyCode::OemPeriod, 39), + _ => return None, + }, keyboard::Key::Unidentified => return None, } } else { diff --git a/src/lib.rs b/src/lib.rs index 77caa0a..6cf3892 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ pub use engines::BrowserEngine; pub use engines::ultralight::Ultralight; mod widgets; -pub use widgets::{browser_view, nav_bar, tab_bar, State}; +pub use widgets::{browser_view, nav_bar, tab_bar, BrowserView, NavBar, State, TabBar}; fn bgr_to_rgb(image: Vec) -> Vec { assert_eq!(image.len() % 4, 0); diff --git a/src/widgets/browser_view.rs b/src/widgets/browser_view.rs index 892c0d2..5a73e44 100644 --- a/src/widgets/browser_view.rs +++ b/src/widgets/browser_view.rs @@ -1,127 +1,159 @@ +use iced::Element; + use super::{BrowserEngine, State}; -use crate::create_image; - -use iced::advanced::{ - self, - graphics::core::event, - layout, mouse, - renderer::{self}, - widget::Tree, - Clipboard, Layout, Shell, Widget, -}; -use iced::event::Status; -use iced::widget::image::{Handle, Image}; -use iced::{theme::Theme, Element, Event, Length, Rectangle, Size}; // helper function to create browser view pub fn browser_view(state: State) -> BrowserView { BrowserView::new(state) } +#[derive(Debug, Clone)] +pub enum Message {} + +#[derive(Debug, Clone)] +pub enum Action { + None, +} + +// Wrapper around BrowserView to keep consistency with other widgets pub struct BrowserView(State); impl BrowserView { pub fn new(state: State) -> Self { Self(state) } + + pub fn update(&mut self, message: Message) -> Action { + match message {} + Action::None + } + + pub fn view(&self) -> Element { + browser_view::BrowserView::new(self.0.clone()).into() + } } -impl Widget for BrowserView -where - Renderer: iced::advanced::image::Renderer, - Engine: BrowserEngine, -{ - fn size(&self) -> Size { - Size { - width: Length::Fill, - height: Length::Fill, +mod browser_view { + use super::{BrowserEngine, State}; + use crate::create_image; + + use iced::advanced::{ + self, + graphics::core::event, + layout, mouse, + renderer::{self}, + widget::Tree, + Clipboard, Layout, Shell, Widget, + }; + use iced::event::Status; + use iced::widget::image::{Handle, Image}; + use iced::{theme::Theme, Element, Event, Length, Rectangle, Size}; + + pub struct BrowserView(State); + + impl BrowserView { + pub fn new(state: State) -> Self { + Self(state) } } - fn layout( - &self, - _tree: &mut Tree, - _renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - layout::Node::new(limits.max()) - } + impl Widget for BrowserView + where + Renderer: iced::advanced::image::Renderer, + Engine: BrowserEngine, + { + fn size(&self) -> Size { + Size { + width: Length::Fill, + height: Length::Fill, + } + } - fn draw( - &self, - tree: &Tree, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - ) { - let mut webengine = self.0.webengine.borrow_mut(); - - let (current_size, allowed_size) = (webengine.size(), layout.bounds().size()); - if current_size.0 != allowed_size.width as u32 - || current_size.1 != allowed_size.height as u32 - { - webengine.resize(allowed_size.width as u32, allowed_size.height as u32); + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + layout::Node::new(limits.max()) } - let image_data = webengine.pixel_buffer().unwrap(); - let image = create_image(image_data, current_size.0, current_size.1, true); + fn draw( + &self, + tree: &Tree, + renderer: &mut Renderer, + theme: &Theme, + style: &renderer::Style, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + ) { + let mut webengine = self.0.webengine.borrow_mut(); - as Widget>::draw( - &image, tree, renderer, theme, style, layout, cursor, viewport, - ) - } + let (current_size, allowed_size) = (webengine.size(), layout.bounds().size()); + if current_size.0 != allowed_size.width as u32 + || current_size.1 != allowed_size.height as u32 + { + webengine.resize(allowed_size.width as u32, allowed_size.height as u32); + } + + let image_data = webengine.pixel_buffer().unwrap(); + let image = create_image(image_data, current_size.0, current_size.1, true); - fn mouse_interaction( - &self, - _state: &Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - _viewport: &Rectangle, - _renderer: &Renderer, - ) -> mouse::Interaction { - if cursor.is_over(layout.bounds()) { - self.0.webengine.borrow().get_cursor() - } else { - mouse::Interaction::Idle + as Widget>::draw( + &image, tree, renderer, theme, style, layout, cursor, viewport, + ) } - } - fn on_event( - &mut self, - _state: &mut Tree, - event: Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - _renderer: &Renderer, - _clipboard: &mut dyn Clipboard, - _shell: &mut Shell<'_, Message>, - _viewport: &Rectangle, - ) -> event::Status { - let mut webengine = self.0.webengine.borrow_mut(); - - match event { - Event::Keyboard(keyboard_event) => webengine.handle_keyboard_event(keyboard_event), - Event::Mouse(mouse_event) => { - if let Some(point) = cursor.position_in(layout.bounds()) { - webengine.handle_mouse_event(point, mouse_event) - } else { - Status::Ignored + fn mouse_interaction( + &self, + _state: &Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, + _viewport: &Rectangle, + _renderer: &Renderer, + ) -> mouse::Interaction { + if cursor.is_over(layout.bounds()) { + self.0.webengine.borrow().get_cursor() + } else { + mouse::Interaction::Idle + } + } + + fn on_event( + &mut self, + _state: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor: mouse::Cursor, + _renderer: &Renderer, + _clipboard: &mut dyn Clipboard, + _shell: &mut Shell<'_, Message>, + _viewport: &Rectangle, + ) -> event::Status { + let mut webengine = self.0.webengine.borrow_mut(); + + match event { + Event::Keyboard(keyboard_event) => webengine.handle_keyboard_event(keyboard_event), + Event::Mouse(mouse_event) => { + if let Some(point) = cursor.position_in(layout.bounds()) { + webengine.handle_mouse_event(point, mouse_event) + } else { + Status::Ignored + } } + _ => Status::Ignored, } - _ => Status::Ignored, } } -} -impl<'a, Message, Renderer, Engine: BrowserEngine + 'a> From> - for Element<'a, Message, Theme, Renderer> -where - Renderer: advanced::Renderer + advanced::image::Renderer, -{ - fn from(widget: BrowserView) -> Self { - Self::new(widget) + impl<'a, Message, Renderer, Engine: BrowserEngine + 'a> From> + for Element<'a, Message, Theme, Renderer> + where + Renderer: advanced::Renderer + advanced::image::Renderer, + { + fn from(widget: BrowserView) -> Self { + Self::new(widget) + } } } diff --git a/src/widgets/hover_text_input.rs b/src/widgets/hover_text_input.rs deleted file mode 100644 index 14616dd..0000000 --- a/src/widgets/hover_text_input.rs +++ /dev/null @@ -1,51 +0,0 @@ -// use iced::advanced::{graphics::core::Element, widget::Operation}; -// use iced::widget::{component, container, text_input, text_input::Id, Component, TextInput}; -// use iced::{theme::Theme, Renderer}; - -// pub struct HoverTextInput<'a, Message> { -// placeholder: String, -// text: String, -// // id: Id, -// text_input: TextInput<'a, Message>, -// } - -// impl HoverTextInput<'_, Message> { -// pub fn new() -> Self { -// HoverTextInput { -// placeholder: String::from("hello"), -// text: String::from("there"), -// // id: Id::unique(), -// text_input: text_input("fasdf", "here"), -// } -// } -// } - -// #[derive(Clone)] -// pub enum Event {} - -// impl Component for HoverTextInput<'_, Message> { -// type State = (); -// type Event = Event; - -// fn update(&mut self, _state: &mut Self::State, event: Self::Event) -> Option { -// match event {}; -// None -// } - -// fn view(&self, _state: &Self::State) -> Element<'_, Self::Event, Theme, Renderer> { -// container(self.text_input).into() -// } - -// fn operate(&self, state: &mut Self::State, operation: &mut dyn Operation) { -// operation.text_input(self.text_input, None) -// // operation.focusable(state, self.id) -// } -// } - -// impl<'a, Message: 'a + Clone> From> -// for Element<'a, Message, Theme, Renderer> -// { -// fn from(widget: HoverTextInput) -> Self { -// component(widget) -// } -// } diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 28430bc..aefddee 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -2,22 +2,18 @@ use crate::engines::{self, BrowserEngine}; use std::{cell::RefCell, rc::Rc}; -mod browser_view; +pub mod browser_view; #[allow(unused)] pub use browser_view::{browser_view, BrowserView}; -mod nav_bar; +pub mod nav_bar; #[allow(unused)] pub use nav_bar::{nav_bar, NavBar}; -mod tab_bar; +pub mod tab_bar; #[allow(unused)] pub use tab_bar::{tab_bar, TabBar}; -#[allow(unused)] -// pub use hover_text_input::HoverTextInput; -mod hover_text_input; - // Configures the Browser Widget #[derive(Debug, Clone)] pub struct Config { diff --git a/src/widgets/nav_bar.rs b/src/widgets/nav_bar.rs index 7398db0..f718421 100644 --- a/src/widgets/nav_bar.rs +++ b/src/widgets/nav_bar.rs @@ -1,14 +1,17 @@ +use iced::widget::{row, text::LineHeight, text_input, tooltip, tooltip::Position, Button, Space}; +use iced::{Element, Length}; +use iced_aw::core::icons::bootstrap::{icon_to_text, Bootstrap}; +use iced_on_focus_widget::hoverable; + use super::{BrowserEngine, State}; -use iced::widget::{ - component, row, text::LineHeight, text_input, tooltip, tooltip::Position, Button, Component, - Space, -}; -use iced::{theme::Theme, Element, Length, Size}; -use iced_aw::core::icons::bootstrap::{icon_to_text, Bootstrap}; +#[derive(Debug, Clone)] +pub enum Action { + None, +} #[derive(Debug, Clone)] -pub enum Event { +pub enum Message { Backward, Forward, Refresh, @@ -16,6 +19,8 @@ pub enum Event { UrlChanged(String), UrlPasted(String), UrlSubmitted, + OnFocus, + OnUnfocus, } // helper function to create navigation bar @@ -25,6 +30,7 @@ pub fn nav_bar(state: State) -> NavBar { // Simple navigation bar widget pub struct NavBar { + search_focused: bool, state: State, url: String, } @@ -34,81 +40,77 @@ impl NavBar { let (_, tab) = state.webengine.borrow().current_tab(); Self { + search_focused: false, state, url: tab.url, } } -} -impl Component for NavBar { - type State = (); - type Event = Event; - - fn update(&mut self, _state: &mut Self::State, event: Event) -> Option { + pub fn update(&mut self, message: Message) -> Action { let webengine = self.state.webengine.borrow(); - match event { - Event::Backward => webengine.go_back(), - Event::Forward => webengine.go_forward(), - Event::Refresh => webengine.refresh(), - Event::Home => webengine.goto_url(&self.state.config.start_page), - Event::UrlChanged(url) => self.url = url, - Event::UrlPasted(url) => { + match message { + Message::Backward => webengine.go_back(), + Message::Forward => webengine.go_forward(), + Message::Refresh => webengine.refresh(), + Message::Home => webengine.goto_url(&self.state.config.start_page), + Message::UrlChanged(url) => self.url = url, + Message::UrlPasted(url) => { webengine.goto_url(&url); self.url = url; } - Event::UrlSubmitted => webengine.goto_url(&self.url), + Message::UrlSubmitted => webengine.goto_url(&self.url), + Message::OnFocus => self.search_focused = true, + Message::OnUnfocus => self.search_focused = false, + } + + if !self.search_focused { + self.url = webengine.get_url().unwrap() } - None + + Action::None } - fn view(&self, _state: &Self::State) -> Element<'_, Event, Theme> { + pub fn view(&self) -> Element { let back = tooltip_helper( Button::new(icon_to_text(Bootstrap::ChevronBarLeft)) - .on_press(Event::Backward) + .on_press(Message::Backward) .into(), "Go Back", ); let forward = tooltip_helper( Button::new(icon_to_text(Bootstrap::ChevronBarRight)) - .on_press(Event::Forward) + .on_press(Message::Forward) .into(), "Go Forward", ); let home = tooltip_helper( Button::new(icon_to_text(Bootstrap::HouseDoor)) - .on_press(Event::Home) + .on_press(Message::Home) .into(), "Go Home", ); let refresh = tooltip_helper( Button::new(icon_to_text(Bootstrap::ArrowCounterclockwise)) - .on_press(Event::Refresh) + .on_press(Message::Refresh) .into(), "Refresh", ); let space = Space::new(Length::Fill, Length::Shrink); let space2 = Space::new(Length::Fill, Length::Shrink); - let search = text_input("https://site.com", &self.url) - .on_input(Event::UrlChanged) - .on_paste(Event::UrlPasted) - .on_submit(Event::UrlSubmitted) - .line_height(LineHeight::Relative(2.0)); + let search = hoverable( + text_input("https://site.com", &self.url) + .on_input(Message::UrlChanged) + .on_paste(Message::UrlPasted) + .on_submit(Message::UrlSubmitted) + .line_height(LineHeight::Relative(2.0)) + .into(), + ) + .on_focus(Message::OnFocus) + .on_unfocus(Message::OnUnfocus); row!(back, forward, home, refresh, space, search, space2).into() } - - fn size_hint(&self) -> Size { - Size { - width: Length::Fill, - height: Length::Shrink, - } - } -} -impl<'a, Message: 'a, Engine: BrowserEngine + 'a> From> for Element<'a, Message> { - fn from(widget: NavBar) -> Self { - component(widget) - } } fn tooltip_helper<'a, Message: 'a>( diff --git a/src/widgets/tab_bar.rs b/src/widgets/tab_bar.rs index e203f7d..f0f3519 100644 --- a/src/widgets/tab_bar.rs +++ b/src/widgets/tab_bar.rs @@ -1,12 +1,17 @@ -use super::{BrowserEngine, State}; - -use iced::widget::{component, row, tooltip, Button, Component}; -use iced::{self, theme::Theme, Element, Length, Size}; +use iced::widget::{row, tooltip, Button}; +use iced::{self, Element, Length}; use iced_aw::core::icons::bootstrap::{icon_to_text, Bootstrap}; use iced_aw::{TabBar as TB, TabLabel}; +use super::{BrowserEngine, State}; + #[derive(Debug, Clone)] -pub enum Event { +pub enum Action { + None, +} + +#[derive(Debug, Clone)] +pub enum Message { TabSelected(usize), TabClosed(usize), NewTab, @@ -26,42 +31,38 @@ impl TabBar { pub fn new(state: State) -> Self { Self { state } } -} -impl Component for TabBar { - type State = (); - type Event = Event; - - fn update(&mut self, _state: &mut Self::State, event: Event) -> Option { + pub fn update(&mut self, event: Message) -> Action { let mut webengine = self.state.webengine.borrow_mut(); match event { - Event::TabSelected(index) => webengine.goto_tab(index as u32).unwrap(), - Event::TabClosed(index) => webengine.close_tab(index as u32), - Event::NewTab => webengine.new_tab(&self.state.config.start_page), + Message::TabSelected(index) => webengine.goto_tab(index as u32).unwrap(), + Message::TabClosed(index) => webengine.close_tab(index as u32), + Message::NewTab => webengine.new_tab(&self.state.config.start_page), } - None + + Action::None } - fn view(&self, _state: &Self::State) -> Element<'_, Event, Theme> { + pub fn view(&self) -> Element { let webengine = self.state.webengine.borrow(); let tab_bar = webengine .get_tabs() .iter() - .fold(TB::new(Event::TabSelected), |tab_bar, tab| { + .fold(TB::new(Message::TabSelected), |tab_bar, tab| { let idx = tab_bar.size(); tab_bar.push(idx, TabLabel::Text(tab.title.to_owned())) }) .set_active_tab(&webengine.current_tab().0) - .on_close(Event::TabClosed) + .on_close(Message::TabClosed) .tab_width(Length::Shrink) .spacing(5.0) .padding(5.0); let new_tab = tooltip( Button::new(icon_to_text(Bootstrap::Plus)) - .on_press(Event::NewTab) + .on_press(Message::NewTab) .padding(5.0), "New Tab", tooltip::Position::Bottom, @@ -69,16 +70,4 @@ impl Component for TabBar { row!(tab_bar, new_tab).into() } - - fn size_hint(&self) -> Size { - Size { - width: Length::Fill, - height: Length::Shrink, - } - } -} -impl<'a, Message: 'a, Engine: BrowserEngine + 'a> From> for Element<'a, Message> { - fn from(widget: TabBar) -> Self { - component(widget) - } }