diff --git a/src/context.rs b/src/context.rs index f233e79..14e9e87 100644 --- a/src/context.rs +++ b/src/context.rs @@ -575,10 +575,8 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, ' /// Updates `self` to have `opacity`. /// /// This setting will be mixed with the current opacity value. - #[must_use] - pub fn with_opacity(mut self, opacity: impl Into) -> Self { + pub fn apply_opacity(&mut self, opacity: impl Into) { self.gfx.opacity *= opacity.into(); - self } /// Returns a new graphics context that renders to the `clip` rectangle. @@ -668,15 +666,20 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, ' "redraw called without set_widget_layout" ); - let background = self.get(&WidgetBackground); - self.fill(background); - - self.apply_current_font_settings(); - self.current_node .tree .note_widget_rendered(self.current_node.node_id); - self.current_node.clone().lock().as_widget().redraw(self); + let widget = self.current_node.clone(); + let mut widget = widget.lock(); + if !widget.as_widget().full_control_redraw() { + let background = self.get(&WidgetBackground); + self.fill(background); + + self.apply_current_font_settings(); + self.apply_opacity(self.get(&Opacity)); + } + + widget.as_widget().redraw(self); } } diff --git a/src/widget.rs b/src/widget.rs index 3bb25cd..5aa0b08 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -63,6 +63,22 @@ pub trait Widget: Send + UnwindSafe + Debug + 'static { Debug::fmt(self, f) } + /// Returns true if this widget handles all built-in style components that + /// apply. + /// + /// These components are: + /// + /// - [`Opacity`](crate::styles::components::Opacity) + /// - [`WidgetBackground`](crate::styles::components::WidgetBackground) + /// - [`FontFamily`] + /// - [`TextSize`] + /// - [`LineHeight`] + /// - [`FontStyle`] + /// - [`FontWeight`] + fn full_control_redraw(&self) -> bool { + false + } + /// Layout this widget and returns the ideal size based on its contents and /// the `available_space`. #[allow(unused_variables)] diff --git a/src/widgets/container.rs b/src/widgets/container.rs index 41a2400..33eb3ec 100644 --- a/src/widgets/container.rs +++ b/src/widgets/container.rs @@ -8,7 +8,7 @@ use kludgine::shapes::{CornerRadii, PathBuilder, Shape}; use kludgine::Color; use crate::context::{EventContext, GraphicsContext, LayoutContext, WidgetContext}; -use crate::styles::components::{CornerRadius, IntrinsicPadding, SurfaceColor}; +use crate::styles::components::{CornerRadius, IntrinsicPadding, Opacity, SurfaceColor}; use crate::styles::{Component, ContainerLevel, Dimension, Edges, RequireInvalidation, Styles}; use crate::value::{Dynamic, IntoValue, Value}; use crate::widget::{MakeWidget, RootBehavior, Widget, WidgetInstance, WidgetRef}; @@ -211,9 +211,16 @@ impl Widget for Container { .finish() } + fn full_control_redraw(&self) -> bool { + true + } + #[allow(clippy::too_many_lines)] fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { + let opacity = context.get(&Opacity); + let background = self.effective_background_color(context); + let background = background.with_alpha_f32(background.alpha_f32() * *opacity); if background.alpha() > 0 { let shadow = self.effective_shadow(context).into_px(context.gfx.scale()); diff --git a/src/widgets/layers.rs b/src/widgets/layers.rs index 59953c4..7468a2c 100644 --- a/src/widgets/layers.rs +++ b/src/widgets/layers.rs @@ -9,7 +9,7 @@ use intentional::Assert; use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Size, Zero}; -use crate::animation::easings::{EaseInQuadradic, EaseOutQuadradic}; +use crate::animation::easings::EaseOutQuadradic; use crate::animation::{AnimationTarget, Spawn, ZeroToOne}; use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext}; use crate::value::{Dynamic, DynamicGuard, Generation, IntoValue, Value}; @@ -205,7 +205,9 @@ impl Widget for OverlayLayer { }; let opacity = child.opacity.get_tracking_refresh(context); - context.for_other(mounted).with_opacity(opacity).redraw(); + let mut context = context.for_other(mounted); + context.apply_opacity(opacity); + context.redraw(); } }