diff --git a/src/chart/manage_chart_data.rs b/src/chart/manage_chart_data.rs index e8daf53a8..ccab59607 100644 --- a/src/chart/manage_chart_data.rs +++ b/src/chart/manage_chart_data.rs @@ -84,7 +84,7 @@ mod tests { use std::collections::VecDeque; use crate::chart::manage_chart_data::{get_max, get_min, update_charts_data}; - use crate::{ChartType, RunTimeData, TrafficChart}; + use crate::{ChartType, Language, RunTimeData, StyleType, TrafficChart}; #[test] fn test_chart_data_updates() { @@ -162,12 +162,9 @@ mod tests { max_received_bytes: 21000, min_sent_packets: -1000, max_received_packets: 21000, - color_mix: 0.0, - color_incoming: Default::default(), - color_outgoing: Default::default(), - color_font: Default::default(), + language: Language::default(), chart_type: ChartType::Packets, - language: Default::default(), + style: StyleType::default(), }; let mut runtime_data = RunTimeData { all_bytes: 0, diff --git a/src/chart/types/traffic_chart.rs b/src/chart/types/traffic_chart.rs index d4b46d73a..d7d17c1ee 100644 --- a/src/chart/types/traffic_chart.rs +++ b/src/chart/types/traffic_chart.rs @@ -5,10 +5,9 @@ use std::collections::VecDeque; use iced::alignment::{Horizontal, Vertical}; use iced::widget::{Column, Container}; use iced::Element; -use plotters::style::RGBColor; use plotters_iced::{Chart, ChartBuilder, ChartWidget, DrawingBackend}; -use crate::gui::styles::style_constants::{get_color_mix_chart, CHARTS_LINE_BORDER}; +use crate::gui::styles::style_constants::{get_alpha_chart_badge, CHARTS_LINE_BORDER}; use crate::gui::styles::types::palette::to_rgb_color; use crate::gui::types::message::Message; use crate::translations::translations::{incoming_translation, outgoing_translation}; @@ -35,12 +34,12 @@ pub struct TrafficChart { pub min_sent_packets: i64, /// Minimum number of received packets per time interval (computed on last 30 intervals) pub max_received_packets: i64, - pub color_mix: f64, - pub color_incoming: RGBColor, - pub color_outgoing: RGBColor, - pub color_font: RGBColor, - pub chart_type: ChartType, + /// Language used for the chart legend pub language: Language, + /// Packets or bytes + pub chart_type: ChartType, + /// Style of the chart + pub style: StyleType, } impl TrafficChart { @@ -55,12 +54,9 @@ impl TrafficChart { max_received_bytes: 0, min_sent_packets: 0, max_received_packets: 0, - color_mix: get_color_mix_chart(style), - color_incoming: to_rgb_color(get_colors(style).secondary), - color_outgoing: to_rgb_color(get_colors(style).outgoing), - color_font: to_rgb_color(get_colors(style).text_body), - chart_type: ChartType::Bytes, language, + chart_type: ChartType::Bytes, + style, } } @@ -79,11 +75,8 @@ impl TrafficChart { self.language = language; } - pub fn change_colors(&mut self, style: StyleType) { - self.color_font = to_rgb_color(get_colors(style).text_body); - self.color_incoming = to_rgb_color(get_colors(style).secondary); - self.color_outgoing = to_rgb_color(get_colors(style).outgoing); - self.color_mix = get_color_mix_chart(style); + pub fn change_style(&mut self, style: StyleType) { + self.style = style; } } @@ -97,9 +90,10 @@ impl Chart for TrafficChart { ) { use plotters::prelude::*; - let font_weight = match self.color_font { - RGBColor(255, 255, 255) => FontStyle::Normal, // if white non-bold - _ => FontStyle::Bold, + let font_weight = if self.style.is_nightly() { + FontStyle::Normal + } else { + FontStyle::Bold }; if self.ticks == 0 { @@ -108,8 +102,11 @@ impl Chart for TrafficChart { let tot_seconds = self.ticks - 1; let first_time_displayed = if self.ticks > 30 { self.ticks - 30 } else { 0 }; - let color_incoming = self.color_incoming; - let color_outgoing = self.color_outgoing; + let colors = get_colors(self.style); + let color_incoming = to_rgb_color(colors.secondary); + let color_outgoing = to_rgb_color(colors.outgoing); + let color_font = to_rgb_color(colors.text_body); + let color_mix = get_alpha_chart_badge(self.style); chart_builder .margin_right(30) @@ -133,7 +130,7 @@ impl Chart for TrafficChart { ("Sarasa Mono SC", 12) .into_font() .style(font_weight) - .color(&self.color_font), + .color(&color_font), ) .y_labels(7) .y_label_formatter(&|bytes| { @@ -146,7 +143,7 @@ impl Chart for TrafficChart { AreaSeries::new( self.received_bytes.iter().copied(), 0, - color_incoming.mix(self.color_mix), + color_incoming.mix(color_mix.into()), ) .border_style( ShapeStyle::from(&color_incoming).stroke_width(CHARTS_LINE_BORDER), @@ -162,7 +159,7 @@ impl Chart for TrafficChart { AreaSeries::new( self.sent_bytes.iter().copied(), 0, - color_outgoing.mix(self.color_mix), + color_outgoing.mix(color_mix.into()), ) .border_style( ShapeStyle::from(&color_outgoing).stroke_width(CHARTS_LINE_BORDER), @@ -182,7 +179,7 @@ impl Chart for TrafficChart { ("Sarasa Mono SC", 13.5) .into_font() .style(font_weight) - .color(&self.color_font), + .color(&color_font), ) .draw() .expect("Error drawing graph"); @@ -203,7 +200,7 @@ impl Chart for TrafficChart { ("Sarasa Mono SC", 12) .into_font() .style(font_weight) - .color(&self.color_font), + .color(&color_font), ) .y_labels(7) .y_label_formatter(&|packets| packets.abs().to_string()) @@ -214,7 +211,7 @@ impl Chart for TrafficChart { AreaSeries::new( self.received_packets.iter().copied(), 0, - color_incoming.mix(self.color_mix), + color_incoming.mix(color_mix.into()), ) .border_style( ShapeStyle::from(&color_incoming).stroke_width(CHARTS_LINE_BORDER), @@ -230,7 +227,7 @@ impl Chart for TrafficChart { AreaSeries::new( self.sent_packets.iter().copied(), 0, - color_outgoing.mix(self.color_mix), + color_outgoing.mix(color_mix.into()), ) .border_style( ShapeStyle::from(&color_outgoing).stroke_width(CHARTS_LINE_BORDER), @@ -250,7 +247,7 @@ impl Chart for TrafficChart { ("Sarasa Mono SC", 13.5) .into_font() .style(font_weight) - .color(&self.color_font), + .color(&color_font), ) .draw() .expect("Error drawing graph"); diff --git a/src/configs/types/config_settings.rs b/src/configs/types/config_settings.rs index 9c59ae86d..4c6894703 100644 --- a/src/configs/types/config_settings.rs +++ b/src/configs/types/config_settings.rs @@ -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, } diff --git a/src/gui/pages/settings_style_page.rs b/src/gui/pages/settings_style_page.rs index b8c2072d5..450a7ceb0 100644 --- a/src/gui/pages/settings_style_page.rs +++ b/src/gui/pages/settings_style_page.rs @@ -1,8 +1,9 @@ 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; @@ -10,8 +11,10 @@ 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_palette::ExtraStyles; use crate::gui::styles::types::gradient_type::GradientType; use crate::gui::types::message::Message; use crate::translations::translations::{ @@ -24,7 +27,7 @@ use crate::{Language, Sniffer, StyleType}; pub fn settings_style_page(sniffer: &Sniffer) -> Container { 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( @@ -55,13 +58,17 @@ pub fn settings_style_page(sniffer: &Sniffer) -> Container { .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( @@ -94,7 +101,17 @@ pub fn settings_style_page(sniffer: &Sniffer) -> Container { mon_amour_translation(sniffer.language).to_string(), MonAmour, )), - ); + ) + .push(vertical_space(Length::Fixed(10.0))); + for children in get_extra_palettes(ExtraStyles::all_styles(), sniffer.style) { + styles_col = styles_col.push(children); + } + + 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)) @@ -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( @@ -203,27 +226,29 @@ 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(>::into( + Rule::horizontal(height).style(>::into( RuleStyleTuple(style, RuleType::PalettePrimary), )), )) .push(Row::new().padding(0).width(Length::Fixed(80.0)).push( - Rule::horizontal(40).style(>::into( + Rule::horizontal(height).style(>::into( RuleStyleTuple(style, RuleType::PaletteSecondary), )), )) .push(Row::new().padding(0).width(Length::Fixed(60.0)).push( - Rule::horizontal(40).style(>::into( + Rule::horizontal(height).style(>::into( RuleStyleTuple(style, RuleType::PaletteOutgoing), )), )) .push(Row::new().padding(0).width(Length::Fixed(40.0)).push( - Rule::horizontal(40).style(>::into( + Rule::horizontal(height).style(>::into( RuleStyleTuple(style, RuleType::PaletteButtons), )), )), @@ -231,8 +256,49 @@ fn get_palette(style: StyleType) -> Container<'static, Message> { .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(>::into( ContainerStyleTuple(style, ContainerType::Palette), )) } + +// Buttons for each extra style arranged in rows of two +fn get_extra_palettes( + styles: &[ExtraStyles], + current_style: StyleType, +) -> Vec> { + // 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(), + >>::into(vertical_space(Length::Fixed(10.0))), + ]); + } else { + children.extend([ + Row::new().push(first).into(), + >>::into(vertical_space(Length::Fixed(10.0))), + ]); + } + } + + children +} diff --git a/src/gui/styles/button.rs b/src/gui/styles/button.rs index f694efaf2..3fd5554d2 100644 --- a/src/gui/styles/button.rs +++ b/src/gui/styles/button.rs @@ -4,7 +4,10 @@ use iced::widget::button; use iced::widget::button::Appearance; use iced::{Background, Color, Vector}; -use crate::gui::styles::style_constants::{get_starred_color, BORDER_BUTTON_RADIUS, BORDER_WIDTH}; +use crate::gui::styles::style_constants::{ + get_alpha_round_borders, get_alpha_round_containers, get_starred_color, BORDER_BUTTON_RADIUS, + BORDER_WIDTH, +}; use crate::gui::styles::types::gradient_type::{ get_gradient_buttons, get_gradient_hovered_buttons, GradientType, }; @@ -42,20 +45,20 @@ impl button::StyleSheet for ButtonStyleTuple { let colors = get_colors(self.0); button::Appearance { background: Some(match self { - ButtonStyleTuple(_, ButtonType::TabActive) => Background::Color(colors.primary), + ButtonStyleTuple(_, ButtonType::TabActive | ButtonType::BorderedRoundSelected) => { + Background::Color(mix_colors(colors.primary, colors.buttons)) + } ButtonStyleTuple(_, ButtonType::Starred) => { Background::Color(get_starred_color(self.0)) } ButtonStyleTuple(_, ButtonType::Badge) => Background::Color(colors.secondary), - ButtonStyleTuple(_, ButtonType::BorderedRound) => { - Background::Color(colors.round_containers) - } + ButtonStyleTuple(_, ButtonType::BorderedRound) => Background::Color(Color { + a: get_alpha_round_containers(self.0), + ..colors.buttons + }), ButtonStyleTuple(_, ButtonType::Neutral | ButtonType::NotStarred) => { Background::Color(Color::TRANSPARENT) } - ButtonStyleTuple(_, ButtonType::BorderedRoundSelected) => { - Background::Color(mix_colors(colors.primary, colors.buttons)) - } ButtonStyleTuple(_, ButtonType::Gradient(GradientType::None)) => { Background::Color(colors.secondary) } @@ -102,7 +105,10 @@ impl button::StyleSheet for ButtonStyleTuple { }, border_color: match self { ButtonStyleTuple(_, ButtonType::Alert) => Color::new(0.8, 0.15, 0.15, 1.0), - ButtonStyleTuple(_, ButtonType::BorderedRound) => colors.round_borders, + ButtonStyleTuple(_, ButtonType::BorderedRound) => Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, _ => colors.secondary, }, } @@ -120,7 +126,6 @@ impl button::StyleSheet for ButtonStyleTuple { ButtonStyleTuple(_, ButtonType::Starred) => { Background::Color(get_starred_color(self.0)) } - ButtonStyleTuple(_, ButtonType::TabActive) => Background::Color(colors.primary), ButtonStyleTuple(_, ButtonType::Gradient(GradientType::None)) => { Background::Color(mix_colors(colors.primary, colors.secondary)) } @@ -156,7 +161,10 @@ impl button::StyleSheet for ButtonStyleTuple { ButtonStyleTuple( _, ButtonType::BorderedRound | ButtonType::Neutral | ButtonType::NotStarred, - ) => colors.round_borders, + ) => Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, _ => colors.secondary, }, text_color: match self { diff --git a/src/gui/styles/container.rs b/src/gui/styles/container.rs index 9a29203df..e3233cd50 100644 --- a/src/gui/styles/container.rs +++ b/src/gui/styles/container.rs @@ -5,7 +5,8 @@ use iced::Theme; use iced::{Background, Color}; use crate::gui::styles::style_constants::{ - get_color_mix_filter_badge, BORDER_ROUNDED_RADIUS, BORDER_WIDTH, + get_alpha_chart_badge, get_alpha_round_borders, get_alpha_round_containers, + BORDER_ROUNDED_RADIUS, BORDER_WIDTH, }; use crate::gui::styles::types::gradient_type::{get_gradient_headers, GradientType}; use crate::{get_colors, StyleType}; @@ -49,14 +50,15 @@ impl iced::widget::container::StyleSheet for ContainerStyleTuple { Background::Color(colors.secondary) } ContainerStyleTuple(_, ContainerType::Tooltip) => Background::Color(colors.buttons), - ContainerStyleTuple(_, ContainerType::BorderedRound) => { - Background::Color(colors.round_containers) - } + ContainerStyleTuple(_, ContainerType::BorderedRound) => Background::Color(Color { + a: get_alpha_round_containers(self.0), + ..colors.buttons + }), ContainerStyleTuple(_, ContainerType::Neutral | ContainerType::Palette) => { Background::Color(Color::TRANSPARENT) } ContainerStyleTuple(_, ContainerType::Badge) => Background::Color(Color { - a: get_color_mix_filter_badge(self.0), + a: get_alpha_chart_badge(self.0), ..colors.secondary }), ContainerStyleTuple(_, ContainerType::Gradient(gradient_type)) => { @@ -94,7 +96,10 @@ impl iced::widget::container::StyleSheet for ContainerStyleTuple { border_color: match self { ContainerStyleTuple(_, ContainerType::Alert) => Color::new(1.0, 0.0, 0.0, 1.0), ContainerStyleTuple(_, ContainerType::Palette) => Color::BLACK, - _ => colors.round_borders, + _ => Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, }, } } diff --git a/src/gui/styles/custom_themes/dracula.rs b/src/gui/styles/custom_themes/dracula.rs new file mode 100644 index 000000000..58fcdf4b8 --- /dev/null +++ b/src/gui/styles/custom_themes/dracula.rs @@ -0,0 +1,48 @@ +#![allow(clippy::unreadable_literal)] + +//! Dracula theme +//! +//! Light style from: +use iced::color; + +use crate::gui::styles::types::custom_palette::{CustomPalette, PaletteExtension}; +use crate::gui::styles::types::palette::Palette; + +pub(in crate::gui::styles) fn dracula_dark() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0x282a36), // Background + secondary: color!(0xff79c6), // Pink + outgoing: color!(0x8be9fd), // Cyan + buttons: color!(0x6272a4), // Comments + text_headers: color!(0x282a36), // Background + text_body: color!(0xf8f8f2), // Foreground + }, + extension: PaletteExtension { + starred: color!(0xf1fa8c, 0.7), + round_borders_alpha: 0.1, + round_containers_alpha: 0.04, + chart_badge_alpha: 0.15, + }, + } +} + +// Light Darker variant +pub(in crate::gui::styles) fn dracula_light() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0xf8f8f2), + secondary: color!(0x9f1670), + outgoing: color!(0x005d6f), + buttons: color!(0xc5c8de), + text_headers: color!(0xf8f8f2), + text_body: color!(0x282a36), + }, + extension: PaletteExtension { + starred: color!(0xffb86c, 0.8), + chart_badge_alpha: 0.75, + round_borders_alpha: 0.45, + round_containers_alpha: 0.25, + }, + } +} diff --git a/src/gui/styles/custom_themes/gruvbox.rs b/src/gui/styles/custom_themes/gruvbox.rs new file mode 100644 index 000000000..2cd7b9fc6 --- /dev/null +++ b/src/gui/styles/custom_themes/gruvbox.rs @@ -0,0 +1,49 @@ +#![allow(clippy::unreadable_literal)] + +//! Gruvbox +//! + +use iced::color; + +use crate::gui::styles::types::custom_palette::{CustomPalette, PaletteExtension}; +use crate::gui::styles::types::palette::Palette; + +/// Gruvbox (night style) +pub(in crate::gui::styles) fn gruvbox_dark() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0x282828), // bg + secondary: color!(0xfe8019), // orange + outgoing: color!(0x8ec07c), // aqua + buttons: color!(0x7c6f64), // bg4 + text_headers: color!(0x1d2021), // bg0_h + text_body: color!(0xebdbb2), // fg + }, + extension: PaletteExtension { + starred: color!(0xd79921, 0.8), + chart_badge_alpha: 0.15, + round_borders_alpha: 0.12, + round_containers_alpha: 0.05, + }, + } +} + +/// Gruvbox (day style) +pub(in crate::gui::styles) fn gruvbox_light() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0xfbf1c7), // bg + secondary: color!(0xd65d0e), // orange + outgoing: color!(0x689d6a), // aqua + buttons: color!(0xd5c4a1), // bg2 + text_headers: color!(0xf9f5d7), // bg0_h + text_body: color!(0x282828), // fg + }, + extension: PaletteExtension { + starred: color!(0xd79921, 0.8), // yellow + chart_badge_alpha: 0.75, + round_borders_alpha: 0.45, + round_containers_alpha: 0.2, + }, + } +} diff --git a/src/gui/styles/custom_themes/mod.rs b/src/gui/styles/custom_themes/mod.rs new file mode 100644 index 000000000..1ccee9527 --- /dev/null +++ b/src/gui/styles/custom_themes/mod.rs @@ -0,0 +1,4 @@ +pub mod dracula; +pub mod gruvbox; +pub mod nord; +pub mod solarized; diff --git a/src/gui/styles/custom_themes/nord.rs b/src/gui/styles/custom_themes/nord.rs new file mode 100644 index 000000000..e6016595e --- /dev/null +++ b/src/gui/styles/custom_themes/nord.rs @@ -0,0 +1,46 @@ +#![allow(clippy::unreadable_literal)] + +//! Nord theme +//! +use iced::color; + +use crate::gui::styles::types::custom_palette::{CustomPalette, PaletteExtension}; +use crate::gui::styles::types::palette::Palette; + +pub(in crate::gui::styles) fn nord_dark() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0x2e3440), // nord0 + secondary: color!(0x88c0d0), // nord8 + outgoing: color!(0xB48EAD), // nord15 + buttons: color!(0x4C566A), // nord3 + text_headers: color!(0x2e3440), // nord0 + text_body: color!(0xd8dee9), // nord4 + }, + extension: PaletteExtension { + starred: color!(0xebcb8b), // nord13 + chart_badge_alpha: 0.2, + round_borders_alpha: 0.35, + round_containers_alpha: 0.15, + }, + } +} + +pub(in crate::gui::styles) fn nord_light() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0xeceff4), // nord6 + secondary: color!(0x05e81ac), // nord10 + outgoing: color!(0xb48ead), // nord15 + buttons: color!(0x8FBCBB), // nord7 + text_headers: color!(0xeceff4), // nord6 + text_body: color!(0x2e3440), // nord0 + }, + extension: PaletteExtension { + starred: color!(0xebcb8b), // nord13 + chart_badge_alpha: 0.6, + round_borders_alpha: 0.35, + round_containers_alpha: 0.15, + }, + } +} diff --git a/src/gui/styles/custom_themes/solarized.rs b/src/gui/styles/custom_themes/solarized.rs new file mode 100644 index 000000000..8d09fa7fb --- /dev/null +++ b/src/gui/styles/custom_themes/solarized.rs @@ -0,0 +1,48 @@ +#![allow(clippy::unreadable_literal)] + +//! Solarized +//! +use iced::color; + +use crate::gui::styles::types::custom_palette::{CustomPalette, PaletteExtension}; +use crate::gui::styles::types::palette::Palette; + +/// Solarized light (Day style) +pub(in crate::gui::styles) fn solarized_light() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0xfdf6e3), // base3 + secondary: color!(0x859900), // green + outgoing: color!(0x268bd2), // blue + buttons: color!(0x93a1a1), // base1 + text_headers: color!(0xfdf6e3), // base3 + text_body: color!(0x002b36), // base03 + }, + extension: PaletteExtension { + starred: color!(0xb58900, 0.9), // yellow + chart_badge_alpha: 0.75, + round_borders_alpha: 0.35, + round_containers_alpha: 0.15, + }, + } +} + +/// Solarized dark (Night style) +pub(in crate::gui::styles) fn solarized_dark() -> CustomPalette { + CustomPalette { + palette: Palette { + primary: color!(0x002b36), // base03 + secondary: color!(0x859900), // green + outgoing: color!(0x268bd2), // blue + buttons: color!(0x586e75), // base01 + text_headers: color!(0x002b36), // base03 + text_body: color!(0xeee8d5), // base2 + }, + extension: PaletteExtension { + starred: color!(0xb58900), // yellow + chart_badge_alpha: 0.25, + round_borders_alpha: 0.15, + round_containers_alpha: 0.08, + }, + } +} diff --git a/src/gui/styles/mod.rs b/src/gui/styles/mod.rs index a927f707e..841c5eaad 100644 --- a/src/gui/styles/mod.rs +++ b/src/gui/styles/mod.rs @@ -1,6 +1,7 @@ pub mod button; pub mod checkbox; pub mod container; +pub mod custom_themes; pub mod picklist; pub mod radio; pub mod rule; diff --git a/src/gui/styles/picklist.rs b/src/gui/styles/picklist.rs index 646b289e3..956181de5 100644 --- a/src/gui/styles/picklist.rs +++ b/src/gui/styles/picklist.rs @@ -3,8 +3,9 @@ use std::rc::Rc; use iced::widget::pick_list; -use iced::Background; +use iced::{Background, Color}; +use crate::gui::styles::style_constants::get_alpha_round_borders; use crate::gui::styles::types::palette::mix_colors; use crate::{get_colors, StyleType}; @@ -51,7 +52,10 @@ impl pick_list::StyleSheet for PicklistStyleTuple { background: Background::Color(colors.buttons), border_radius: 0.0.into(), border_width: 1.0, - border_color: colors.round_borders, + border_color: Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, } } diff --git a/src/gui/styles/rule.rs b/src/gui/styles/rule.rs index 78adb6774..963b7f117 100644 --- a/src/gui/styles/rule.rs +++ b/src/gui/styles/rule.rs @@ -2,7 +2,9 @@ use iced::widget::rule; use iced::widget::rule::FillMode; +use iced::Color; +use crate::gui::styles::style_constants::get_alpha_round_borders; use crate::{get_colors, StyleType}; #[derive(Clone, Copy)] @@ -36,14 +38,20 @@ impl rule::StyleSheet for RuleStyleTuple { RuleType::Outgoing | RuleType::PaletteOutgoing => colors.outgoing, RuleType::PalettePrimary => colors.primary, RuleType::PaletteButtons => colors.buttons, - RuleType::Standard => colors.round_borders, + RuleType::Standard => Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, }, width: match self.1 { RuleType::Incoming | RuleType::Outgoing => 5, 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(), diff --git a/src/gui/styles/scrollbar.rs b/src/gui/styles/scrollbar.rs index bcfdf84f1..19dc64aff 100644 --- a/src/gui/styles/scrollbar.rs +++ b/src/gui/styles/scrollbar.rs @@ -5,7 +5,7 @@ use iced::widget::scrollable::{Scrollbar, Scroller}; use iced::Theme; use iced::{Background, Color}; -use crate::gui::styles::style_constants::BORDER_ROUNDED_RADIUS; +use crate::gui::styles::style_constants::{get_alpha_round_borders, BORDER_ROUNDED_RADIUS}; use crate::gui::styles::types::palette::mix_colors; use crate::{get_colors, StyleType}; @@ -38,9 +38,15 @@ impl iced::widget::scrollable::StyleSheet for ScrollbarStyleTuple { background: Some(Background::Color(Color::TRANSPARENT)), border_radius: BORDER_ROUNDED_RADIUS.into(), border_width: 0.0, - border_color: colors.round_borders, + border_color: Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, scroller: Scroller { - color: colors.round_borders, + color: Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, border_radius: BORDER_ROUNDED_RADIUS.into(), border_width: 0.0, border_color: Color::TRANSPARENT, @@ -51,10 +57,16 @@ impl iced::widget::scrollable::StyleSheet for ScrollbarStyleTuple { fn hovered(&self, _: &Self::Style, is_mouse_over_scrollbar: bool) -> Scrollbar { let colors = get_colors(self.0); Scrollbar { - background: Some(Background::Color(colors.round_borders)), + background: Some(Background::Color(Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + })), border_radius: BORDER_ROUNDED_RADIUS.into(), border_width: 0.0, - border_color: colors.round_borders, + border_color: Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, scroller: Scroller { color: if is_mouse_over_scrollbar { colors.secondary diff --git a/src/gui/styles/style_constants.rs b/src/gui/styles/style_constants.rs index dac03204c..70d5e0ad9 100644 --- a/src/gui/styles/style_constants.rs +++ b/src/gui/styles/style_constants.rs @@ -2,10 +2,9 @@ use iced::font::{Family, Stretch, Weight}; use iced::{Color, Font}; -use plotters::style::RGBColor; -use crate::gui::styles::types::palette::{to_rgb_color, Palette}; -use crate::{get_colors, StyleType}; +use crate::gui::styles::types::palette::Palette; +use crate::StyleType; // night theme const PRIMARY_NIGHT: Color = Color { @@ -33,14 +32,6 @@ pub const NIGHT_STYLE: Palette = Palette { outgoing: SECONDARY_DAY, text_headers: Color::BLACK, text_body: Color::WHITE, - round_borders: Color { - a: 0.3, - ..Color::BLACK - }, - round_containers: Color { - a: 0.2, - ..Color::BLACK - }, }; // day theme @@ -64,14 +55,6 @@ pub const DAY_STYLE: Palette = Palette { outgoing: SECONDARY_NIGHT, text_headers: Color::WHITE, text_body: Color::BLACK, - round_borders: Color { - a: 0.25, - ..Color::BLACK - }, - round_containers: Color { - a: 0.1, - ..Color::BLACK - }, }; // deep sea theme @@ -106,14 +89,6 @@ pub const DEEP_SEA_STYLE: Palette = Palette { outgoing: OUTGOING_DEEP_SEA, text_headers: Color::BLACK, text_body: Color::WHITE, - round_borders: Color { - a: 0.1, - ..SECONDARY_DEEP_SEA - }, - round_containers: Color { - a: 0.03, - ..SECONDARY_DEEP_SEA - }, }; // mon amour theme @@ -148,14 +123,6 @@ pub const MON_AMOUR_STYLE: Palette = Palette { outgoing: OUTGOING_MON_AMOUR, text_headers: Color::WHITE, text_body: Color::BLACK, - round_borders: Color { - a: 0.6, - ..BUTTONS_MON_AMOUR - }, - round_containers: Color { - a: 0.3, - ..BUTTONS_MON_AMOUR - }, }; pub const SARASA_MONO_BOLD_BYTES: &[u8] = @@ -177,23 +144,18 @@ pub const SARASA_MONO: Font = Font { }; pub fn get_font(style: StyleType) -> Font { - match to_rgb_color(get_colors(style).text_body) { - RGBColor(255, 255, 255) => SARASA_MONO, - _ => SARASA_MONO_BOLD, + if style.is_nightly() { + SARASA_MONO + } else { + SARASA_MONO_BOLD } } pub fn get_font_headers(style: StyleType) -> Font { - match to_rgb_color(get_colors(style).text_headers) { - RGBColor(255, 255, 255) => SARASA_MONO, - _ => SARASA_MONO_BOLD, - } -} - -pub fn get_color_mix_chart(style: StyleType) -> f64 { - match style { - StyleType::Night | StyleType::DeepSea => 0.3, - StyleType::Day | StyleType::MonAmour => 0.8, + if style.is_nightly() { + SARASA_MONO_BOLD + } else { + SARASA_MONO } } @@ -228,13 +190,32 @@ pub fn get_starred_color(style: StyleType) -> Color { b: 39.0 / 255.0, a: 0.8, }, + StyleType::Custom(style) => style.to_ext().starred, } } -pub fn get_color_mix_filter_badge(style: StyleType) -> f32 { +pub fn get_alpha_chart_badge(style: StyleType) -> f32 { match style { StyleType::Night | StyleType::DeepSea => 0.2, - StyleType::Day => 0.7, + StyleType::Day | StyleType::MonAmour => 0.8, + StyleType::Custom(style) => style.to_ext().chart_badge_alpha, + } +} + +pub fn get_alpha_round_borders(style: StyleType) -> f32 { + match style { + StyleType::Night | StyleType::DeepSea => 0.35, + StyleType::Day => 0.45, StyleType::MonAmour => 0.5, + StyleType::Custom(style) => style.to_ext().round_borders_alpha, + } +} + +pub fn get_alpha_round_containers(style: StyleType) -> f32 { + match style { + StyleType::Night | StyleType::MonAmour => 0.25, + StyleType::Day => 0.2, + StyleType::DeepSea => 0.15, + StyleType::Custom(style) => style.to_ext().round_containers_alpha, } } diff --git a/src/gui/styles/text.rs b/src/gui/styles/text.rs index 7ce47ab33..a21b34a0e 100644 --- a/src/gui/styles/text.rs +++ b/src/gui/styles/text.rs @@ -4,7 +4,6 @@ use iced::widget::{Column, Text}; use iced::Color; use crate::gui::styles::style_constants::get_font; -use crate::gui::styles::types::palette::Palette; use crate::gui::types::message::Message; use crate::{get_colors, StyleType}; @@ -38,21 +37,18 @@ pub struct TextStyleTuple(pub StyleType, pub TextType); impl From for iced::theme::Text { fn from(tuple: TextStyleTuple) -> Self { - let colors = get_colors(tuple.0); - iced::theme::Text::Color(highlight(tuple.1, &colors)) + iced::theme::Text::Color(highlight(tuple.0, tuple.1)) } } /// Returns the weighted average of two colors; color intensity is fixed to 100% -pub fn highlight(element: TextType, colors: &Palette) -> Color { +pub fn highlight(style: StyleType, element: TextType) -> Color { + let colors = get_colors(style); let color = colors.secondary; + let is_nightly = style.is_nightly(); match element { TextType::Title => { - let (p1, c) = if colors.text_body.eq(&Color::BLACK) { - (0.9, 0.7) - } else { - (0.6, 1.0) - }; + let (p1, c) = if is_nightly { (0.6, 1.0) } else { (0.9, 0.7) }; Color { r: c * (1.0 - p1) + color.r * p1, g: c * (1.0 - p1) + color.g * p1, @@ -61,11 +57,7 @@ pub fn highlight(element: TextType, colors: &Palette) -> Color { } } TextType::Subtitle => { - let (p1, c) = if colors.text_body.eq(&Color::BLACK) { - (0.6, 0.7) - } else { - (0.4, 1.0) - }; + let (p1, c) = if is_nightly { (0.4, 1.0) } else { (0.6, 0.7) }; Color { r: c * (1.0 - p1) + color.r * p1, g: c * (1.0 - p1) + color.g * p1, diff --git a/src/gui/styles/text_input.rs b/src/gui/styles/text_input.rs index 4b87c72fb..aa15a8f7e 100644 --- a/src/gui/styles/text_input.rs +++ b/src/gui/styles/text_input.rs @@ -4,6 +4,7 @@ use iced::widget::text_input; use iced::widget::text_input::Appearance; use iced::{Background, Color}; +use crate::gui::styles::style_constants::get_alpha_round_borders; use crate::{get_colors, StyleType}; #[derive(Clone, Copy)] @@ -35,7 +36,10 @@ impl iced::widget::text_input::StyleSheet for TextInputStyleTuple { border_width: 1.0, border_color: match self.1 { TextInputType::Badge => Color::TRANSPARENT, - TextInputType::Standard => colors.round_borders, + TextInputType::Standard => Color { + a: get_alpha_round_borders(self.0), + ..colors.buttons + }, }, icon_color: colors.text_body, } diff --git a/src/gui/styles/types/custom_palette.rs b/src/gui/styles/types/custom_palette.rs new file mode 100644 index 000000000..6a2d7f0af --- /dev/null +++ b/src/gui/styles/types/custom_palette.rs @@ -0,0 +1,114 @@ +use std::fmt; + +use iced::Color; +use serde::{Deserialize, Serialize}; + +use crate::gui::styles::custom_themes::{dracula, gruvbox, nord, solarized}; +use crate::gui::styles::types::palette::Palette; + +/// Custom style with any relevant metadata +pub struct CustomPalette { + /// Color scheme's palette + pub(crate) palette: Palette, + /// Extra colors such as the favorites star + pub(crate) extension: PaletteExtension, +} + +/// Extension color for themes. +pub struct PaletteExtension { + /// Color of favorites star + pub starred: Color, + /// Badge/logo alpha + pub chart_badge_alpha: f32, + /// Round borders alpha + pub round_borders_alpha: f32, + /// Round containers alpha + pub round_containers_alpha: f32, +} + +/// Built in extra styles +#[derive(Clone, Copy, Serialize, Deserialize, Debug, Hash, PartialEq)] +#[serde(tag = "custom")] +pub enum ExtraStyles { + DraculaDark, + DraculaLight, + GruvboxDark, + GruvboxLight, + NordDark, + NordLight, + SolarizedDark, + SolarizedLight, +} + +impl ExtraStyles { + /// [`Palette`] of the [`ExtraStyles`] variant + pub fn to_palette(self) -> Palette { + match self { + ExtraStyles::DraculaLight => dracula::dracula_light().palette, + ExtraStyles::DraculaDark => dracula::dracula_dark().palette, + ExtraStyles::GruvboxDark => gruvbox::gruvbox_dark().palette, + ExtraStyles::GruvboxLight => gruvbox::gruvbox_light().palette, + ExtraStyles::NordLight => nord::nord_light().palette, + ExtraStyles::NordDark => nord::nord_dark().palette, + ExtraStyles::SolarizedDark => solarized::solarized_dark().palette, + ExtraStyles::SolarizedLight => solarized::solarized_light().palette, + } + } + + /// Extension colors for the current [`ExtraStyles`] variant + pub fn to_ext(self) -> PaletteExtension { + match self { + ExtraStyles::DraculaLight => dracula::dracula_light().extension, + ExtraStyles::DraculaDark => dracula::dracula_dark().extension, + ExtraStyles::GruvboxDark => gruvbox::gruvbox_dark().extension, + ExtraStyles::GruvboxLight => gruvbox::gruvbox_light().extension, + ExtraStyles::NordLight => nord::nord_light().extension, + ExtraStyles::NordDark => nord::nord_dark().extension, + ExtraStyles::SolarizedDark => solarized::solarized_dark().extension, + ExtraStyles::SolarizedLight => solarized::solarized_light().extension, + } + } + + /// Theme is a night/dark style + pub const fn is_nightly(self) -> bool { + match self { + ExtraStyles::DraculaDark + | ExtraStyles::GruvboxDark + | ExtraStyles::NordDark + | ExtraStyles::SolarizedDark => true, + ExtraStyles::DraculaLight + | ExtraStyles::GruvboxLight + | ExtraStyles::NordLight + | ExtraStyles::SolarizedLight => false, + } + } + + /// Slice of all implemented custom styles + pub const fn all_styles() -> &'static [Self] { + &[ + ExtraStyles::DraculaDark, + ExtraStyles::DraculaLight, + ExtraStyles::GruvboxDark, + ExtraStyles::GruvboxLight, + ExtraStyles::NordDark, + ExtraStyles::NordLight, + ExtraStyles::SolarizedDark, + ExtraStyles::SolarizedLight, + ] + } +} + +impl fmt::Display for ExtraStyles { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ExtraStyles::DraculaLight => write!(f, "Dracula (Day)"), + ExtraStyles::DraculaDark => write!(f, "Dracula (Night)"), + ExtraStyles::GruvboxDark => write!(f, "Gruvbox (Night)"), + ExtraStyles::GruvboxLight => write!(f, "Gruvbox (Day)"), + ExtraStyles::NordLight => write!(f, "Nord (Day)"), + ExtraStyles::NordDark => write!(f, "Nord (Night)"), + ExtraStyles::SolarizedLight => write!(f, "Solarized (Day)"), + ExtraStyles::SolarizedDark => write!(f, "Solarized (Night)"), + } + } +} diff --git a/src/gui/styles/types/mod.rs b/src/gui/styles/types/mod.rs index 803384dc7..4613b2da9 100644 --- a/src/gui/styles/types/mod.rs +++ b/src/gui/styles/types/mod.rs @@ -1,3 +1,4 @@ +pub mod custom_palette; pub mod gradient_type; pub mod palette; pub mod style_type; diff --git a/src/gui/styles/types/palette.rs b/src/gui/styles/types/palette.rs index fd0026381..1c27f514e 100644 --- a/src/gui/styles/types/palette.rs +++ b/src/gui/styles/types/palette.rs @@ -29,10 +29,6 @@ pub struct Palette { pub text_headers: Color, /// Color of body and buttons text pub text_body: Color, - /// Color of round container borders and scrollbar borders - pub round_borders: Color, - /// Color of round containers - pub round_containers: Color, } pub fn get_colors(style: StyleType) -> Palette { @@ -41,6 +37,7 @@ pub fn get_colors(style: StyleType) -> Palette { StyleType::Day => DAY_STYLE, StyleType::DeepSea => DEEP_SEA_STYLE, StyleType::MonAmour => MON_AMOUR_STYLE, + StyleType::Custom(style) => style.to_palette(), } } diff --git a/src/gui/styles/types/style_type.rs b/src/gui/styles/types/style_type.rs index c73508ed6..a097e1273 100644 --- a/src/gui/styles/types/style_type.rs +++ b/src/gui/styles/types/style_type.rs @@ -1,12 +1,16 @@ use serde::{Deserialize, Serialize}; +use crate::gui::styles::types::custom_palette::ExtraStyles; + /// Used to specify the kind of style of the application #[derive(Clone, Copy, Serialize, Deserialize, Debug, Hash, PartialEq)] +#[serde(tag = "style", content = "name")] pub enum StyleType { Night, Day, DeepSea, MonAmour, + Custom(ExtraStyles), } impl Default for StyleType { @@ -20,6 +24,7 @@ impl StyleType { match self { StyleType::Night | StyleType::DeepSea => true, StyleType::Day | StyleType::MonAmour => false, + StyleType::Custom(style) => style.is_nightly(), } } } diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs index 3b33e7d8f..8a84c8c6e 100644 --- a/src/gui/types/sniffer.rs +++ b/src/gui/types/sniffer.rs @@ -141,7 +141,7 @@ impl Sniffer { Message::Reset => return self.reset(), Message::Style(style) => { self.style = style; - self.traffic_chart.change_colors(self.style); + self.traffic_chart.change_style(self.style); } Message::Waiting => self.update_waiting_dots(), Message::AddOrRemoveFavorite(host, add) => self.add_or_remove_favorite(&host, add), @@ -522,8 +522,6 @@ mod tests { use crate::countries::types::country::Country; use crate::gui::components::types::my_modal::MyModal; use crate::gui::pages::types::settings_page::SettingsPage; - use crate::gui::styles::style_constants::get_color_mix_chart; - use crate::gui::styles::types::palette::to_rgb_color; use crate::gui::types::message::Message; use crate::networking::types::host::Host; use crate::notifications::types::logged_notification::{ @@ -534,8 +532,8 @@ mod tests { }; use crate::notifications::types::sound::Sound; use crate::{ - get_colors, AppProtocol, ByteMultiple, ChartType, InfoTraffic, IpVersion, Language, - ReportSortType, RunningPage, Sniffer, Status, StyleType, TransProtocol, + AppProtocol, ByteMultiple, ChartType, InfoTraffic, IpVersion, Language, ReportSortType, + RunningPage, Sniffer, Status, StyleType, TransProtocol, }; #[test] @@ -659,94 +657,14 @@ mod tests { sniffer.update(Message::Style(StyleType::MonAmour)); assert_eq!(sniffer.style, StyleType::MonAmour); - assert_eq!( - sniffer.traffic_chart.color_font, - to_rgb_color(get_colors(StyleType::MonAmour).text_body) - ); - assert_eq!( - sniffer.traffic_chart.color_outgoing, - to_rgb_color(get_colors(StyleType::MonAmour).outgoing) - ); - assert_eq!( - sniffer.traffic_chart.color_incoming, - to_rgb_color(get_colors(StyleType::MonAmour).secondary) - ); - assert_eq!( - sniffer.traffic_chart.color_mix, - get_color_mix_chart(StyleType::MonAmour) - ); sniffer.update(Message::Style(StyleType::Day)); assert_eq!(sniffer.style, StyleType::Day); - assert_eq!( - sniffer.traffic_chart.color_font, - to_rgb_color(get_colors(StyleType::Day).text_body) - ); - assert_eq!( - sniffer.traffic_chart.color_outgoing, - to_rgb_color(get_colors(StyleType::Day).outgoing) - ); - assert_eq!( - sniffer.traffic_chart.color_incoming, - to_rgb_color(get_colors(StyleType::Day).secondary) - ); - assert_eq!( - sniffer.traffic_chart.color_mix, - get_color_mix_chart(StyleType::Day) - ); sniffer.update(Message::Style(StyleType::Night)); assert_eq!(sniffer.style, StyleType::Night); - assert_eq!( - sniffer.traffic_chart.color_font, - to_rgb_color(get_colors(StyleType::Night).text_body) - ); - assert_eq!( - sniffer.traffic_chart.color_outgoing, - to_rgb_color(get_colors(StyleType::Night).outgoing) - ); - assert_eq!( - sniffer.traffic_chart.color_incoming, - to_rgb_color(get_colors(StyleType::Night).secondary) - ); - assert_eq!( - sniffer.traffic_chart.color_mix, - get_color_mix_chart(StyleType::Night) - ); sniffer.update(Message::Style(StyleType::DeepSea)); assert_eq!(sniffer.style, StyleType::DeepSea); - assert_eq!( - sniffer.traffic_chart.color_font, - to_rgb_color(get_colors(StyleType::DeepSea).text_body) - ); - assert_eq!( - sniffer.traffic_chart.color_outgoing, - to_rgb_color(get_colors(StyleType::DeepSea).outgoing) - ); - assert_eq!( - sniffer.traffic_chart.color_incoming, - to_rgb_color(get_colors(StyleType::DeepSea).secondary) - ); - assert_eq!( - sniffer.traffic_chart.color_mix, - get_color_mix_chart(StyleType::DeepSea) - ); sniffer.update(Message::Style(StyleType::DeepSea)); assert_eq!(sniffer.style, StyleType::DeepSea); - assert_eq!( - sniffer.traffic_chart.color_font, - to_rgb_color(get_colors(StyleType::DeepSea).text_body) - ); - assert_eq!( - sniffer.traffic_chart.color_outgoing, - to_rgb_color(get_colors(StyleType::DeepSea).outgoing) - ); - assert_eq!( - sniffer.traffic_chart.color_incoming, - to_rgb_color(get_colors(StyleType::DeepSea).secondary) - ); - assert_eq!( - sniffer.traffic_chart.color_mix, - get_color_mix_chart(StyleType::DeepSea) - ); } #[test]