mirror of
https://github.com/danbulant/cushy
synced 2026-05-24 12:28:23 +00:00
Added WidgetCacheKey
This commit is contained in:
parent
534f676ef0
commit
5506a24dae
4 changed files with 62 additions and 21 deletions
|
|
@ -706,9 +706,8 @@ pub struct WidgetContext<'context, 'window> {
|
|||
window: &'context mut RunningWindow<'window>,
|
||||
theme: Cow<'context, ThemePair>,
|
||||
pending_state: PendingState<'context>,
|
||||
theme_mode: ThemeMode,
|
||||
effective_styles: Styles,
|
||||
enabled: bool,
|
||||
cache: WidgetCacheKey,
|
||||
}
|
||||
|
||||
impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||
|
|
@ -736,11 +735,14 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
focus_is_advancing: false,
|
||||
}),
|
||||
effective_styles: current_node.effective_styles(),
|
||||
enabled,
|
||||
cache: WidgetCacheKey {
|
||||
theme_mode,
|
||||
enabled,
|
||||
invalidation: current_node.invalidation(),
|
||||
},
|
||||
current_node,
|
||||
redraw_status,
|
||||
theme: Cow::Borrowed(theme),
|
||||
theme_mode,
|
||||
window,
|
||||
}
|
||||
}
|
||||
|
|
@ -753,9 +755,8 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
window: &mut *self.window,
|
||||
theme: Cow::Borrowed(self.theme.as_ref()),
|
||||
pending_state: self.pending_state.borrowed(),
|
||||
theme_mode: self.theme_mode,
|
||||
cache: self.cache,
|
||||
effective_styles: self.effective_styles.clone(),
|
||||
enabled: self.enabled,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -778,17 +779,20 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
let theme_mode = if let Some(mode) = theme_mode {
|
||||
mode.get_tracked(self)
|
||||
} else {
|
||||
self.theme_mode
|
||||
self.cache.theme_mode
|
||||
};
|
||||
WidgetContext {
|
||||
effective_styles,
|
||||
enabled: current_node.enabled(&self.handle()),
|
||||
cache: WidgetCacheKey {
|
||||
theme_mode,
|
||||
enabled: current_node.enabled(&self.handle()),
|
||||
invalidation: current_node.invalidation(),
|
||||
},
|
||||
current_node,
|
||||
redraw_status: self.redraw_status,
|
||||
window: &mut *self.window,
|
||||
theme,
|
||||
pending_state: self.pending_state.borrowed(),
|
||||
theme_mode,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -796,7 +800,7 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
/// Returns true if this widget is enabled.
|
||||
#[must_use]
|
||||
pub const fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
self.cache.enabled
|
||||
}
|
||||
|
||||
pub(crate) fn parent(&self) -> Option<ManagedWidget> {
|
||||
|
|
@ -1004,7 +1008,7 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
/// Returns the current theme in either light or dark mode.
|
||||
#[must_use]
|
||||
pub fn theme(&self) -> &Theme {
|
||||
match self.theme_mode {
|
||||
match self.cache.theme_mode {
|
||||
ThemeMode::Light => &self.theme.light,
|
||||
ThemeMode::Dark => &self.theme.dark,
|
||||
}
|
||||
|
|
@ -1013,11 +1017,18 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
/// Returns the opposite theme of [`Self::theme()`].
|
||||
#[must_use]
|
||||
pub fn inverse_theme(&self) -> &Theme {
|
||||
match self.theme_mode {
|
||||
match self.cache.theme_mode {
|
||||
ThemeMode::Light => &self.theme.dark,
|
||||
ThemeMode::Dark => &self.theme.light,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a key that can be checked to see if a widget should invalidate
|
||||
/// caches it stores.
|
||||
#[must_use]
|
||||
pub fn cache_key(&self) -> WidgetCacheKey {
|
||||
self.cache
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -1207,3 +1218,24 @@ impl<T> MapManagedWidget<T> for ManagedWidget {
|
|||
map(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// An type that contains information about the state of a widget.
|
||||
///
|
||||
/// This value can be stored and compared in future widget events. If the cache
|
||||
/// keys are not equal, the widget should clear all caches.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct WidgetCacheKey {
|
||||
theme_mode: ThemeMode,
|
||||
enabled: bool,
|
||||
invalidation: u64,
|
||||
}
|
||||
|
||||
impl Default for WidgetCacheKey {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
theme_mode: ThemeMode::default().inverse(),
|
||||
enabled: false,
|
||||
invalidation: u64::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,6 +277,11 @@ impl Tree {
|
|||
data.widget_from_node(id, self)
|
||||
}
|
||||
|
||||
pub(crate) fn invalidation(&self, id: LotId) -> Option<u64> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
data.nodes.get(id).map(|node| node.invalidation)
|
||||
}
|
||||
|
||||
pub(crate) fn is_enabled(&self, mut id: LotId, context: &WindowHandle) -> bool {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -1186,6 +1186,10 @@ impl ManagedWidget {
|
|||
self.tree.is_enabled(self.node_id, handle)
|
||||
}
|
||||
|
||||
pub(crate) fn invalidation(&self) -> u64 {
|
||||
self.tree.invalidation(self.node_id).expect("missing node")
|
||||
}
|
||||
|
||||
/// Returns true if this widget is currently the hovered widget.
|
||||
#[must_use]
|
||||
pub fn hovered(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ use kludgine::shapes::{Shape, StrokeOptions};
|
|||
use kludgine::Color;
|
||||
|
||||
use crate::animation::{AnimationHandle, AnimationTarget, LinearInterpolate, Spawn};
|
||||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext, WidgetContext};
|
||||
use crate::context::{
|
||||
AsEventContext, EventContext, GraphicsContext, LayoutContext, WidgetCacheKey, WidgetContext,
|
||||
};
|
||||
use crate::styles::components::{
|
||||
AutoFocusableControls, Easing, HighlightColor, IntrinsicPadding, OpaqueWidgetColor,
|
||||
OutlineColor, SurfaceColor, TextColor,
|
||||
|
|
@ -36,7 +38,7 @@ pub struct Button {
|
|||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
struct CacheState {
|
||||
enabled: bool,
|
||||
key: WidgetCacheKey,
|
||||
kind: ButtonKind,
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ impl Button {
|
|||
content: content.widget_ref(),
|
||||
on_click: None,
|
||||
cached_state: CacheState {
|
||||
enabled: true,
|
||||
key: WidgetCacheKey::default(),
|
||||
kind: ButtonKind::default(),
|
||||
},
|
||||
buttons_pressed: 0,
|
||||
|
|
@ -213,11 +215,12 @@ impl Button {
|
|||
let visual_state = Self::visual_style(context);
|
||||
|
||||
self.cached_state = CacheState {
|
||||
enabled: !matches!(visual_state, VisualState::Disabled),
|
||||
key: context.cache_key(),
|
||||
kind,
|
||||
};
|
||||
|
||||
if !self.cached_state.enabled {
|
||||
// TODO this should be genericized to happen automatically.
|
||||
if !context.enabled() {
|
||||
context.blur();
|
||||
}
|
||||
|
||||
|
|
@ -331,12 +334,9 @@ impl VisualState {
|
|||
impl Widget for Button {
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
#![allow(clippy::similar_names)]
|
||||
let enabled = context.enabled();
|
||||
|
||||
// TODO This seems ugly. It needs context, so it can't be moved into the
|
||||
// dynamic system.
|
||||
let current_style = self.kind.get_tracked(context);
|
||||
if self.cached_state.enabled != enabled || self.cached_state.kind != current_style {
|
||||
if self.cached_state.key != context.cache_key() || self.cached_state.kind != current_style {
|
||||
self.update_colors(context, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue