diff options
Diffstat (limited to '')
| -rw-r--r-- | src/appearance.rs | 50 | ||||
| -rw-r--r-- | src/config.rs | 2 | ||||
| -rw-r--r-- | src/dialog.rs | 4 | ||||
| -rw-r--r-- | src/main.rs | 99 | ||||
| -rw-r--r-- | src/panes/designer_view.rs | 2 | ||||
| -rw-r--r-- | src/types.rs | 4 | ||||
| -rw-r--r-- | src/types/project.rs | 16 |
7 files changed, 117 insertions, 60 deletions
diff --git a/src/appearance.rs b/src/appearance.rs index 4d73ec5..0af9879 100644 --- a/src/appearance.rs +++ b/src/appearance.rs @@ -2,31 +2,31 @@ use std::sync::Arc; use iced_material::Theme; -pub fn iced_theme_from_str(theme_name: &str) -> iced::Theme { +pub fn iced_theme_from_str(theme_name: &str) -> Option<iced::Theme> { match theme_name { - "Light" => iced::Theme::Light, - "Dark" => iced::Theme::Dark, - "Dracula" => iced::Theme::Dracula, - "Nord" => iced::Theme::Nord, - "Solarized Light" => iced::Theme::SolarizedLight, - "Solarized Dark" => iced::Theme::SolarizedDark, - "Gruvbox Light" => iced::Theme::GruvboxLight, - "Gruvbox Dark" => iced::Theme::GruvboxDark, - "Catppuccin Latte" => iced::Theme::CatppuccinLatte, - "Catppuccin Frappé" => iced::Theme::CatppuccinFrappe, - "Catppuccin Macchiato" => iced::Theme::CatppuccinMacchiato, - "Catppuccin Mocha" => iced::Theme::CatppuccinMocha, - "Tokyo Night" => iced::Theme::TokyoNight, - "Tokyo Night Storm" => iced::Theme::TokyoNightStorm, - "Tokyo Night Light" => iced::Theme::TokyoNightLight, - "Kanagawa Wave" => iced::Theme::KanagawaWave, - "Kanagawa Dragon" => iced::Theme::KanagawaDragon, - "Kanagawa Lotus" => iced::Theme::KanagawaLotus, - "Moonfly" => iced::Theme::Moonfly, - "Nightfly" => iced::Theme::Nightfly, - "Oxocarbon" => iced::Theme::Oxocarbon, - "Ferra" => iced::Theme::Ferra, - _ => iced::Theme::default(), + "Light" => Some(iced::Theme::Light), + "Dark" => Some(iced::Theme::Dark), + "Dracula" => Some(iced::Theme::Dracula), + "Nord" => Some(iced::Theme::Nord), + "Solarized Light" => Some(iced::Theme::SolarizedLight), + "Solarized Dark" => Some(iced::Theme::SolarizedDark), + "Gruvbox Light" => Some(iced::Theme::GruvboxLight), + "Gruvbox Dark" => Some(iced::Theme::GruvboxDark), + "Catppuccin Latte" => Some(iced::Theme::CatppuccinLatte), + "Catppuccin Frappé" => Some(iced::Theme::CatppuccinFrappe), + "Catppuccin Macchiato" => Some(iced::Theme::CatppuccinMacchiato), + "Catppuccin Mocha" => Some(iced::Theme::CatppuccinMocha), + "Tokyo Night" => Some(iced::Theme::TokyoNight), + "Tokyo Night Storm" => Some(iced::Theme::TokyoNightStorm), + "Tokyo Night Light" => Some(iced::Theme::TokyoNightLight), + "Kanagawa Wave" => Some(iced::Theme::KanagawaWave), + "Kanagawa Dragon" => Some(iced::Theme::KanagawaDragon), + "Kanagawa Lotus" => Some(iced::Theme::KanagawaLotus), + "Moonfly" => Some(iced::Theme::Moonfly), + "Nightfly" => Some(iced::Theme::Nightfly), + "Oxocarbon" => Some(iced::Theme::Oxocarbon), + "Ferra" => Some(iced::Theme::Ferra), + _ => None, } } @@ -39,7 +39,7 @@ pub struct Appearance { impl Default for Appearance { fn default() -> Self { Self { - selected: Theme::default(), + selected: Theme::Dark, all: Theme::ALL.into(), } } diff --git a/src/config.rs b/src/config.rs index 0ef094c..98140e6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -104,7 +104,7 @@ impl Config { Some(theme) }; - let mut selected = Theme::default(); + let mut selected = Theme::Dark; let mut all = Theme::ALL.to_owned(); if let Some(index) = diff --git a/src/dialog.rs b/src/dialog.rs index c5e008c..2aefb50 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use iced::widget::{Space, text}; +use iced::widget::{space, text}; use iced_dialog::button; use iced_material::button::filled_tonal; @@ -34,7 +34,7 @@ impl From<Action> for Vec<Element<'_, Message>> { Action::Close => vec![button("Close", Message::DialogYes).into()], Action::UnsavedChanges(_) => vec![ button("Don't Save", Message::DialogNo).style(danger).into(), - Space::with_width(20).into(), + space().width(20).into(), button("Save", Message::DialogYes) .style(filled_tonal) .into(), diff --git a/src/main.rs b/src/main.rs index d04183a..add73ec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,13 +20,19 @@ use config::Config; use dialog::{Dialog, UnsavedChanges}; use error::Error; use iced::advanced::widget::Id; -use iced::widget::{column, container, pane_grid, pick_list, row, text_editor}; +use iced::system::theme_changes; +use iced::theme::{self, Base}; +use iced::time::Duration; +use iced::widget::{ + checkbox, column, container, pane_grid, pick_list, row, text, text_editor, +}; use iced::{ - Alignment, Length, Subscription, Task, clipboard, keyboard, window, + Alignment, Length, Subscription, Task, border, clipboard, keyboard, window, }; use iced_anim::transition::Easing; use iced_anim::{Animated, Animation}; use iced_material::Theme; +use iced_material::utils::{disabled_container, disabled_text}; use panes::{code_view, designer_view, element_list}; use types::{ Action, ConfigChangeType, DesignerPane, Element, Message, Panes, Project, @@ -79,6 +85,8 @@ struct IcedBuilder { project: Project, config: Config, theme: Animated<Theme>, + theme_mode: theme::Mode, + use_system_theme: bool, pane_state: pane_grid::State<Panes>, focus: Option<pane_grid::Pane>, designer_page: DesignerPane, @@ -119,7 +127,10 @@ impl IcedBuilder { project_path, project: Project::new(), config, - theme: Animated::new(theme, Easing::EASE_IN), + theme: Animated::new(theme, Easing::EASE_IN) + .with_duration(Duration::from_millis(300)), + theme_mode: theme::Mode::Dark, + use_system_theme: false, pane_state: state, focus: None, designer_page: DesignerPane::DesignerView, @@ -203,10 +214,25 @@ impl IcedBuilder { Message::SwitchTheme(event) => { self.theme.update(event); - return self.update(ConfigChangeType::SelectedTheme.into()); + if !self.use_system_theme { + return self.update(ConfigChangeType::SelectedTheme.into()); + } } - Message::SystemThemeChanged(theme) => { - Theme::update_system_theme(theme); + Message::SystemThemeChanged(mode) => { + self.theme_mode = mode; + + if self.use_system_theme { + self.theme.set_target(Theme::default(mode)); + } + } + Message::UseSystemTheme(use_system_theme) => { + self.use_system_theme = use_system_theme; + + self.theme.set_target(if use_system_theme { + Theme::default(self.theme_mode) + } else { + self.config.selected_theme() + }); } Message::CopyCode => { return clipboard::write(self.editor_content.text()); @@ -217,13 +243,15 @@ impl IcedBuilder { self.editor_content.perform(action); } } - Message::RefreshEditorContent => match self.project.app_code() { - Ok(code) => { - self.editor_content = - text_editor::Content::with_text(&code); + Message::RefreshEditorContent => { + match self.project.app_code(self.theme_mode) { + Ok(code) => { + self.editor_content = + text_editor::Content::with_text(&code); + } + Err(error) => self.dialog = Dialog::error(error), } - Err(error) => self.dialog = Dialog::error(error), - }, + } Message::DropNewElement(name, point, _) => { return iced_drop::zones_on_point( move |zones| Message::HandleNew(name.clone(), zones), @@ -434,7 +462,7 @@ impl IcedBuilder { } } Message::CloseApp => { - return window::get_latest().and_then(window::close); + return iced::exit(); } Message::EscapePressed if self.dialog.action() == dialog::Action::Close => @@ -485,19 +513,46 @@ impl IcedBuilder { let window_events = window::events().map(|(_id, event)| Message::WindowEvent(event)); - let system_theme = - Theme::subscription().map(Message::SystemThemeChanged); + let system_theme = theme_changes().map(Message::SystemThemeChanged); Subscription::batch([keyboard, window_events, system_theme]) } fn view(&self) -> Element<'_, Message> { - let header = row![pick_list( - self.config.themes(), - Some(self.theme.target()), - |theme| Message::SwitchTheme(theme.into()) - )] - .width(200); + let header = row![ + if self.use_system_theme { + Element::from( + container(text(self.config.selected_theme().to_string())) + .padding([5, 10]) + .width(Length::Fill) + .style(|theme: &Theme| { + let color = theme.colors().surface.on_surface; + container::Style { + background: Some( + disabled_container(color).into(), + ), + text_color: Some(disabled_text(color)), + border: border::rounded(4), + ..Default::default() + } + }), + ) + } else { + Element::from( + pick_list( + self.config.themes(), + Some(self.theme.target()), + |theme| Message::SwitchTheme(theme.into()), + ) + .width(Length::Fill), + ) + }, + checkbox("Use system theme", self.use_system_theme) + .on_toggle(Message::UseSystemTheme) + ] + .spacing(10) + .align_y(Alignment::Center) + .width(500); let pane_grid = pane_grid(&self.pane_state, |id, pane, _is_maximized| { let is_focused = Some(id) == self.focus; @@ -505,7 +560,7 @@ impl IcedBuilder { Panes::Designer => match &self.designer_page { DesignerPane::DesignerView => designer_view::view( self.project.element_tree.as_ref(), - self.project.get_theme(), + self.project.get_theme(self.theme_mode), is_focused, ), DesignerPane::CodeView => { diff --git a/src/panes/designer_view.rs b/src/panes/designer_view.rs index 92364bf..48a8304 100644 --- a/src/panes/designer_view.rs +++ b/src/panes/designer_view.rs @@ -29,7 +29,7 @@ pub fn view<'a>( None => center("Open a project or begin creating one").into(), }; - let content = container(themer(designer_theme, el_tree)) + let content = container(themer(Some(designer_theme), el_tree)) .id("drop_zone") .height(Length::Fill) .width(Length::Fill); diff --git a/src/types.rs b/src/types.rs index d998d61..0014090 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; pub use element_name::ElementName; use iced::advanced::widget::Id; +use iced::theme::Mode; use iced::widget::{pane_grid, text_editor}; use iced::window; use iced_anim::Event; @@ -25,7 +26,8 @@ pub enum Message { ConfigWrite(Result<(), Error>), SaveConfigChanges(ConfigChangeType), SwitchTheme(Event<Theme>), - SystemThemeChanged(Theme), + SystemThemeChanged(Mode), + UseSystemTheme(bool), CopyCode, SwitchPane(DesignerPane), EditorAction(text_editor::Action), diff --git a/src/types/project.rs b/src/types/project.rs index ceb4f84..aac9bca 100644 --- a/src/types/project.rs +++ b/src/types/project.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; extern crate fxhash; -use iced::Theme; +use iced::theme::{Base, Mode, Theme}; use rust_format::{Formatter, PostProcess, PrettyPlease}; use serde::{Deserialize, Serialize}; @@ -31,11 +31,11 @@ impl Project { } } - pub fn get_theme(&self) -> Theme { - match &self.theme { - Some(theme) => iced_theme_from_str(theme), - None => iced::Theme::default(), - } + pub fn get_theme(&self, mode: Mode) -> Theme { + self.theme + .as_ref() + .and_then(|theme| iced_theme_from_str(theme)) + .unwrap_or_else(|| Theme::default(mode)) } pub async fn from_path(path: PathBuf) -> Result<(PathBuf, Self), Error> { @@ -90,14 +90,14 @@ impl Project { Ok(path) } - pub fn app_code(&mut self) -> Result<String, Error> { + pub fn app_code(&mut self, theme_mode: Mode) -> Result<String, Error> { use iced::debug; let codegen = debug::time("Code Generation"); let result = match self.element_tree { Some(ref element_tree) => { let (imports, view) = element_tree.codegen(); - let theme = self.get_theme(); + let theme = self.get_theme(theme_mode); let app_code = format!( r#"// Automatically generated by iced Builder |
