use apply::Apply; use cosmic::{ font::Font, iced::{ widget::{ self, container::draw_background, rule::FillMode, text::StyleSheet as TextStyleSheet, }, Element, }, iced_core::{ alignment, event, layout::{Layout, Limits, Node}, mouse, overlay, renderer, widget::{ operation::{Operation, OperationOutputWrapper}, tree::Tree, Id, Widget, }, Clipboard, Color, Length, Rectangle, Shell, Size, }, iced_style::{ button::StyleSheet as ButtonStyleSheet, container::StyleSheet as ContainerStyleSheet, rule::StyleSheet as RuleStyleSheet, }, iced_widget::scrollable::AbsoluteOffset, theme, widget::{icon, text, Icon}, }; use super::tab_text::tab_text; pub(super) enum TabRuleTheme { ActiveActivated, ActiveDeactivated, Default, } impl Into for TabRuleTheme { fn into(self) -> theme::Rule { match self { Self::ActiveActivated => theme::Rule::custom(|theme| widget::rule::Appearance { color: theme.cosmic().accent_color().into(), width: 4, radius: 0.0.into(), fill_mode: FillMode::Full, }), Self::ActiveDeactivated => theme::Rule::custom(|theme| widget::rule::Appearance { color: theme.cosmic().palette.neutral_5.into(), width: 4, radius: 0.0.into(), fill_mode: FillMode::Full, }), Self::Default => theme::Rule::custom(|theme| widget::rule::Appearance { color: theme.cosmic().palette.neutral_5.into(), width: 4, radius: 8.0.into(), fill_mode: FillMode::Padded(4), }), } } } pub(super) enum TabBackgroundTheme { ActiveActivated, ActiveDeactivated, Default, } impl TabBackgroundTheme { fn background_color(&self) -> Color { match self { TabBackgroundTheme::ActiveActivated => Color::from_rgba(0.365, 0.365, 0.365, 1.0), TabBackgroundTheme::ActiveDeactivated => Color::from_rgba(0.365, 0.365, 0.365, 1.0), TabBackgroundTheme::Default => Color::from_rgba(0.26, 0.26, 0.26, 1.0), } } } impl Into for TabBackgroundTheme { fn into(self) -> theme::Container { let background_color = cosmic::iced::Background::Color(self.background_color()); match self { Self::ActiveActivated => { theme::Container::custom(move |theme| widget::container::Appearance { text_color: Some(Color::from(theme.cosmic().accent_text_color())), background: Some(background_color), border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }) } Self::ActiveDeactivated => { theme::Container::custom(move |_theme| widget::container::Appearance { text_color: None, background: Some(background_color), border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }) } Self::Default => theme::Container::Transparent, } } } pub trait TabMessage { fn activate(idx: usize) -> Self; fn is_activate(&self) -> Option; fn scroll_further() -> Self; fn scroll_back() -> Self; fn populate_scroll(&mut self, current_offset: AbsoluteOffset) -> Option; fn scrolled() -> Self; } pub struct Tab<'a, Message: TabMessage> { id: Id, app_icon: Icon<'a>, title: String, font: Font, close_message: Option, rule_theme: TabRuleTheme, background_theme: TabBackgroundTheme, active: bool, } impl<'a, Message: TabMessage> Tab<'a, Message> { pub fn new(title: impl Into, app_id: impl Into, id: Id) -> Self { Tab { id, app_icon: icon(app_id.into(), 16), title: title.into(), font: cosmic::font::FONT, close_message: None, rule_theme: TabRuleTheme::Default, background_theme: TabBackgroundTheme::Default, active: false, } } pub fn on_close(mut self, message: Message) -> Self { self.close_message = Some(message); self } pub(super) fn font(mut self, font: Font) -> Self { self.font = font; self } pub(super) fn rule_style(mut self, theme: TabRuleTheme) -> Self { self.rule_theme = theme; self } pub(super) fn background_style(mut self, theme: TabBackgroundTheme) -> Self { self.background_theme = theme; self } pub(super) fn non_active(mut self) -> Self { self.active = false; self } pub(super) fn active(mut self) -> Self { self.active = true; self } pub(super) fn internal(self, idx: usize) -> TabInternal<'a, Message, Renderer> where Renderer: cosmic::iced_core::Renderer + 'a, Renderer: cosmic::iced_core::text::Renderer, Renderer::Theme: ButtonStyleSheet