From 5d697fb77cbea59260365571c91d002442caf910 Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Sun, 6 Oct 2024 14:20:36 -0600 Subject: [PATCH] refactor --- README.md | 15 +- examples/basic_browser.rs | 10 +- examples/custom_widgets.rs | 86 +++++------- examples/keyboard_driven.rs | 22 +-- src/helpers.rs | 102 ++++++++++++++ src/lib.rs | 109 +-------------- src/widgets/mod.rs | 266 ++++++++++++++---------------------- 7 files changed, 264 insertions(+), 346 deletions(-) create mode 100644 src/helpers.rs diff --git a/README.md b/README.md index 101c9b3..e3fdff5 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,14 @@ ``` Rust use iced::{Settings, Task, Theme}; -use icy_browser::{get_fonts, BasicBrowser, Bookmark, Message}; +use icy_browser::{get_fonts, Bookmark, IcyBrowser, Message, Ultralight}; -fn run() -> (BasicBrowser, Task) { +fn run() -> (IcyBrowser, Task) { ( - BasicBrowser::new_basic() + IcyBrowser::new() .with_tab_bar() .with_nav_bar() - .with_bookmark_bar(vec![Bookmark::new( - "https://www.rust-lang.org", - "rust-lang.org", - )]) + .with_bookmark_bar(&[Bookmark::new("https://www.rust-lang.org", "rust-lang.org")]) .build(), Task::none(), ) @@ -44,8 +41,8 @@ fn main() -> iced::Result { ..Default::default() }; - iced::application("Basic Browser", BasicBrowser::update, BasicBrowser::view) - .subscription(BasicBrowser::subscription) + iced::application("Basic Browser", IcyBrowser::update, IcyBrowser::view) + .subscription(IcyBrowser::subscription) .settings(settings) .theme(|_| Theme::Dark) .run_with(run) diff --git a/examples/basic_browser.rs b/examples/basic_browser.rs index beae140..ee8d680 100644 --- a/examples/basic_browser.rs +++ b/examples/basic_browser.rs @@ -1,11 +1,11 @@ // Simple browser with familiar browser widgets and the ultralight(webkit) webengine as a backend use iced::{Settings, Task, Theme}; -use icy_browser::{get_fonts, BasicBrowser, Bookmark, Message}; +use icy_browser::{get_fonts, Bookmark, IcyBrowser, Message, Ultralight}; -fn run() -> (BasicBrowser, Task) { +fn run() -> (IcyBrowser, Task) { ( - BasicBrowser::new_basic() + IcyBrowser::new() .with_tab_bar() .with_nav_bar() .with_bookmark_bar(&[Bookmark::new("https://www.rust-lang.org", "rust-lang.org")]) @@ -20,8 +20,8 @@ fn main() -> iced::Result { ..Default::default() }; - iced::application("Basic Browser", BasicBrowser::update, BasicBrowser::view) - .subscription(BasicBrowser::subscription) + iced::application("Basic Browser", IcyBrowser::update, IcyBrowser::view) + .subscription(IcyBrowser::subscription) .settings(settings) .theme(|_| Theme::Dark) .run_with(run) diff --git a/examples/custom_widgets.rs b/examples/custom_widgets.rs index b1f9454..dd280fe 100644 --- a/examples/custom_widgets.rs +++ b/examples/custom_widgets.rs @@ -1,14 +1,11 @@ // Custom view example with rainbow border -use iced::widget::{column, container}; +use iced::widget::container; use iced::{time, Border}; use iced::{Color, Element, Length, Settings, Subscription, Task, Theme}; use std::time::{Duration, Instant}; -use icy_browser::{ - browser_view, get_fonts, hoverable, nav_bar, tab_bar, widgets, BrowserEngine, BrowserWidget, - Ultralight, -}; +use icy_browser::{get_fonts, widgets, IcyBrowser, Ultralight}; fn main() -> iced::Result { let settings = Settings { @@ -37,29 +34,26 @@ struct CustomWidgetState { } struct Browser { - widgets: BrowserWidget, + icy_browser: IcyBrowser, + custom_widget_state: CustomWidgetState, } impl Default for Browser { fn default() -> Self { Self { - widgets: BrowserWidget::new() - .with_custom_view( - custom_view, - CustomWidgetState { - border_colors: vec![ - Color::from_rgb(1.0, 0.0, 0.0), // Red - Color::from_rgb(1.0, 0.5, 0.0), // Orange - Color::from_rgb(1.0, 1.0, 0.0), // Yellow - Color::from_rgb(0.0, 1.0, 0.0), // Green - Color::from_rgb(0.0, 0.0, 1.0), // Blue - Color::from_rgb(0.29, 0.0, 0.51), // Indigo - Color::from_rgb(0.56, 0.0, 1.0), // Violet - ], - start_time: Instant::now(), - }, - ) - .build(), + icy_browser: IcyBrowser::new().with_tab_bar().with_nav_bar().build(), + custom_widget_state: CustomWidgetState { + border_colors: vec![ + Color::from_rgb(1.0, 0.0, 0.0), // Red + Color::from_rgb(1.0, 0.5, 0.0), // Orange + Color::from_rgb(1.0, 1.0, 0.0), // Yellow + Color::from_rgb(0.0, 1.0, 0.0), // Green + Color::from_rgb(0.0, 0.0, 1.0), // Blue + Color::from_rgb(0.29, 0.0, 0.51), // Indigo + Color::from_rgb(0.56, 0.0, 1.0), // Violet + ], + start_time: Instant::now(), + }, } } } @@ -67,14 +61,26 @@ impl Default for Browser { impl Browser { fn update(&mut self, message: Message) -> Task { match message { - Message::BrowserWidget(msg) => self.widgets.update(msg).map(Message::BrowserWidget), - Message::Update => self.widgets.force_update().map(Message::BrowserWidget), + Message::BrowserWidget(msg) => self.icy_browser.update(msg).map(Message::BrowserWidget), + Message::Update => self.icy_browser.force_update().map(Message::BrowserWidget), Message::Tick => Task::none(), // Tick } } fn view(&self) -> Element { - self.widgets.view().map(Message::BrowserWidget) + let elapsed = self.custom_widget_state.start_time.elapsed().as_secs_f32(); + let color_index = (elapsed * 2.0) as usize % self.custom_widget_state.border_colors.len(); + let color = self.custom_widget_state.border_colors[color_index]; + + container(self.icy_browser.view().map(Message::BrowserWidget)) + .center_x(Length::Fill) + .center_y(Length::Fill) + .padding(20) + .style(move |_theme| container::Style { + border: Border::default().color(color).width(20), + ..Default::default() + }) + .into() } fn subscription(&self) -> Subscription { @@ -84,31 +90,3 @@ impl Browser { ]) } } - -fn custom_view( - browser_widget: &BrowserWidget, - widget_state: CustomWidgetState, -) -> Element { - let elapsed = widget_state.start_time.elapsed().as_secs_f32(); - let color_index = (elapsed * 2.0) as usize % widget_state.border_colors.len(); - let color = widget_state.border_colors[color_index]; - - container(column![ - tab_bar(browser_widget.engine().get_tabs()), - hoverable(nav_bar(&browser_widget.nav_bar_state)) - .on_focus_change(icy_browser::Message::UpdateUrl), - browser_view( - browser_widget.view_size, - browser_widget.engine().get_tabs().get_current().get_view(), - !browser_widget.show_overlay, - ), - ]) - .center_x(Length::Fill) - .center_y(Length::Fill) - .padding(20) - .style(move |_theme| container::Style { - border: Border::default().color(color).width(20), - ..Default::default() - }) - .into() -} diff --git a/examples/keyboard_driven.rs b/examples/keyboard_driven.rs index 67f80aa..9b948cc 100644 --- a/examples/keyboard_driven.rs +++ b/examples/keyboard_driven.rs @@ -6,8 +6,8 @@ use iced::{Element, Settings, Subscription, Task}; use std::time::Duration; use icy_browser::{ - get_fonts, widgets, BasicBrowser, Bookmark, BrowserWidget, KeyType, Message as WidgetMessage, - ShortcutBuilder, ShortcutModifier, + get_fonts, widgets, Bookmark, IcyBrowser, KeyType, Message as WidgetMessage, ShortcutBuilder, + ShortcutModifier, Ultralight, }; fn main() -> iced::Result { @@ -33,7 +33,7 @@ pub enum Message { } struct Browser { - widgets: BasicBrowser, + icy_browser: IcyBrowser, } impl Default for Browser { @@ -47,7 +47,7 @@ impl Default for Browser { ], ) .build(); - let widgets = BrowserWidget::new_basic() + let widgets = IcyBrowser::new() .with_custom_shortcuts(shortcuts) .with_tab_bar() .with_bookmark_bar(&[ @@ -60,24 +60,26 @@ impl Default for Browser { ]) .build(); - Self { widgets } + Self { + icy_browser: widgets, + } } } impl Browser { fn update(&mut self, message: Message) -> Task { match message { - Message::BrowserWidget(msg) => self.widgets.update(msg).map(Message::BrowserWidget), - Message::Update => self.widgets.force_update().map(Message::BrowserWidget), + Message::BrowserWidget(msg) => self.icy_browser.update(msg).map(Message::BrowserWidget), + Message::Update => self.icy_browser.force_update().map(Message::BrowserWidget), Message::Event(event) => self - .widgets - .update(widgets::Message::Event(Some(event))) + .icy_browser + .update(widgets::Message::IcedEvent(Some(event))) .map(Message::BrowserWidget), } } fn view(&self) -> Element { - self.widgets.view().map(Message::BrowserWidget) + self.icy_browser.view().map(Message::BrowserWidget) } fn subscription(&self) -> Subscription { diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..9fd9993 --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,102 @@ +use iced::widget::{ + button, + image::{Handle, Image}, + Button, +}; +pub use iced_fonts::BOOTSTRAP_FONT_BYTES; +use std::{borrow::Cow, str::FromStr}; +use url::{ParseError, Url}; + +use super::{Message, PixelFormat}; + +// Helper function to ensure required icons are imported +pub fn get_fonts() -> Vec> { + vec![BOOTSTRAP_FONT_BYTES.into()] +} + +// Image details for passing the view around +#[derive(Debug, Clone)] +pub struct ImageInfo { + pub pixels: Vec, + pub width: u32, + pub height: u32, +} + +impl Default for ImageInfo { + fn default() -> Self { + Self { + pixels: vec![255; (Self::WIDTH as usize * Self::HEIGHT as usize) * 4], + width: Self::WIDTH, + height: Self::HEIGHT, + } + } +} + +impl ImageInfo { + // The default dimentions + const WIDTH: u32 = 800; + const HEIGHT: u32 = 800; + + pub fn new(pixels: Vec, format: PixelFormat, width: u32, height: u32) -> Self { + // R, G, B, A + assert_eq!(pixels.len() % 4, 0); + + let pixels = match format { + PixelFormat::Rgba => pixels, + PixelFormat::Bgra => pixels + .chunks(4) + .flat_map(|chunk| [chunk[2], chunk[1], chunk[0], chunk[3]]) + .collect(), + }; + + Self { + pixels, + width, + height, + } + } + + pub fn as_image(&self) -> Image { + Image::new(Handle::from_rgba( + self.width, + self.height, + self.pixels.clone(), + )) + } +} + +pub fn to_url(url: &str) -> Option { + match Url::parse(url) { + Ok(url) => Some(url), + Err(error) => { + if let ParseError::RelativeUrlWithoutBase = error { + let mut base = String::from("https://"); + base.push_str(url); + Url::parse(&base).ok() + } else { + None + } + } + } +} + +pub type Bookmarks = Vec; + +#[derive(Debug, Clone)] +pub struct Bookmark { + url: Url, + name: String, + // icon: Optional<> +} +impl Bookmark { + pub fn new(url: &str, name: &str) -> Self { + Bookmark { + url: Url::from_str(url).expect("Failed to parse url from bookmark url"), + name: name.to_string(), + } + } + + pub fn as_button(&self) -> Button { + button(self.name.as_str()).on_press(Message::GoToUrl(self.url.to_string())) + } +} diff --git a/src/lib.rs b/src/lib.rs index 93144da..a14bb4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,5 @@ -use iced::widget::{ - button, - image::{Handle, Image}, - Button, -}; pub use iced_fonts::BOOTSTRAP_FONT_BYTES; pub use iced_on_focus_widget::hoverable; -use std::{borrow::Cow, str::FromStr}; -use url::{ParseError, Url}; mod engines; pub use engines::{BrowserEngine, PixelFormat, Tab, TabInfo, Tabs}; @@ -15,104 +8,10 @@ pub use engines::{BrowserEngine, PixelFormat, Tab, TabInfo, Tabs}; pub use engines::ultralight::Ultralight; pub mod widgets; -pub use widgets::{browser_view, command_window, nav_bar, tab_bar, BrowserWidget, Message}; +pub use widgets::{browser_view, command_window, nav_bar, tab_bar, IcyBrowser, Message}; + +mod helpers; +pub use helpers::{get_fonts, to_url, Bookmark, Bookmarks, ImageInfo}; mod shortcut; pub use shortcut::{KeyType, Shortcut, ShortcutBuilder, ShortcutModifier, Shortcuts}; - -// Used when Not using custom views -#[derive(Clone)] -pub struct NoCustomView; - -#[cfg(feature = "ultralight")] -pub type BasicBrowser = BrowserWidget; - -// Helper function to ensure required icons are imported -pub fn get_fonts() -> Vec> { - vec![BOOTSTRAP_FONT_BYTES.into()] -} - -// Image details for passing the view around -#[derive(Debug, Clone)] -pub struct ImageInfo { - pixels: Vec, - width: u32, - height: u32, -} - -impl Default for ImageInfo { - fn default() -> Self { - Self { - pixels: vec![255; (Self::WIDTH as usize * Self::HEIGHT as usize) * 4], - width: Self::WIDTH, - height: Self::HEIGHT, - } - } -} - -impl ImageInfo { - // The default dimentions - const WIDTH: u32 = 800; - const HEIGHT: u32 = 800; - - pub fn new(pixels: Vec, format: PixelFormat, width: u32, height: u32) -> Self { - // R, G, B, A - assert_eq!(pixels.len() % 4, 0); - - let pixels = match format { - PixelFormat::Rgba => pixels, - PixelFormat::Bgra => pixels - .chunks(4) - .flat_map(|chunk| [chunk[2], chunk[1], chunk[0], chunk[3]]) - .collect(), - }; - - Self { - pixels, - width, - height, - } - } - - fn as_image(&self) -> Image { - Image::new(Handle::from_rgba( - self.width, - self.height, - self.pixels.clone(), - )) - } -} - -fn to_url(url: &str) -> Option { - match Url::parse(url) { - Ok(url) => Some(url), - Err(error) => { - if let ParseError::RelativeUrlWithoutBase = error { - let mut base = String::from("https://"); - base.push_str(url); - Url::parse(&base).ok() - } else { - None - } - } - } -} - -#[derive(Debug, Clone)] -pub struct Bookmark { - url: Url, - name: String, - // icon: Optional<> -} -impl Bookmark { - pub fn new(url: &str, name: &str) -> Self { - Bookmark { - url: Url::from_str(url).expect("Failed to parse url from bookmark url"), - name: name.to_string(), - } - } - - pub fn as_button(&self) -> Button { - button(self.name.as_str()).on_press(Message::GoToUrl(self.url.to_string())) - } -} diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 17d4c48..12f6a0f 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,8 +1,7 @@ use command_window::CommandWindowState; -use iced::event::{self, Event}; use iced::keyboard::{self, key}; use iced::widget::{self, column}; -use iced::{mouse, Element, Point, Size, Subscription, Task}; +use iced::{mouse, Element, Event, Point, Size, Subscription, Task}; use iced_on_focus_widget::hoverable; use nav_bar::NavBarState; use std::string::ToString; @@ -13,20 +12,35 @@ use url::Url; mod browser_view; pub use browser_view::browser_view; -mod nav_bar; +pub mod nav_bar; pub use nav_bar::nav_bar; -mod tab_bar; +pub mod tab_bar; pub use tab_bar::tab_bar; -mod bookmark_bar; +pub mod bookmark_bar; pub use bookmark_bar::bookmark_bar; -mod command_window; +pub mod command_window; pub use command_window::command_window; -use crate::Bookmark; -use crate::{engines::BrowserEngine, shortcut::check_shortcut, to_url, ImageInfo, Shortcuts}; +use crate::{ + engines::BrowserEngine, shortcut::check_shortcut, to_url, Bookmark, Bookmarks, ImageInfo, + Shortcuts, +}; + +/// Allows users to implement their own custom view view with custom widgets and configurations +pub trait CustomWidget { + fn update(&mut self, message: Message); + fn view( + &self, + nav_bar_state: NavBarState, + command_window_state: CommandWindowState, + bookmarks: Option>, + shortcuts: Shortcuts, + ); + fn subscription(&self) -> Subscription; +} // Options exist only to have defaults for EnumIter #[derive(Debug, Clone, PartialEq, Display, EnumIter)] @@ -66,7 +80,7 @@ pub enum Message { SendKeyboardEvent(Option), SendMouseEvent(Point, Option), UpdateViewSize(Size), - Event(Option), + IcedEvent(Option), } /// Allows different widgets to interact in their native way @@ -81,46 +95,30 @@ impl Default for TabSelectionType { } } -/// Allows users to create their own views with the same information of native widgets -pub type CustomView = fn( - &BrowserWidget, - custom_view_state: CustomViewState, -) -> Element; - -/// Allows users to create their own updates with the same information of native widgets -pub type CustomUpdate<'a, Engine, CustomViewState> = fn( - &BrowserWidget, - custom_view_state: &mut CustomViewState, -) -> Element<'a, Message>; - -pub struct BrowserWidget { - pub engine: Option, - pub home: Url, - pub nav_bar_state: NavBarState, - pub command_window_state: CommandWindowState, - custom_view: Option>, - custom_view_state: Option, - pub with_tab_bar: bool, - pub with_nav_bar: bool, - pub bookmarks: Option>, - pub show_overlay: bool, - pub shortcuts: Shortcuts, - pub view_size: Size, +pub struct IcyBrowser { + engine: Engine, + home: Url, + nav_bar_state: NavBarState, + command_window_state: CommandWindowState, + with_tab_bar: bool, + with_nav_bar: bool, + bookmarks: Option, + show_overlay: bool, + shortcuts: Shortcuts, + view_size: Size, } -impl Default for BrowserWidget +impl Default for IcyBrowser where Engine: BrowserEngine, { fn default() -> Self { let home = Url::parse(Self::HOME).unwrap(); Self { - engine: None, + engine: Engine::new(), home, nav_bar_state: NavBarState::new(), command_window_state: CommandWindowState::new(), - custom_view: None, - custom_view_state: None, with_tab_bar: false, with_nav_bar: false, bookmarks: None, @@ -131,28 +129,12 @@ where } } -#[cfg(feature = "ultralight")] -use crate::engines::ultralight::Ultralight; - -#[cfg(feature = "ultralight")] -impl BrowserWidget { - pub fn new_basic() -> BrowserWidget { - BrowserWidget { - engine: Some(Ultralight::new()), - ..BrowserWidget::default() - } - } -} - -impl BrowserWidget -where - Engine: BrowserEngine, -{ +impl IcyBrowser { const HOME: &'static str = "https://google.com"; pub fn new() -> Self { Self { - engine: Some(Engine::new()), + engine: Engine::new(), ..Default::default() } } @@ -182,51 +164,34 @@ where self } - pub fn with_custom_view( - mut self, - custom_view: CustomView, - custom_view_state: CustomViewState, - ) -> Self { - self.custom_view = Some(custom_view); - self.custom_view_state = Some(custom_view_state); - self - } - pub fn build(self) -> Self { - assert!(self.engine.is_some()); - let mut build = Self { ..self }; let _ = build.update(Message::CreateTab); // disregaurd task::none() for update build } + /// Allows creation of custom widgets that need interal info pub fn engine(&self) -> &Engine { - self.engine - .as_ref() - .expect("Browser was created without a backend engine!") + &self.engine } - fn engine_mut(&mut self) -> &mut Engine { - self.engine - .as_mut() - .expect("Browser was created without a backend engine!") + /// Allows creation of custom widgets that need interal info + pub fn mut_engine(&mut self) -> &mut Engine { + &mut self.engine } fn update_engine(&mut self) { - self.engine().do_work(); - if self.engine().has_loaded() { - if self.engine().need_render() { - let (format, image_data) = self.engine_mut().pixel_buffer(); + self.engine.do_work(); + if self.engine.has_loaded() { + if self.engine.need_render() { + let (format, image_data) = self.engine.pixel_buffer(); let view = ImageInfo::new( image_data, format, self.view_size.width, self.view_size.height, ); - self.engine_mut() - .get_tabs_mut() - .get_current_mut() - .set_view(view) + self.engine.get_tabs_mut().get_current_mut().set_view(view) } } else { let view = ImageInfo { @@ -234,118 +199,108 @@ where height: self.view_size.height, ..Default::default() }; - self.engine_mut() - .get_tabs_mut() - .get_current_mut() - .set_view(view) + self.engine.get_tabs_mut().get_current_mut().set_view(view) } } /// This is used to periodically update browserview pub fn force_update(&mut self) -> Task { - self.engine().do_work(); - let (format, image_data) = self.engine_mut().pixel_buffer(); + self.engine.do_work(); + let (format, image_data) = self.engine.pixel_buffer(); let view = ImageInfo::new( image_data, format, self.view_size.width, self.view_size.height, ); - self.engine_mut() - .get_tabs_mut() - .get_current_mut() - .set_view(view); + self.engine.get_tabs_mut().get_current_mut().set_view(view); Task::none() } - pub fn update(&mut self, message: Message) -> Task { - let task = match message { + pub fn update(&mut self, event: Message) -> Task { + let task = match event { Message::Update => self.force_update(), Message::UpdateViewSize(size) => { self.view_size = size; - self.engine_mut().resize(size); + self.engine.resize(size); Task::none() } Message::SendKeyboardEvent(event) => { - self.engine() + self.engine .handle_keyboard_event(event.expect("Value cannot be none")); Task::none() } Message::SendMouseEvent(point, event) => { - self.engine_mut() + self.engine .handle_mouse_event(point, event.expect("Value cannot be none")); Task::none() } Message::ChangeTab(index_type) => { let id = match index_type { TabSelectionType::Id(id) => id, - TabSelectionType::Index(index) => { - self.engine_mut().get_tabs().index_to_id(index) - } + TabSelectionType::Index(index) => self.engine.get_tabs().index_to_id(index), }; - self.engine_mut().get_tabs_mut().set_current_id(id); - self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); + self.engine.get_tabs_mut().set_current_id(id); + self.nav_bar_state.0 = self.engine.get_tabs().get_current().url(); Task::none() } Message::CloseCurrentTab => Task::done(Message::CloseTab(TabSelectionType::Id( - self.engine().get_tabs().get_current_id(), + self.engine.get_tabs().get_current_id(), ))), Message::CloseTab(index_type) => { // ensure there is always at least one tab - if self.engine().get_tabs().tabs().len() == 1 { + if self.engine.get_tabs().tabs().len() == 1 { let _ = self.update(Message::CreateTab); // ignore task } let id = match index_type { TabSelectionType::Id(id) => id, - TabSelectionType::Index(index) => { - self.engine_mut().get_tabs().index_to_id(index) - } + TabSelectionType::Index(index) => self.engine.get_tabs().index_to_id(index), }; - self.engine_mut().get_tabs_mut().remove(id); - self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); + self.engine.get_tabs_mut().remove(id); + self.nav_bar_state.0 = self.engine.get_tabs().get_current().url(); Task::none() } Message::CreateTab => { 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( + let tab = self.engine.new_tab( home.clone(), Size::new(bounds.width + 10, bounds.height - 10), ); - let id = self.engine_mut().get_tabs_mut().insert(tab); - self.engine_mut().get_tabs_mut().set_current_id(id); - self.engine_mut().force_need_render(); - self.engine_mut().resize(bounds); - self.engine().goto_url(&home); + let id = self.engine.get_tabs_mut().insert(tab); + self.engine.get_tabs_mut().set_current_id(id); + self.engine.force_need_render(); + self.engine.resize(bounds); + self.engine.goto_url(&home); Task::none() } Message::GoBackward => { - self.engine().go_back(); - self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); + self.engine.go_back(); + self.nav_bar_state.0 = self.engine.get_tabs().get_current().url(); Task::none() } Message::GoForward => { - self.engine().go_forward(); - self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); + self.engine.go_forward(); + self.nav_bar_state.0 = self.engine.get_tabs().get_current().url(); Task::none() } Message::Refresh => { - self.engine().refresh(); + self.engine.refresh(); Task::none() } Message::GoHome => { - self.engine().goto_url(&self.home); + self.engine.goto_url(&self.home); Task::none() } Message::GoToUrl(url) => { - self.engine().goto_url(&to_url(&url).unwrap()); + self.engine.goto_url(&to_url(&url).unwrap()); Task::none() } Message::UpdateUrl => { - self.nav_bar_state.0 = self.engine().get_tabs().get_current().url(); + self.nav_bar_state.0 = self.engine.get_tabs().get_current().url(); Task::none() } Message::UrlChanged(url) => { @@ -379,7 +334,7 @@ where self.show_overlay = false; widget::focus_next() } - Message::Event(event) => { + Message::IcedEvent(event) => { match event { Some(Event::Keyboard(key)) => { if let iced::keyboard::Event::KeyPressed { @@ -424,52 +379,37 @@ where } pub fn view(&self) -> Element { - match self.custom_view { - Some(custom_view) => { - if let Some(state) = &self.custom_view_state { - custom_view(self, state.clone()) - } else { - panic!( - "If Custom View is set, Custom View State must be set too. Use () if unused", - ) - } - } - None => { - let mut column = column![]; - - if self.with_tab_bar { - column = column.push(tab_bar(self.engine().get_tabs())) - } - if self.with_nav_bar { - column = column.push( - hoverable(nav_bar(&self.nav_bar_state)).on_focus_change(Message::UpdateUrl), - ) - } - if let Some(bookmarks) = self.bookmarks.as_ref() { - column = column.push(bookmark_bar(bookmarks)) - } + let mut column = column![]; - let browser_view = browser_view( - self.view_size, - self.engine().get_tabs().get_current().get_view(), - !self.show_overlay, - ); - if self.show_overlay { - column = column.push(command_window(browser_view, &self.command_window_state)) - } else { - column = column.push(browser_view); - } + if self.with_tab_bar { + column = column.push(tab_bar(self.engine.get_tabs())) + } + if self.with_nav_bar { + column = column + .push(hoverable(nav_bar(&self.nav_bar_state)).on_focus_change(Message::UpdateUrl)) + } + if let Some(bookmarks) = self.bookmarks.as_ref() { + column = column.push(bookmark_bar(bookmarks)) + } - column.into() - } + let browser_view = browser_view( + self.view_size, + self.engine.get_tabs().get_current().get_view(), + !self.show_overlay, + ); + if self.show_overlay { + column = column.push(command_window(browser_view, &self.command_window_state)) + } else { + column = column.push(browser_view); } + + column.into() } pub fn subscription(&self) -> Subscription { Subscription::batch([ iced::time::every(Duration::from_millis(10)).map(move |_| Message::Update), - // This is needed for child widgets such as overlay to detect Key events - event::listen().map(|e: Event| Message::Event(Some(e))), + iced::event::listen().map(|e: iced::Event| Message::IcedEvent(Some(e))), ]) } }