mirror of
https://github.com/danbulant/cushy
synced 2026-06-19 06:21:15 +00:00
Small improvements
- Caching font family resolution to avoid scanning the database over and over. The db should still be cached, but this makes repeated setting free. - into_switcher rename for Dynamic<WidgetInstance> to avoid conflicting with Switchable::switcher() - Dynamic debugging is less verbose - IntoDynamic<Validation> for Result<T,E> - Input no longer blinks cursor when disabled.
This commit is contained in:
parent
8f99ae19fd
commit
a3e45d1d86
7 changed files with 98 additions and 23 deletions
|
|
@ -17,7 +17,7 @@ fn main() -> gooey::Result {
|
|||
AppState::Winner(winner) => game_end(*winner, &app).make_widget(),
|
||||
}
|
||||
}))
|
||||
.switcher()
|
||||
.into_switcher()
|
||||
.contain()
|
||||
.width(Lp::inches(2)..Lp::inches(6))
|
||||
.height(Lp::inches(2)..Lp::inches(6))
|
||||
|
|
|
|||
|
|
@ -623,15 +623,6 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
|
|||
self.gfx.set_font_weight(self.widget.get(&FontWeight));
|
||||
}
|
||||
|
||||
// /// Applies the current style settings for font family, text size, font
|
||||
// /// style, and font weight.
|
||||
// pub fn apply_current_font_settings_to<'a>(&self, attrs: Attrs<'a>) -> Attrs<'a> {
|
||||
// attrs.set_available_font_family(&self.widget.get(&FontFamily));
|
||||
// attrs.set_font_size(self.widget.get(&TextSize));
|
||||
// attrs.set_font_style(self.widget.get(&FontStyle));
|
||||
// attrs.set_font_weight(self.widget.get(&FontWeight));
|
||||
// }
|
||||
|
||||
/// Invokes [`Widget::redraw()`](crate::widget::Widget::redraw) on this
|
||||
/// context's widget.
|
||||
///
|
||||
|
|
@ -1270,6 +1261,14 @@ pub trait ManageWidget {
|
|||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed;
|
||||
}
|
||||
|
||||
impl ManageWidget for WidgetId {
|
||||
type Managed = Option<ManagedWidget>;
|
||||
|
||||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed {
|
||||
context.current_node.tree.widget(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ManageWidget for WidgetInstance {
|
||||
type Managed = Option<ManagedWidget>;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use crate::styles::FontFamilyList;
|
|||
pub struct Graphics<'clip, 'gfx, 'pass> {
|
||||
renderer: RenderContext<'clip, 'gfx, 'pass>,
|
||||
region: Rect<Px>,
|
||||
current_font_family: &'clip mut Option<FontFamilyList>,
|
||||
}
|
||||
|
||||
enum RenderContext<'clip, 'gfx, 'pass> {
|
||||
|
|
@ -29,10 +30,14 @@ enum RenderContext<'clip, 'gfx, 'pass> {
|
|||
impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
||||
/// Returns a new graphics context for the given [`Renderer`].
|
||||
#[must_use]
|
||||
pub fn new(renderer: Renderer<'gfx, 'pass>) -> Self {
|
||||
pub fn new(
|
||||
renderer: Renderer<'gfx, 'pass>,
|
||||
current_font_family: &'clip mut Option<FontFamilyList>,
|
||||
) -> Self {
|
||||
Self {
|
||||
region: renderer.clip_rect().into_signed(),
|
||||
renderer: RenderContext::Renderer(renderer),
|
||||
current_font_family,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,8 +91,11 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
|||
|
||||
/// Sets the font family to the first family in `list`.
|
||||
pub fn set_available_font_family(&mut self, list: &FontFamilyList) {
|
||||
if let Some(family) = self.find_available_font_family(list) {
|
||||
self.set_font_family(family);
|
||||
if self.current_font_family.as_ref() != Some(list) {
|
||||
*self.current_font_family = Some(list.clone());
|
||||
if let Some(family) = self.find_available_font_family(list) {
|
||||
self.set_font_family(family);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +131,7 @@ impl<'clip, 'gfx, 'pass> Graphics<'clip, 'gfx, 'pass> {
|
|||
Graphics {
|
||||
renderer: RenderContext::Clipped(self.renderer.clipped_to(new_clip)),
|
||||
region,
|
||||
current_font_family: &mut *self.current_font_family,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
61
src/value.rs
61
src/value.rs
|
|
@ -1,7 +1,7 @@
|
|||
//! Types for storing and interacting with values in Widgets.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::future::Future;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
use std::ops::{Deref, DerefMut, Not};
|
||||
|
|
@ -25,7 +25,6 @@ use crate::widgets::{Radio, Select, Space, Switcher};
|
|||
|
||||
/// An instance of a value that provides APIs to observe and react to its
|
||||
/// contents.
|
||||
#[derive(Debug)]
|
||||
pub struct Dynamic<T>(Arc<DynamicData<T>>);
|
||||
|
||||
impl<T> Dynamic<T> {
|
||||
|
|
@ -598,18 +597,34 @@ impl<T> Dynamic<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for Dynamic<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0.state() {
|
||||
Ok(state) => f
|
||||
.debug_struct("Dynamic")
|
||||
.field("value", &state.wrapped.value)
|
||||
.field("generation", &state.wrapped.generation)
|
||||
.finish(),
|
||||
Err(_) => f.debug_tuple("Dynamic").field(&"<unable to lock>").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dynamic<WidgetInstance> {
|
||||
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
||||
/// dynamic.
|
||||
#[must_use]
|
||||
pub fn switcher(self) -> Switcher {
|
||||
pub fn into_switcher(self) -> Switcher {
|
||||
Switcher::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Dynamic<WidgetInstance> {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
self.switcher().make_with_id(id)
|
||||
self.into_switcher().make_with_id(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -634,6 +649,8 @@ impl<T> context::sealed::Trackable for Dynamic<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Dynamic<T> {}
|
||||
|
||||
impl<T> PartialEq for Dynamic<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.0, &other.0)
|
||||
|
|
@ -833,7 +850,7 @@ struct DeadlockError;
|
|||
impl std::error::Error for DeadlockError {}
|
||||
|
||||
impl Display for DeadlockError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("a deadlock was detected")
|
||||
}
|
||||
}
|
||||
|
|
@ -869,7 +886,7 @@ impl<T> Debug for State<T>
|
|||
where
|
||||
T: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("State")
|
||||
.field("wrapped", &self.wrapped)
|
||||
.field("readers", &self.readers)
|
||||
|
|
@ -988,6 +1005,17 @@ pub struct DynamicGuard<'a, T> {
|
|||
accessed_mut: bool,
|
||||
}
|
||||
|
||||
impl<T> DynamicGuard<'_, T> {
|
||||
/// Returns the generation of the value at the time of locking the dynamic.
|
||||
///
|
||||
/// Even if this guard accesses the data through [`DerefMut`], this value
|
||||
/// will remain unchanged while the guard is held.
|
||||
#[must_use]
|
||||
pub fn generation(&self) -> Generation {
|
||||
self.guard.wrapped.generation
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for DynamicGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
|
|
@ -1896,6 +1924,19 @@ impl Validation {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, E> IntoDynamic<Validation> for Dynamic<Result<T, E>>
|
||||
where
|
||||
T: Send + 'static,
|
||||
E: Display + Send + 'static,
|
||||
{
|
||||
fn into_dynamic(self) -> Dynamic<Validation> {
|
||||
self.map_each(|result| match result {
|
||||
Ok(_) => Validation::Valid,
|
||||
Err(err) => Validation::Invalid(err.to_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A grouping of validations that can be checked simultaneously.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Validations {
|
||||
|
|
@ -2135,13 +2176,17 @@ impl WhenValidation<'_> {
|
|||
/// The validation is linked with `self` such that checking `self`'s
|
||||
/// validation status will include this validation.
|
||||
#[must_use]
|
||||
pub fn validate_result<E>(&self, result: impl IntoDynamic<Result<(), E>>) -> Dynamic<Validation>
|
||||
pub fn validate_result<T, E>(
|
||||
&self,
|
||||
result: impl IntoDynamic<Result<T, E>>,
|
||||
) -> Dynamic<Validation>
|
||||
where
|
||||
T: Send + 'static,
|
||||
E: Display + Send + 'static,
|
||||
{
|
||||
let result = result.into_dynamic();
|
||||
let error_message = result.map_each(move |value| match value {
|
||||
Ok(()) => None,
|
||||
Ok(_) => None,
|
||||
Err(err) => Some(err.to_string()),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -800,6 +800,15 @@ impl<const N: usize> GridWidgets<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> From<Vec<T>> for GridWidgets<N>
|
||||
where
|
||||
T: Into<GridSection<N>>,
|
||||
{
|
||||
fn from(value: Vec<T>) -> Self {
|
||||
Self(value.into_iter().map(T::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> From<T> for GridWidgets<N>
|
||||
where
|
||||
T: Into<GridSection<N>>,
|
||||
|
|
@ -851,6 +860,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> From<[T; N]> for GridSection<N>
|
||||
where
|
||||
T: MakeWidget,
|
||||
{
|
||||
fn from(values: [T; N]) -> Self {
|
||||
let mut widgets = values.into_iter();
|
||||
Self(array::from_fn(|_| {
|
||||
widgets.next().assert("length checked").make_widget()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Deref for GridSection<N> {
|
||||
type Target = [WidgetInstance; N];
|
||||
|
||||
|
|
|
|||
|
|
@ -1099,7 +1099,7 @@ where
|
|||
.translate_by(padding),
|
||||
);
|
||||
}
|
||||
} else if window_focused {
|
||||
} else if window_focused && context.enabled() {
|
||||
let (location, _) =
|
||||
Self::point_from_cursor(cache.measured, cache.cursor, cache.bytes);
|
||||
if cursor_state.visible {
|
||||
|
|
|
|||
|
|
@ -637,6 +637,7 @@ where
|
|||
let root_mode = self.constrain_window_resizing(resizable, &mut window, graphics);
|
||||
|
||||
let graphics = self.contents.new_frame(graphics);
|
||||
let mut current_font_family = None;
|
||||
let mut context = GraphicsContext {
|
||||
widget: WidgetContext::new(
|
||||
self.root.clone(),
|
||||
|
|
@ -646,7 +647,7 @@ where
|
|||
self.theme_mode.get(),
|
||||
&mut self.cursor,
|
||||
),
|
||||
gfx: Exclusive::Owned(Graphics::new(graphics)),
|
||||
gfx: Exclusive::Owned(Graphics::new(graphics, &mut current_font_family)),
|
||||
};
|
||||
self.theme_mode.redraw_when_changed(&context);
|
||||
let mut layout_context = LayoutContext::new(&mut context);
|
||||
|
|
|
|||
Loading…
Reference in a new issue