Widget::full_control_redraw

+ transparent containers show their shadows properly
This commit is contained in:
Jonathan Johnson 2023-12-13 14:45:56 -08:00
parent 353db9dc39
commit cd4bb5130f
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
4 changed files with 40 additions and 12 deletions

View file

@ -575,10 +575,8 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
/// Updates `self` to have `opacity`. /// Updates `self` to have `opacity`.
/// ///
/// This setting will be mixed with the current opacity value. /// This setting will be mixed with the current opacity value.
#[must_use] pub fn apply_opacity(&mut self, opacity: impl Into<ZeroToOne>) {
pub fn with_opacity(mut self, opacity: impl Into<ZeroToOne>) -> Self {
self.gfx.opacity *= opacity.into(); self.gfx.opacity *= opacity.into();
self
} }
/// Returns a new graphics context that renders to the `clip` rectangle. /// 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" "redraw called without set_widget_layout"
); );
let background = self.get(&WidgetBackground);
self.fill(background);
self.apply_current_font_settings();
self.current_node self.current_node
.tree .tree
.note_widget_rendered(self.current_node.node_id); .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);
} }
} }

View file

@ -63,6 +63,22 @@ pub trait Widget: Send + UnwindSafe + Debug + 'static {
Debug::fmt(self, f) 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 /// Layout this widget and returns the ideal size based on its contents and
/// the `available_space`. /// the `available_space`.
#[allow(unused_variables)] #[allow(unused_variables)]

View file

@ -8,7 +8,7 @@ use kludgine::shapes::{CornerRadii, PathBuilder, Shape};
use kludgine::Color; use kludgine::Color;
use crate::context::{EventContext, GraphicsContext, LayoutContext, WidgetContext}; 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::styles::{Component, ContainerLevel, Dimension, Edges, RequireInvalidation, Styles};
use crate::value::{Dynamic, IntoValue, Value}; use crate::value::{Dynamic, IntoValue, Value};
use crate::widget::{MakeWidget, RootBehavior, Widget, WidgetInstance, WidgetRef}; use crate::widget::{MakeWidget, RootBehavior, Widget, WidgetInstance, WidgetRef};
@ -211,9 +211,16 @@ impl Widget for Container {
.finish() .finish()
} }
fn full_control_redraw(&self) -> bool {
true
}
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
let opacity = context.get(&Opacity);
let background = self.effective_background_color(context); let background = self.effective_background_color(context);
let background = background.with_alpha_f32(background.alpha_f32() * *opacity);
if background.alpha() > 0 { if background.alpha() > 0 {
let shadow = self.effective_shadow(context).into_px(context.gfx.scale()); let shadow = self.effective_shadow(context).into_px(context.gfx.scale());

View file

@ -9,7 +9,7 @@ use intentional::Assert;
use kludgine::figures::units::{Px, UPx}; use kludgine::figures::units::{Px, UPx};
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Size, Zero}; 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::animation::{AnimationTarget, Spawn, ZeroToOne};
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext}; use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
use crate::value::{Dynamic, DynamicGuard, Generation, IntoValue, Value}; use crate::value::{Dynamic, DynamicGuard, Generation, IntoValue, Value};
@ -205,7 +205,9 @@ impl Widget for OverlayLayer {
}; };
let opacity = child.opacity.get_tracking_refresh(context); 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();
} }
} }