Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2d00141
Define palette extension structs.
joshuamegnauth54 Jul 31, 2023
54b4abf
Draft out skeleton for minimal custom themes.
joshuamegnauth54 Jul 31, 2023
3efdceb
Add `Dracula` as an example theme to test.
joshuamegnauth54 Aug 1, 2023
5e333e3
Automatically append custom styles to settings.
joshuamegnauth54 Aug 2, 2023
2044602
Add gruvbox.
joshuamegnauth54 Aug 3, 2023
5722964
Fix deserializing `StyleType::Custom`.
joshuamegnauth54 Aug 3, 2023
474aaeb
Merge remote-tracking branch 'upstream/main' into custom_themes_minimal
joshuamegnauth54 Aug 4, 2023
e1a1c7f
Add style Solarized light.
joshuamegnauth54 Aug 4, 2023
5386d87
improvements to style settings page layout
GyulyVGC Aug 4, 2023
dd3f5ac
format files and fix lints
GyulyVGC Aug 4, 2023
85a6596
use StyleType::is_nightly to determine font weights
GyulyVGC Aug 4, 2023
b165fcd
fix tests
GyulyVGC Aug 4, 2023
306c46d
Add style Solarized dark.
joshuamegnauth54 Aug 5, 2023
d677171
Add Nord and update solarized.
joshuamegnauth54 Aug 5, 2023
2a4ca7f
improvements to overall palettes structure and colors
GyulyVGC Aug 5, 2023
09deb57
Add Nord (Day) as a light theme.
joshuamegnauth54 Aug 6, 2023
5004407
Add Gruvbox light.
joshuamegnauth54 Aug 6, 2023
a344376
fixed highlighted text and minor palettes improvements
GyulyVGC Aug 6, 2023
ff0c702
Add a light variation of Dracula.
joshuamegnauth54 Aug 7, 2023
32ec19f
fix Dracula Light palette
GyulyVGC Aug 7, 2023
66f1b8d
refactoring
GyulyVGC Aug 7, 2023
0b56a2a
some more refactoring
GyulyVGC Aug 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/configs/types/config_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use crate::{Language, StyleType};

#[derive(Serialize, Deserialize, Default)]
pub struct ConfigSettings {
pub style: StyleType,
pub color_gradient: GradientType,
pub language: Language,
pub notifications: Notifications,
// StyleType should be last in order to deserialize as a table properly
pub style: StyleType,
}
98 changes: 82 additions & 16 deletions src/gui/pages/settings_style_page.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
use iced::alignment::{Horizontal, Vertical};
use iced::widget::scrollable::Direction;
use iced::widget::{button, horizontal_space, vertical_space, Rule};
use iced::widget::{Button, Column, Container, Row, Text};
use iced::widget::{Button, Column, Container, Row, Scrollable, Space, Text};
use iced::Length::Fixed;
use iced::{Alignment, Length};
use iced::{Alignment, Element, Length};

use crate::gui::components::tab::get_settings_tabs;
use crate::gui::pages::settings_notifications_page::settings_header;
use crate::gui::pages::types::settings_page::SettingsPage;
use crate::gui::styles::button::{ButtonStyleTuple, ButtonType};
use crate::gui::styles::container::{ContainerStyleTuple, ContainerType};
use crate::gui::styles::rule::{RuleStyleTuple, RuleType};
use crate::gui::styles::scrollbar::{ScrollbarStyleTuple, ScrollbarType};
use crate::gui::styles::style_constants::{get_font, BORDER_WIDTH, FONT_SIZE_SUBTITLE, ICONS};
use crate::gui::styles::text::{TextStyleTuple, TextType};
use crate::gui::styles::types::custom_styles::ExtraStyles;
use crate::gui::styles::types::gradient_type::GradientType;
use crate::gui::types::message::Message;
use crate::translations::translations::{
Expand All @@ -24,7 +27,7 @@ use crate::{Language, Sniffer, StyleType};

pub fn settings_style_page(sniffer: &Sniffer) -> Container<Message> {
let font = get_font(sniffer.style);
let content = Column::new()
let mut content = Column::new()
.align_items(Alignment::Center)
.width(Length::Fill)
.push(settings_header(
Expand Down Expand Up @@ -55,13 +58,17 @@ pub fn settings_style_page(sniffer: &Sniffer) -> Container<Message> {
.font(font)
.size(FONT_SIZE_SUBTITLE),
)
.push(vertical_space(Length::Fixed(10.0)))
.push(vertical_space(Length::Fixed(15.0)))
.push(gradients_row(
sniffer.style,
sniffer.color_gradient,
sniffer.language,
))
.push(vertical_space(Length::Fixed(10.0)))
.push(vertical_space(Length::Fixed(15.0)));

let mut styles_col = Column::new()
.align_items(Alignment::Center)
.width(Length::Fill)
.push(
Row::new()
.push(get_palette_container(
Expand Down Expand Up @@ -94,7 +101,17 @@ pub fn settings_style_page(sniffer: &Sniffer) -> Container<Message> {
mon_amour_translation(sniffer.language).to_string(),
MonAmour,
)),
);
)
.push(vertical_space(Length::Fixed(10.0)));
for style in get_extra_styles(ExtraStyles::all_styles(), sniffer.style) {
styles_col = styles_col.push(style);
}

let styles_scroll = Scrollable::new(styles_col)
.direction(Direction::Vertical(ScrollbarType::properties()))
.style(ScrollbarStyleTuple(sniffer.style, ScrollbarType::Standard));

content = content.push(styles_scroll);

Container::new(content)
.height(Length::Fixed(400.0))
Expand Down Expand Up @@ -177,16 +194,22 @@ fn get_palette_container(
on_press: StyleType,
) -> Button<'static, Message> {
let font = get_font(style);
let content = Column::new()

let is_custom = matches!(on_press, StyleType::Custom(_));

let mut content = Column::new()
.width(Length::Fill)
.align_items(Alignment::Center)
.spacing(5)
.push(Text::new(name).font(font))
.push(get_palette(on_press))
.push(Text::new(description).font(font));
.push(get_palette(on_press, is_custom));

if !is_custom {
content = content.push(Text::new(description).font(font));
}

Button::new(content)
.height(Length::Fixed(110.0))
.height(Length::Fixed(if is_custom { 75.0 } else { 110.0 }))
.width(Length::Fixed(380.0))
.padding(5)
.style(
Expand All @@ -203,36 +226,79 @@ fn get_palette_container(
.on_press(Message::Style(on_press))
}

fn get_palette(style: StyleType) -> Container<'static, Message> {
fn get_palette(style: StyleType, is_custom: bool) -> Container<'static, Message> {
let height = if is_custom { 25.0 } else { 40.0 };

Container::new(
Row::new()
.padding(0)
.push(Row::new().padding(0).width(Length::Fixed(120.0)).push(
Rule::horizontal(40).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
Rule::horizontal(height).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
RuleStyleTuple(style, RuleType::PalettePrimary),
)),
))
.push(Row::new().padding(0).width(Length::Fixed(80.0)).push(
Rule::horizontal(40).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
Rule::horizontal(height).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
RuleStyleTuple(style, RuleType::PaletteSecondary),
)),
))
.push(Row::new().padding(0).width(Length::Fixed(60.0)).push(
Rule::horizontal(40).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
Rule::horizontal(height).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
RuleStyleTuple(style, RuleType::PaletteOutgoing),
)),
))
.push(Row::new().padding(0).width(Length::Fixed(40.0)).push(
Rule::horizontal(40).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
Rule::horizontal(height).style(<RuleStyleTuple as Into<iced::theme::Rule>>::into(
RuleStyleTuple(style, RuleType::PaletteButtons),
)),
)),
)
.align_x(Horizontal::Center)
.align_y(Vertical::Center)
.width(300.0 + 2.0 * BORDER_WIDTH)
.height(40.0 + 1.7 * BORDER_WIDTH)
.height(height + 1.7 * BORDER_WIDTH)
.style(<ContainerStyleTuple as Into<iced::theme::Container>>::into(
ContainerStyleTuple(style, ContainerType::Palette),
))
}

// Buttons for each extra style arranged in rows of two
fn get_extra_styles(
styles: &[ExtraStyles],
current_style: StyleType,
) -> Vec<Element<'static, Message>> {
// Map each extra style into a palette container
let mut styles = styles.iter().map(|&style| {
let name = style.to_string();
let description = String::new();
let style = StyleType::Custom(style);
get_palette_container(current_style, name, description, style)
});

// The best way to do this would be with itertools, but that would introduce another dependency.
let mut children = Vec::with_capacity(styles.len());

// This handles the case where there aren't an even number of styles.
// [Iterator::zip] drops remainders. Itertools' `zip_longest` and the unstable array chunks API
// are both better solutions.
while let (Some(first), second) = (styles.next(), styles.next()) {
// Add both styles and the vertical space if there are two styles.
if let Some(second) = second {
children.extend([
Row::new()
.push(first)
.push(horizontal_space(Length::Fixed(15.0)))
.push(second)
.into(),
<Space as Into<Element<Message>>>::into(vertical_space(Length::Fixed(10.0))),
]);
} else {
children.extend([
Row::new().push(first).into(),
<Space as Into<Element<Message>>>::into(vertical_space(Length::Fixed(10.0))),
]);
}
}

children
}
5 changes: 4 additions & 1 deletion src/gui/styles/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ impl rule::StyleSheet for RuleStyleTuple {
RuleType::PalettePrimary
| RuleType::PaletteSecondary
| RuleType::PaletteOutgoing
| RuleType::PaletteButtons => 40,
| RuleType::PaletteButtons => match self.0 {
StyleType::Custom(_) => 25,
_ => 40,
},
RuleType::Standard => 3,
},
radius: 0.0.into(),
Expand Down
3 changes: 3 additions & 0 deletions src/gui/styles/style_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ pub fn get_color_mix_chart(style: StyleType) -> f64 {
match style {
StyleType::Night | StyleType::DeepSea => 0.3,
StyleType::Day | StyleType::MonAmour => 0.8,
StyleType::Custom(style) => style.to_ext().color_mixing,
}
}

Expand Down Expand Up @@ -228,6 +229,7 @@ pub fn get_starred_color(style: StyleType) -> Color {
b: 39.0 / 255.0,
a: 0.8,
},
StyleType::Custom(style) => style.to_ext().starred,
}
}

Expand All @@ -236,5 +238,6 @@ pub fn get_color_mix_filter_badge(style: StyleType) -> f32 {
StyleType::Night | StyleType::DeepSea => 0.2,
StyleType::Day => 0.7,
StyleType::MonAmour => 0.5,
StyleType::Custom(style) => style.to_ext().badge_alpha,
}
}
90 changes: 90 additions & 0 deletions src/gui/styles/types/custom_styles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
mod dracula;
mod gruvbox;
mod solarized;

use std::fmt;

use iced::Color;
use serde::{Deserialize, Serialize};

use super::palette::Palette;

/// Custom style with any relevant metadata
pub struct CustomPalette {
/// Displayable name of the style (i.e. "Catppuccin (Mocha)")
name: &'static str,
Comment thread
GyulyVGC marked this conversation as resolved.
Resolved
/// Color scheme's palette
palette: Palette,
/// Extra colors such as the favorites star
extension: PaletteExtension,
}

/// Extension color for themes.
pub struct PaletteExtension {
/// Color of favorites star
pub starred: Color,
/// Badge/logo alpha
pub badge_alpha: f32,
/// Traffic chart color mixing
pub color_mixing: f64,
}

/// Built in extra styles
#[derive(Clone, Copy, Serialize, Deserialize, Debug, Hash, PartialEq)]
#[serde(tag = "custom")]
pub enum ExtraStyles {
Dracula,
Gruvbox,
SolarizedLight,
}

impl ExtraStyles {
/// [`Palette`] of the [`ExtraStyles`] variant
#[inline]
pub fn to_palette(self) -> Palette {
match self {
ExtraStyles::Dracula => dracula::dracula().palette,
ExtraStyles::Gruvbox => gruvbox::gruvbox_dark().palette,
ExtraStyles::SolarizedLight => solarized::solarized_light().palette,
}
}

/// Extension colors for the current [`ExtraStyles`] variant
#[inline]
pub fn to_ext(self) -> PaletteExtension {
match self {
ExtraStyles::Dracula => dracula::dracula().extension,
ExtraStyles::Gruvbox => gruvbox::gruvbox_dark().extension,
ExtraStyles::SolarizedLight => solarized::solarized_light().extension,
}
}

/// Theme is a night/dark style
#[inline]
pub const fn is_nightly(self) -> bool {
match self {
ExtraStyles::Dracula | ExtraStyles::Gruvbox => true,
ExtraStyles::SolarizedLight => false,
}
}

/// Slice of all implemented custom styles
#[inline]
pub const fn all_styles() -> &'static [Self] {
&[
ExtraStyles::Dracula,
ExtraStyles::Gruvbox,
ExtraStyles::SolarizedLight,
]
}
}

impl fmt::Display for ExtraStyles {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ExtraStyles::Dracula => write!(f, "Dracula"),
ExtraStyles::Gruvbox => write!(f, "Gruvbox (Dark)"),
ExtraStyles::SolarizedLight => write!(f, "Solarized (Light)"),
}
}
}
28 changes: 28 additions & 0 deletions src/gui/styles/types/custom_styles/dracula.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![allow(clippy::unreadable_literal)]

//! Dracula theme
//! <https://draculatheme.com/>
use iced::color;

use super::{CustomPalette, Palette, PaletteExtension};

pub(super) fn dracula() -> CustomPalette {
CustomPalette {
name: "Dracula",
palette: Palette {
primary: color!(0x44475a), // Current line
secondary: color!(0xff79c6), // Pink
outgoing: color!(0x8be9fd), // Cyan
buttons: color!(0x6272a4), // Comments
text_headers: color!(0x44475a), // Current line
text_body: color!(0xf8f8f2), // Foreground
round_borders: color!(0xbd93f9), // Purple
Comment thread
GyulyVGC marked this conversation as resolved.
Resolved
round_containers: color!(0x44475a), // Current line
},
extension: PaletteExtension {
starred: color!(0xf1fa8c),
badge_alpha: 0.75,
color_mixing: 0.3,
},
}
}
29 changes: 29 additions & 0 deletions src/gui/styles/types/custom_styles/gruvbox.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![allow(clippy::unreadable_literal)]

//! Gruvbox
//! <https://github.com/morhetz/gruvbox>

use iced::color;

use super::{CustomPalette, Palette, PaletteExtension};

pub(super) fn gruvbox_dark() -> CustomPalette {
CustomPalette {
name: "Gruvbox (Dark)",
palette: Palette {
primary: color!(0x282828), // bg
secondary: color!(0xfe8019), // orange
outgoing: color!(0x8ec07c), // aqua
buttons: color!(0x928374), // gray
text_headers: color!(0x1d2021), // bg0_h
text_body: color!(0xebdbb2), // fg
round_borders: color!(0x98971a), // green
round_containers: color!(0x504945), // bg2
},
extension: PaletteExtension {
starred: color!(0xd79921),
badge_alpha: 0.75,
color_mixing: 0.3,
},
}
}
Loading