mirror of
https://github.com/danbulant/cushy
synced 2026-06-08 09:01:12 +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>,
|
window: &'context mut RunningWindow<'window>,
|
||||||
theme: Cow<'context, ThemePair>,
|
theme: Cow<'context, ThemePair>,
|
||||||
pending_state: PendingState<'context>,
|
pending_state: PendingState<'context>,
|
||||||
theme_mode: ThemeMode,
|
|
||||||
effective_styles: Styles,
|
effective_styles: Styles,
|
||||||
enabled: bool,
|
cache: WidgetCacheKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'context, 'window> WidgetContext<'context, 'window> {
|
impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
|
|
@ -736,11 +735,14 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
focus_is_advancing: false,
|
focus_is_advancing: false,
|
||||||
}),
|
}),
|
||||||
effective_styles: current_node.effective_styles(),
|
effective_styles: current_node.effective_styles(),
|
||||||
enabled,
|
cache: WidgetCacheKey {
|
||||||
|
theme_mode,
|
||||||
|
enabled,
|
||||||
|
invalidation: current_node.invalidation(),
|
||||||
|
},
|
||||||
current_node,
|
current_node,
|
||||||
redraw_status,
|
redraw_status,
|
||||||
theme: Cow::Borrowed(theme),
|
theme: Cow::Borrowed(theme),
|
||||||
theme_mode,
|
|
||||||
window,
|
window,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -753,9 +755,8 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
window: &mut *self.window,
|
window: &mut *self.window,
|
||||||
theme: Cow::Borrowed(self.theme.as_ref()),
|
theme: Cow::Borrowed(self.theme.as_ref()),
|
||||||
pending_state: self.pending_state.borrowed(),
|
pending_state: self.pending_state.borrowed(),
|
||||||
theme_mode: self.theme_mode,
|
cache: self.cache,
|
||||||
effective_styles: self.effective_styles.clone(),
|
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 {
|
let theme_mode = if let Some(mode) = theme_mode {
|
||||||
mode.get_tracked(self)
|
mode.get_tracked(self)
|
||||||
} else {
|
} else {
|
||||||
self.theme_mode
|
self.cache.theme_mode
|
||||||
};
|
};
|
||||||
WidgetContext {
|
WidgetContext {
|
||||||
effective_styles,
|
effective_styles,
|
||||||
enabled: current_node.enabled(&self.handle()),
|
cache: WidgetCacheKey {
|
||||||
|
theme_mode,
|
||||||
|
enabled: current_node.enabled(&self.handle()),
|
||||||
|
invalidation: current_node.invalidation(),
|
||||||
|
},
|
||||||
current_node,
|
current_node,
|
||||||
redraw_status: self.redraw_status,
|
redraw_status: self.redraw_status,
|
||||||
window: &mut *self.window,
|
window: &mut *self.window,
|
||||||
theme,
|
theme,
|
||||||
pending_state: self.pending_state.borrowed(),
|
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.
|
/// Returns true if this widget is enabled.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn enabled(&self) -> bool {
|
pub const fn enabled(&self) -> bool {
|
||||||
self.enabled
|
self.cache.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parent(&self) -> Option<ManagedWidget> {
|
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.
|
/// Returns the current theme in either light or dark mode.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn theme(&self) -> &Theme {
|
pub fn theme(&self) -> &Theme {
|
||||||
match self.theme_mode {
|
match self.cache.theme_mode {
|
||||||
ThemeMode::Light => &self.theme.light,
|
ThemeMode::Light => &self.theme.light,
|
||||||
ThemeMode::Dark => &self.theme.dark,
|
ThemeMode::Dark => &self.theme.dark,
|
||||||
}
|
}
|
||||||
|
|
@ -1013,11 +1017,18 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
/// Returns the opposite theme of [`Self::theme()`].
|
/// Returns the opposite theme of [`Self::theme()`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn inverse_theme(&self) -> &Theme {
|
pub fn inverse_theme(&self) -> &Theme {
|
||||||
match self.theme_mode {
|
match self.cache.theme_mode {
|
||||||
ThemeMode::Light => &self.theme.dark,
|
ThemeMode::Light => &self.theme.dark,
|
||||||
ThemeMode::Dark => &self.theme.light,
|
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)]
|
#[derive(Clone)]
|
||||||
|
|
@ -1207,3 +1218,24 @@ impl<T> MapManagedWidget<T> for ManagedWidget {
|
||||||
map(self)
|
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)
|
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 {
|
pub(crate) fn is_enabled(&self, mut id: LotId, context: &WindowHandle) -> bool {
|
||||||
let data = self.data.lock().ignore_poison();
|
let data = self.data.lock().ignore_poison();
|
||||||
loop {
|
loop {
|
||||||
|
|
|
||||||
|
|
@ -1186,6 +1186,10 @@ impl ManagedWidget {
|
||||||
self.tree.is_enabled(self.node_id, handle)
|
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.
|
/// Returns true if this widget is currently the hovered widget.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hovered(&self) -> bool {
|
pub fn hovered(&self) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ use kludgine::shapes::{Shape, StrokeOptions};
|
||||||
use kludgine::Color;
|
use kludgine::Color;
|
||||||
|
|
||||||
use crate::animation::{AnimationHandle, AnimationTarget, LinearInterpolate, Spawn};
|
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::{
|
use crate::styles::components::{
|
||||||
AutoFocusableControls, Easing, HighlightColor, IntrinsicPadding, OpaqueWidgetColor,
|
AutoFocusableControls, Easing, HighlightColor, IntrinsicPadding, OpaqueWidgetColor,
|
||||||
OutlineColor, SurfaceColor, TextColor,
|
OutlineColor, SurfaceColor, TextColor,
|
||||||
|
|
@ -36,7 +38,7 @@ pub struct Button {
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
struct CacheState {
|
struct CacheState {
|
||||||
enabled: bool,
|
key: WidgetCacheKey,
|
||||||
kind: ButtonKind,
|
kind: ButtonKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +131,7 @@ impl Button {
|
||||||
content: content.widget_ref(),
|
content: content.widget_ref(),
|
||||||
on_click: None,
|
on_click: None,
|
||||||
cached_state: CacheState {
|
cached_state: CacheState {
|
||||||
enabled: true,
|
key: WidgetCacheKey::default(),
|
||||||
kind: ButtonKind::default(),
|
kind: ButtonKind::default(),
|
||||||
},
|
},
|
||||||
buttons_pressed: 0,
|
buttons_pressed: 0,
|
||||||
|
|
@ -213,11 +215,12 @@ impl Button {
|
||||||
let visual_state = Self::visual_style(context);
|
let visual_state = Self::visual_style(context);
|
||||||
|
|
||||||
self.cached_state = CacheState {
|
self.cached_state = CacheState {
|
||||||
enabled: !matches!(visual_state, VisualState::Disabled),
|
key: context.cache_key(),
|
||||||
kind,
|
kind,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.cached_state.enabled {
|
// TODO this should be genericized to happen automatically.
|
||||||
|
if !context.enabled() {
|
||||||
context.blur();
|
context.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,12 +334,9 @@ impl VisualState {
|
||||||
impl Widget for Button {
|
impl Widget for Button {
|
||||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||||
#![allow(clippy::similar_names)]
|
#![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);
|
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);
|
self.update_colors(context, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue