From 072a3d5ca0032df6caa9011860fc496500c2a840 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 9 Feb 2024 12:43:05 -0500 Subject: [PATCH] feat: lower the opacity of colors used in the segmented button when disabled This is needed for the new tiling applet. Transparent text only seems to be working with the wgpu feature at the moment --- examples/cosmic/Cargo.toml | 2 +- examples/cosmic/src/window/demo.rs | 10 +++ src/widget/segmented_button/widget.rs | 104 +++++++++++++++++--------- 3 files changed, 78 insertions(+), 38 deletions(-) diff --git a/examples/cosmic/Cargo.toml b/examples/cosmic/Cargo.toml index 4a704a1e..d89f652d 100644 --- a/examples/cosmic/Cargo.toml +++ b/examples/cosmic/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] apply = "0.3.0" fraction = "0.14.0" -libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "dbus-config", "a11y" ] } +libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "dbus-config", "a11y", "wgpu" ] } once_cell = "1.18" slotmap = "1.0.6" env_logger = "0.10" diff --git a/examples/cosmic/src/window/demo.rs b/examples/cosmic/src/window/demo.rs index 53152356..b863f0b4 100644 --- a/examples/cosmic/src/window/demo.rs +++ b/examples/cosmic/src/window/demo.rs @@ -330,15 +330,25 @@ impl State { .spacing(8) .on_activate(Message::Selection) .into(), + text("Disabled Horizontal With Spacing").into(), + segmented_selection::horizontal(&self.selection) + .spacing(8) + .into(), text("Horizontal Multi-Select").into(), segmented_selection::horizontal(&self.multi_selection) .spacing(8) .on_activate(Message::MultiSelection) .into(), + text("Disabled Horizontal Multi-Select").into(), + segmented_selection::horizontal(&self.multi_selection) + .spacing(8) + .into(), text("Vertical").into(), segmented_selection::vertical(&self.selection) .on_activate(Message::Selection) .into(), + text("Disabled Vertical").into(), + segmented_selection::vertical(&self.selection).into(), text("Vertical Multi-Select Shrunk").into(), segmented_selection::vertical(&self.multi_selection) .width(Length::Shrink) diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 9f376c53..e3bee4aa 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -14,7 +14,7 @@ use iced_core::mouse::ScrollDelta; use iced_core::text::{LineHeight, Paragraph, Renderer as TextRenderer, Shaping}; use iced_core::widget::{self, operation, tree}; use iced_core::{layout, renderer, widget::Tree, Clipboard, Layout, Shell, Widget}; -use iced_core::{Border, Point, Renderer as IcedRenderer, Shadow, Text}; +use iced_core::{Border, Gradient, Point, Renderer as IcedRenderer, Shadow, Text}; use slotmap::{Key, SecondaryMap}; use std::marker::PhantomData; use std::time::{Duration, Instant}; @@ -686,6 +686,9 @@ where _viewport: &iced::Rectangle, _renderer: &Renderer, ) -> iced_core::mouse::Interaction { + if self.on_activate.is_none() { + return iced_core::mouse::Interaction::default(); + } let state = tree.state.downcast_ref::(); let bounds = layout.bounds(); @@ -719,7 +722,31 @@ where let appearance = Self::variant_appearance(theme, &self.style); let bounds = layout.bounds(); let button_amount = self.model.items.len(); - + let apply_alpha = |mut c: Color| { + if self.on_activate.is_some() { + c + } else { + c.a /= 2.0; + c + } + }; + let bg_with_alpha = |mut b| { + match &mut b { + Background::Color(c) => { + *c = apply_alpha(*c); + } + Background::Gradient(g) => { + let Gradient::Linear(mut l) = g; + for c in &mut l.stops { + let Some(stop) = c else { + continue; + }; + stop.color = apply_alpha(stop.color); + } + } + } + b + }; // Draw the background, if a background was defined. if let Some(background) = appearance.background { renderer.fill_quad( @@ -731,20 +758,21 @@ where }, shadow: Shadow::default(), }, - background, + bg_with_alpha(background), ); } // Draw previous and next tab buttons if there is a need to paginate tabs. if state.collapsed { // Previous tab button - let mut background_appearance = if Item::PrevButton == state.focused_item { - Some(appearance.focus) - } else if Item::PrevButton == state.hovered { - Some(appearance.hover) - } else { - None - }; + let mut background_appearance = + if self.on_activate.is_some() && Item::PrevButton == state.focused_item { + Some(appearance.focus) + } else if self.on_activate.is_some() && Item::PrevButton == state.hovered { + Some(appearance.hover) + } else { + None + }; if let Some(background_appearance) = background_appearance.take() { renderer.fill_quad( @@ -763,7 +791,7 @@ where }, background_appearance .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), + .map_or(Background::Color(Color::TRANSPARENT), bg_with_alpha), ); } @@ -773,13 +801,13 @@ where style, cursor, viewport, - if state.buttons_offset == 0 { + apply_alpha(if state.buttons_offset == 0 { appearance.inactive.text_color } else if let Item::PrevButton = state.focused_item { appearance.focus.text_color } else { appearance.active.text_color - }, + }), Rectangle { x: bounds.x + f32::from(self.button_height) / 4.0, y: bounds.y + f32::from(self.button_height) / 4.0, @@ -790,13 +818,14 @@ where ); // Next tab button - background_appearance = if Item::NextButton == state.focused_item { - Some(appearance.focus) - } else if Item::NextButton == state.hovered { - Some(appearance.hover) - } else { - None - }; + background_appearance = + if self.on_activate.is_some() && Item::NextButton == state.focused_item { + Some(appearance.focus) + } else if self.on_activate.is_some() && Item::NextButton == state.hovered { + Some(appearance.hover) + } else { + None + }; if let Some(background_appearance) = background_appearance { renderer.fill_quad( @@ -825,13 +854,13 @@ where style, cursor, viewport, - if self.next_tab_sensitive(state) { + apply_alpha(if self.next_tab_sensitive(state) { appearance.active.text_color } else if let Item::NextButton = state.focused_item { appearance.focus.text_color } else { appearance.inactive.text_color - }, + }), Rectangle { x: bounds.x + bounds.width - f32::from(self.button_height) + f32::from(self.button_height) / 4.0, @@ -846,17 +875,18 @@ where // Draw each of the items in the widget. for (nth, (key, mut bounds)) in self.variant_button_bounds(state, bounds).enumerate() { let key_is_active = self.model.is_active(key); - let key_is_hovered = state.hovered == Item::Tab(key); + let key_is_hovered = self.on_activate.is_some() && state.hovered == Item::Tab(key); - let (status_appearance, font) = if Item::Tab(key) == state.focused_item { - (appearance.focus, &self.font_active) - } else if key_is_active { - (appearance.active, &self.font_active) - } else if key_is_hovered { - (appearance.hover, &self.font_hovered) - } else { - (appearance.inactive, &self.font_inactive) - }; + let (status_appearance, font) = + if self.on_activate.is_some() && Item::Tab(key) == state.focused_item { + (appearance.focus, &self.font_active) + } else if key_is_active { + (appearance.active, &self.font_active) + } else if key_is_hovered { + (appearance.hover, &self.font_hovered) + } else { + (appearance.inactive, &self.font_inactive) + }; let font = font.unwrap_or_else(|| renderer.default_font()); let button_appearance = if nth == 0 { @@ -880,7 +910,7 @@ where }, status_appearance .background - .unwrap_or(Background::Color(Color::TRANSPARENT)), + .map_or(Background::Color(Color::TRANSPARENT), bg_with_alpha), ); } @@ -900,7 +930,7 @@ where }, shadow: Shadow::default(), }, - background, + bg_with_alpha(background.into()), ); } @@ -931,7 +961,7 @@ where style, cursor, viewport, - status_appearance.text_color, + apply_alpha(status_appearance.text_color), Rectangle { width, height: width, @@ -977,7 +1007,7 @@ where line_height: self.line_height, }, bounds.position(), - status_appearance.text_color, + apply_alpha(status_appearance.text_color), Rectangle { width: { let width = bounds.width - close_icon_width; @@ -1004,7 +1034,7 @@ where style, cursor, viewport, - status_appearance.text_color, + apply_alpha(status_appearance.text_color), close_button_bounds, self.close_icon.clone(), );