mirror of
https://github.com/danbulant/cushy
synced 2026-06-17 21:41:11 +00:00
Widget docs + refactoring
- MakeWidgetWithId::make_with_id -> MakeWidgetWithTag::make_With_tag - ManagedWidget -> MountedWidget - *_refresh -> *_redraw, standardized on terminology - get_tracked -> get_tracking_redraw
This commit is contained in:
parent
01e04a4eb9
commit
02d6b343f1
25 changed files with 376 additions and 199 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
|
@ -1181,13 +1181,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lyon_tessellation"
|
||||
version = "1.0.12"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f5bcf02928361d18e6edb8ad3bc5b93cba8aa57e2508deb072c2d2ade8bbd0d"
|
||||
checksum = "8c7c67b5bc8123b352b2e7e742b47d1f236a13fe77619433be9568fbd888e9c0"
|
||||
dependencies = [
|
||||
"float_next_after",
|
||||
"lyon_path",
|
||||
"thiserror",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1271,9 +1271,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.0"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375"
|
||||
checksum = "39a69c7c189ae418f83003da62820aca28d15a07725ce51fb924999335d622ff"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -2064,7 +2064,7 @@ dependencies = [
|
|||
"cursor-icon",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2 0.9.0",
|
||||
"memmap2 0.9.2",
|
||||
"rustix",
|
||||
"thiserror",
|
||||
"wayland-backend",
|
||||
|
|
@ -2164,18 +2164,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -2982,7 +2982,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2 0.9.0",
|
||||
"memmap2 0.9.2",
|
||||
"ndk",
|
||||
"ndk-sys",
|
||||
"objc2",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//! traits or using the [`Custom`] widget with callbacks.
|
||||
|
||||
use gooey::value::Dynamic;
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithId, Widget, WidgetInstance, WidgetTag, HANDLED};
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance, WidgetTag, HANDLED};
|
||||
use gooey::widgets::Custom;
|
||||
use gooey::Run;
|
||||
use kludgine::figures::units::{Lp, UPx};
|
||||
|
|
@ -29,7 +29,7 @@ fn main() -> gooey::Result {
|
|||
///
|
||||
/// This approach was added to make it easy to create one-off widgets in a
|
||||
/// hierarchy to handle events or other purpose-built functions.
|
||||
fn callback_widget() -> impl MakeWidgetWithId {
|
||||
fn callback_widget() -> impl MakeWidgetWithTag {
|
||||
// This implementation and the impl `Widget` implementation both use the
|
||||
// same Dynamic value setup.
|
||||
let toggle = Toggle::default();
|
||||
|
|
@ -44,7 +44,7 @@ fn callback_widget() -> impl MakeWidgetWithId {
|
|||
.height(Lp::inches(1))
|
||||
}
|
||||
|
||||
/// A second approach is to implement [`MakeWidgetWithId`] for a type. This
|
||||
/// A second approach is to implement [`MakeWidgetWithTag`] for a type. This
|
||||
/// allows any type to be used when composing your UI that know how to create a
|
||||
/// widget.
|
||||
///
|
||||
|
|
@ -52,7 +52,7 @@ fn callback_widget() -> impl MakeWidgetWithId {
|
|||
/// widgets) in a reusable fashion.
|
||||
///
|
||||
/// [`MakeWidget`] is implemented automatically for all types that implement
|
||||
/// [`MakeWidgetWithId`]. The difference between the traits is purely whether
|
||||
/// [`MakeWidgetWithTag`]. The difference between the traits is purely whether
|
||||
/// allowing a caller instantiating your custom widget to provide an id for the
|
||||
/// widget. These IDs are used when configuring custom tab orders, so if your
|
||||
/// widget or any of its children aren't focusable, implementing [`MakeWidget`]
|
||||
|
|
@ -60,10 +60,10 @@ fn callback_widget() -> impl MakeWidgetWithId {
|
|||
#[derive(Default)]
|
||||
struct ToggleMakeWidget(Toggle);
|
||||
|
||||
impl MakeWidgetWithId for ToggleMakeWidget {
|
||||
fn make_with_id(self, id: WidgetTag) -> WidgetInstance {
|
||||
impl MakeWidgetWithTag for ToggleMakeWidget {
|
||||
fn make_with_tag(self, id: WidgetTag) -> WidgetInstance {
|
||||
// In a real code base, the contents of callback_widget() would go here
|
||||
callback_widget().make_with_id(id)
|
||||
callback_widget().make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ impl MakeWidgetWithId for ToggleMakeWidget {
|
|||
///
|
||||
/// This is the lowest-level way to implement a Widget, but it also provides the
|
||||
/// most power and flexibility.
|
||||
fn impl_widget() -> impl MakeWidgetWithId {
|
||||
fn impl_widget() -> impl MakeWidgetWithTag {
|
||||
Toggle::default()
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ impl Default for Toggle {
|
|||
|
||||
impl Widget for Toggle {
|
||||
fn redraw(&mut self, context: &mut gooey::context::GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
context.fill(self.color.get_tracking_refresh(context));
|
||||
context.fill(self.color.get_tracking_redraw(context));
|
||||
}
|
||||
|
||||
fn layout(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::process::exit;
|
||||
|
||||
use gooey::value::{Dynamic, MapEach};
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithId, WidgetTag};
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithTag, WidgetTag};
|
||||
use gooey::widgets::grid::{Grid, GridDimension, GridWidgets};
|
||||
use gooey::widgets::input::{InputValue, MaskedString};
|
||||
use gooey::widgets::Expand;
|
||||
|
|
@ -24,7 +24,7 @@ fn main() -> gooey::Result {
|
|||
|
||||
let username_row = (
|
||||
"Username",
|
||||
username.clone().into_input().make_with_id(username_tag),
|
||||
username.clone().into_input().make_with_tag(username_tag),
|
||||
);
|
||||
|
||||
let password_row = (
|
||||
|
|
@ -38,7 +38,7 @@ fn main() -> gooey::Result {
|
|||
eprintln!("Login cancelled");
|
||||
exit(0)
|
||||
})
|
||||
.make_with_id(cancel_tag)
|
||||
.make_with_tag(cancel_tag)
|
||||
.into_escape()
|
||||
.with_next_focus(username_id)
|
||||
.and(Expand::empty())
|
||||
|
|
@ -49,7 +49,7 @@ fn main() -> gooey::Result {
|
|||
println!("Welcome, {}", username.get());
|
||||
exit(0);
|
||||
})
|
||||
.make_with_id(login_tag)
|
||||
.make_with_tag(login_tag)
|
||||
.with_enabled(valid)
|
||||
.into_default()
|
||||
.with_next_focus(cancel_id),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::panic::UnwindSafe;
|
||||
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithId, WidgetTag};
|
||||
use gooey::widget::{MakeWidget, MakeWidgetWithTag, WidgetTag};
|
||||
use gooey::widgets::container::ContainerShadow;
|
||||
use gooey::widgets::layers::{OverlayBuilder, OverlayLayer};
|
||||
use gooey::Run;
|
||||
|
|
@ -48,7 +48,7 @@ fn test_widget(overlay: &OverlayLayer, is_root: bool) -> impl MakeWidget {
|
|||
);
|
||||
}
|
||||
|
||||
buttons.pad().make_with_id(my_tag)
|
||||
buttons.pad().make_with_tag(my_tag)
|
||||
}
|
||||
|
||||
fn show_overlay_button(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use crate::styles::{ComponentDefinition, Styles, Theme, ThemePair};
|
|||
use crate::utils::IgnorePoison;
|
||||
use crate::value::{IntoValue, Value};
|
||||
use crate::widget::{
|
||||
EventHandling, ManagedWidget, RootBehavior, WidgetId, WidgetInstance, WidgetRef,
|
||||
EventHandling, MountedWidget, RootBehavior, WidgetId, WidgetInstance, WidgetRef,
|
||||
};
|
||||
use crate::window::{CursorState, RunningWindow, ThemeMode};
|
||||
use crate::ConstraintLimit;
|
||||
|
|
@ -350,7 +350,7 @@ impl<'context, 'window> EventContext<'context, 'window> {
|
|||
}
|
||||
}
|
||||
|
||||
fn next_focus_after(&mut self, mut focus: ManagedWidget, advance: bool) -> Option<WidgetId> {
|
||||
fn next_focus_after(&mut self, mut focus: MountedWidget, advance: bool) -> Option<WidgetId> {
|
||||
// First, look within the current focus for any focusable children.
|
||||
let stop_at = focus.id();
|
||||
if let Some(focus) = self.next_focus_within(&focus, None, stop_at, advance) {
|
||||
|
|
@ -375,7 +375,7 @@ impl<'context, 'window> EventContext<'context, 'window> {
|
|||
|
||||
fn next_focus_sibling(
|
||||
&mut self,
|
||||
focus: &ManagedWidget,
|
||||
focus: &MountedWidget,
|
||||
stop_at: WidgetId,
|
||||
advance: bool,
|
||||
) -> Option<WidgetId> {
|
||||
|
|
@ -387,7 +387,7 @@ impl<'context, 'window> EventContext<'context, 'window> {
|
|||
/// that returns true from `accept_focus`.
|
||||
fn next_focus_within(
|
||||
&mut self,
|
||||
focus: &ManagedWidget,
|
||||
focus: &MountedWidget,
|
||||
start_at: Option<WidgetId>,
|
||||
stop_at: WidgetId,
|
||||
advance: bool,
|
||||
|
|
@ -782,7 +782,7 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> LayoutContext<'context, 'window, 'cl
|
|||
/// Sets the layout for `child` to `layout`.
|
||||
///
|
||||
/// `layout` is relative to the current widget's controls.
|
||||
pub fn set_child_layout(&mut self, child: &ManagedWidget, layout: Rect<Px>) {
|
||||
pub fn set_child_layout(&mut self, child: &MountedWidget, layout: Rect<Px>) {
|
||||
// TODO verify that `child` belongs to the current node.
|
||||
if self.persist_layout {
|
||||
child.set_layout(layout);
|
||||
|
|
@ -824,7 +824,7 @@ pub trait AsEventContext<'window> {
|
|||
/// Pushes a new child widget into the widget hierarchy beneathq the
|
||||
/// context's widget.
|
||||
#[must_use]
|
||||
fn push_child(&mut self, child: WidgetInstance) -> ManagedWidget {
|
||||
fn push_child(&mut self, child: WidgetInstance) -> MountedWidget {
|
||||
let mut context = self.as_event_context();
|
||||
let pushed_widget = context
|
||||
.current_node
|
||||
|
|
@ -838,7 +838,7 @@ pub trait AsEventContext<'window> {
|
|||
}
|
||||
|
||||
/// Removes a widget from the hierarchy.
|
||||
fn remove_child(&mut self, child: &ManagedWidget) {
|
||||
fn remove_child(&mut self, child: &MountedWidget) {
|
||||
let mut context = self.as_event_context();
|
||||
child
|
||||
.lock()
|
||||
|
|
@ -868,7 +868,7 @@ impl<'window> AsEventContext<'window> for GraphicsContext<'_, 'window, '_, '_, '
|
|||
/// This type provides access to the widget hierarchy from the perspective of a
|
||||
/// specific widget.
|
||||
pub struct WidgetContext<'context, 'window> {
|
||||
current_node: ManagedWidget,
|
||||
current_node: MountedWidget,
|
||||
redraw_status: &'context InvalidationStatus,
|
||||
window: &'context mut RunningWindow<'window>,
|
||||
theme: Cow<'context, ThemePair>,
|
||||
|
|
@ -880,7 +880,7 @@ pub struct WidgetContext<'context, 'window> {
|
|||
|
||||
impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||
pub(crate) fn new(
|
||||
current_node: ManagedWidget,
|
||||
current_node: MountedWidget,
|
||||
redraw_status: &'context InvalidationStatus,
|
||||
theme: &'context ThemePair,
|
||||
window: &'context mut RunningWindow<'window>,
|
||||
|
|
@ -942,12 +942,12 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
widget.manage(self).map(|current_node| {
|
||||
let (effective_styles, theme, theme_mode) = current_node.overidden_theme();
|
||||
let theme = if let Some(theme) = theme {
|
||||
Cow::Owned(theme.get_tracked(self))
|
||||
Cow::Owned(theme.get_tracking_redraw(self))
|
||||
} else {
|
||||
Cow::Borrowed(self.theme.as_ref())
|
||||
};
|
||||
let theme_mode = if let Some(mode) = theme_mode {
|
||||
mode.get_tracked(self)
|
||||
mode.get_tracking_redraw(self)
|
||||
} else {
|
||||
self.cache.theme_mode
|
||||
};
|
||||
|
|
@ -981,7 +981,7 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
self.cache.enabled
|
||||
}
|
||||
|
||||
pub(crate) fn parent(&self) -> Option<ManagedWidget> {
|
||||
pub(crate) fn parent(&self) -> Option<MountedWidget> {
|
||||
self.current_node.parent()
|
||||
}
|
||||
|
||||
|
|
@ -1096,7 +1096,7 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
#[must_use]
|
||||
pub fn focused(&self, check_window: bool) -> bool {
|
||||
self.pending_state.focus == Some(self.current_node.id())
|
||||
&& (!check_window || self.window.focused().get_tracking_refresh(self))
|
||||
&& (!check_window || self.window.focused().get_tracking_redraw(self))
|
||||
}
|
||||
|
||||
/// Returns true if this widget is the target to activate when the user
|
||||
|
|
@ -1123,7 +1123,7 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
|||
|
||||
/// Returns the widget this context is for.
|
||||
#[must_use]
|
||||
pub const fn widget(&self) -> &ManagedWidget {
|
||||
pub const fn widget(&self) -> &MountedWidget {
|
||||
&self.current_node
|
||||
}
|
||||
|
||||
|
|
@ -1315,18 +1315,18 @@ impl InvalidationStatus {
|
|||
}
|
||||
}
|
||||
|
||||
/// A type chat can convert to a [`ManagedWidget`] through a [`WidgetContext`].
|
||||
/// A type chat can convert to a [`MountedWidget`] through a [`WidgetContext`].
|
||||
pub trait ManageWidget {
|
||||
/// The managed type, which can be `Option<ManagedWidget>` or
|
||||
/// `ManagedWidget`.
|
||||
type Managed: MapManagedWidget<ManagedWidget>;
|
||||
/// The managed type, which can be `Option<MountedWidget>` or
|
||||
/// `MountedWidget`.
|
||||
type Managed: MapManagedWidget<MountedWidget>;
|
||||
|
||||
/// Resolve `self` into a [`ManagedWidget`].
|
||||
/// Resolve `self` into a [`MountedWidget`].
|
||||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed;
|
||||
}
|
||||
|
||||
impl ManageWidget for WidgetId {
|
||||
type Managed = Option<ManagedWidget>;
|
||||
type Managed = Option<MountedWidget>;
|
||||
|
||||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed {
|
||||
context.current_node.tree.widget(*self)
|
||||
|
|
@ -1334,7 +1334,7 @@ impl ManageWidget for WidgetId {
|
|||
}
|
||||
|
||||
impl ManageWidget for WidgetInstance {
|
||||
type Managed = Option<ManagedWidget>;
|
||||
type Managed = Option<MountedWidget>;
|
||||
|
||||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed {
|
||||
context.current_node.tree.widget(self.id())
|
||||
|
|
@ -1342,7 +1342,7 @@ impl ManageWidget for WidgetInstance {
|
|||
}
|
||||
|
||||
impl ManageWidget for WidgetRef {
|
||||
type Managed = Option<ManagedWidget>;
|
||||
type Managed = Option<MountedWidget>;
|
||||
|
||||
fn manage(&self, context: &WidgetContext<'_, '_>) -> Self::Managed {
|
||||
match self {
|
||||
|
|
@ -1352,7 +1352,7 @@ impl ManageWidget for WidgetRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl ManageWidget for ManagedWidget {
|
||||
impl ManageWidget for MountedWidget {
|
||||
type Managed = Self;
|
||||
|
||||
fn manage(&self, _context: &WidgetContext<'_, '_>) -> Self::Managed {
|
||||
|
|
@ -1360,27 +1360,27 @@ impl ManageWidget for ManagedWidget {
|
|||
}
|
||||
}
|
||||
|
||||
/// A type that can produce another type when provided a [`ManagedWidget`].
|
||||
/// A type that can produce another type when provided a [`MountedWidget`].
|
||||
pub trait MapManagedWidget<T> {
|
||||
/// The result of the mapping operation.
|
||||
type Result;
|
||||
|
||||
/// Call `map` with a [`ManagedWidget`].
|
||||
fn map(self, map: impl FnOnce(ManagedWidget) -> T) -> Self::Result;
|
||||
/// Call `map` with a [`MountedWidget`].
|
||||
fn map(self, map: impl FnOnce(MountedWidget) -> T) -> Self::Result;
|
||||
}
|
||||
|
||||
impl<T> MapManagedWidget<T> for Option<ManagedWidget> {
|
||||
impl<T> MapManagedWidget<T> for Option<MountedWidget> {
|
||||
type Result = Option<T>;
|
||||
|
||||
fn map(self, map: impl FnOnce(ManagedWidget) -> T) -> Self::Result {
|
||||
fn map(self, map: impl FnOnce(MountedWidget) -> T) -> Self::Result {
|
||||
self.map(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MapManagedWidget<T> for ManagedWidget {
|
||||
impl<T> MapManagedWidget<T> for MountedWidget {
|
||||
type Result = T;
|
||||
|
||||
fn map(self, map: impl FnOnce(ManagedWidget) -> T) -> Self::Result {
|
||||
fn map(self, map: impl FnOnce(MountedWidget) -> T) -> Self::Result {
|
||||
map(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
src/lib.rs
18
src/lib.rs
|
|
@ -125,24 +125,6 @@ pub trait Run: Sized {
|
|||
fn run(self) -> crate::Result;
|
||||
}
|
||||
|
||||
/// Creates a [`Children`](crate::widget::Children) instance with the given list
|
||||
/// of widgets.
|
||||
#[macro_export]
|
||||
#[deprecated = "use MakeWidget.and()/Children.and() to chain widgets without a macro"]
|
||||
macro_rules! children {
|
||||
() => {
|
||||
$crate::widget::Children::new()
|
||||
};
|
||||
($($widget:expr),+) => {{
|
||||
let mut widgets = $crate::widget::Children::with_capacity($crate::count!($($widget),+ ;));
|
||||
$(widgets.push($widget);)+
|
||||
widgets
|
||||
}};
|
||||
($($widget:expr),+ ,) => {{
|
||||
$crate::children!($($widget),+)
|
||||
}};
|
||||
}
|
||||
|
||||
/// Counts the number of expressions passed to it.
|
||||
///
|
||||
/// This is used inside of Gooey macros to preallocate collections.
|
||||
|
|
|
|||
52
src/tree.rs
52
src/tree.rs
|
|
@ -10,7 +10,7 @@ use crate::context::sealed::WindowHandle;
|
|||
use crate::styles::{Styles, ThemePair, VisualOrder};
|
||||
use crate::utils::IgnorePoison;
|
||||
use crate::value::Value;
|
||||
use crate::widget::{ManagedWidget, WidgetId, WidgetInstance};
|
||||
use crate::widget::{MountedWidget, WidgetId, WidgetInstance};
|
||||
use crate::window::ThemeMode;
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ impl Tree {
|
|||
pub fn push_boxed(
|
||||
&self,
|
||||
widget: WidgetInstance,
|
||||
parent: Option<&ManagedWidget>,
|
||||
) -> ManagedWidget {
|
||||
parent: Option<&MountedWidget>,
|
||||
) -> MountedWidget {
|
||||
let mut data = self.data.lock().ignore_poison();
|
||||
let id = widget.id();
|
||||
let (effective_styles, parent_id) = if let Some(parent) = parent {
|
||||
|
|
@ -60,14 +60,14 @@ impl Tree {
|
|||
if let Some(next_focus) = widget.next_focus() {
|
||||
data.previous_focuses.insert(next_focus, id);
|
||||
}
|
||||
ManagedWidget {
|
||||
MountedWidget {
|
||||
node_id,
|
||||
widget,
|
||||
tree: self.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_child(&self, child: &ManagedWidget, parent: &ManagedWidget) {
|
||||
pub fn remove_child(&self, child: &MountedWidget, parent: &MountedWidget) {
|
||||
let mut data = self.data.lock().ignore_poison();
|
||||
data.remove_child(child.node_id, parent.node_id);
|
||||
|
||||
|
|
@ -163,11 +163,11 @@ impl Tree {
|
|||
&self,
|
||||
parent: LotId,
|
||||
order: VisualOrder,
|
||||
) -> Vec<ManagedWidget> {
|
||||
) -> Vec<MountedWidget> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
let node = &data.nodes[parent];
|
||||
let mut unordered = node.children.clone();
|
||||
let mut ordered = Vec::<ManagedWidget>::with_capacity(unordered.len());
|
||||
let mut ordered = Vec::<MountedWidget>::with_capacity(unordered.len());
|
||||
loop {
|
||||
// Identify the next "row" of widgets by finding the top of a widget that is the closest to the origin of
|
||||
let mut min_vertical = order.vertical.max_px();
|
||||
|
|
@ -225,13 +225,13 @@ impl Tree {
|
|||
data.nodes[id].effective_styles.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn hover(&self, new_hover: Option<&ManagedWidget>) -> HoverResults {
|
||||
pub(crate) fn hover(&self, new_hover: Option<&MountedWidget>) -> HoverResults {
|
||||
let mut data = self.data.lock().ignore_poison();
|
||||
let hovered = new_hover
|
||||
.map(|new_hover| data.widget_hierarchy(new_hover.node_id, self))
|
||||
.unwrap_or_default();
|
||||
let unhovered =
|
||||
match data.update_tracked_widget(new_hover.map(ManagedWidget::id), self, |data| {
|
||||
match data.update_tracked_widget(new_hover.map(MountedWidget::id), self, |data| {
|
||||
&mut data.hover
|
||||
}) {
|
||||
Ok(Some(old_hover)) => {
|
||||
|
|
@ -250,12 +250,12 @@ impl Tree {
|
|||
HoverResults { unhovered, hovered }
|
||||
}
|
||||
|
||||
pub fn focus(&self, new_focus: Option<WidgetId>) -> Result<Option<ManagedWidget>, ()> {
|
||||
pub fn focus(&self, new_focus: Option<WidgetId>) -> Result<Option<MountedWidget>, ()> {
|
||||
let mut data = self.data.lock().ignore_poison();
|
||||
data.update_tracked_widget(new_focus, self, |data| &mut data.focus)
|
||||
}
|
||||
|
||||
pub fn previous_focus(&self, focus: WidgetId) -> Option<ManagedWidget> {
|
||||
pub fn previous_focus(&self, focus: WidgetId) -> Option<MountedWidget> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
let previous = *data.previous_focuses.get(&focus)?;
|
||||
data.widget_from_id(previous, self)
|
||||
|
|
@ -263,20 +263,20 @@ impl Tree {
|
|||
|
||||
pub fn activate(
|
||||
&self,
|
||||
new_active: Option<&ManagedWidget>,
|
||||
) -> Result<Option<ManagedWidget>, ()> {
|
||||
new_active: Option<&MountedWidget>,
|
||||
) -> Result<Option<MountedWidget>, ()> {
|
||||
let mut data = self.data.lock().ignore_poison();
|
||||
data.update_tracked_widget(new_active.map(ManagedWidget::id), self, |data| {
|
||||
data.update_tracked_widget(new_active.map(MountedWidget::id), self, |data| {
|
||||
&mut data.active
|
||||
})
|
||||
}
|
||||
|
||||
pub fn widget(&self, id: WidgetId) -> Option<ManagedWidget> {
|
||||
pub fn widget(&self, id: WidgetId) -> Option<MountedWidget> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
data.widget_from_id(id, self)
|
||||
}
|
||||
|
||||
pub(crate) fn widget_from_node(&self, id: LotId) -> Option<ManagedWidget> {
|
||||
pub(crate) fn widget_from_node(&self, id: LotId) -> Option<MountedWidget> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
data.widget_from_node(id, self)
|
||||
}
|
||||
|
|
@ -333,7 +333,7 @@ impl Tree {
|
|||
self.data.lock().ignore_poison().focus
|
||||
}
|
||||
|
||||
pub(crate) fn widgets_under_point(&self, point: Point<Px>) -> Vec<ManagedWidget> {
|
||||
pub(crate) fn widgets_under_point(&self, point: Point<Px>) -> Vec<MountedWidget> {
|
||||
let data = self.data.lock().ignore_poison();
|
||||
data.render_info.widgets_under_point(point, &data, self)
|
||||
}
|
||||
|
|
@ -398,8 +398,8 @@ impl Tree {
|
|||
}
|
||||
|
||||
pub(crate) struct HoverResults {
|
||||
pub unhovered: Vec<ManagedWidget>,
|
||||
pub hovered: Vec<ManagedWidget>,
|
||||
pub unhovered: Vec<MountedWidget>,
|
||||
pub hovered: Vec<MountedWidget>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -416,17 +416,17 @@ struct TreeData {
|
|||
}
|
||||
|
||||
impl TreeData {
|
||||
fn widget_from_id(&self, id: WidgetId, tree: &Tree) -> Option<ManagedWidget> {
|
||||
fn widget_from_id(&self, id: WidgetId, tree: &Tree) -> Option<MountedWidget> {
|
||||
let node_id = *self.nodes_by_id.get(&id)?;
|
||||
Some(ManagedWidget {
|
||||
Some(MountedWidget {
|
||||
node_id,
|
||||
widget: self.nodes[node_id].widget.clone(),
|
||||
tree: tree.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn widget_from_node(&self, node_id: LotId, tree: &Tree) -> Option<ManagedWidget> {
|
||||
Some(ManagedWidget {
|
||||
fn widget_from_node(&self, node_id: LotId, tree: &Tree) -> Option<MountedWidget> {
|
||||
Some(MountedWidget {
|
||||
node_id,
|
||||
widget: self.nodes.get(node_id)?.widget.clone(),
|
||||
tree: tree.clone(),
|
||||
|
|
@ -489,7 +489,7 @@ impl TreeData {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn widget_hierarchy(&self, mut widget: LotId, tree: &Tree) -> Vec<ManagedWidget> {
|
||||
pub(crate) fn widget_hierarchy(&self, mut widget: LotId, tree: &Tree) -> Vec<MountedWidget> {
|
||||
let mut hierarchy = Vec::new();
|
||||
while let Some(managed) = self.widget_from_node(widget, tree) {
|
||||
hierarchy.push(managed);
|
||||
|
|
@ -509,7 +509,7 @@ impl TreeData {
|
|||
new_widget: Option<WidgetId>,
|
||||
tree: &Tree,
|
||||
property: impl FnOnce(&mut Self) -> &mut Option<LotId>,
|
||||
) -> Result<Option<ManagedWidget>, ()> {
|
||||
) -> Result<Option<MountedWidget>, ()> {
|
||||
let new_widget = new_widget.and_then(|w| self.widget_from_id(w, tree));
|
||||
match (
|
||||
mem::replace(property(self), new_widget.as_ref().map(|w| w.node_id)),
|
||||
|
|
@ -555,7 +555,7 @@ impl RenderInfo {
|
|||
point: Point<Px>,
|
||||
tree_data: &TreeData,
|
||||
tree: &Tree,
|
||||
) -> Vec<ManagedWidget> {
|
||||
) -> Vec<MountedWidget> {
|
||||
// We pessimistically allocate a vector as if all widgets match, up to a
|
||||
// reasonable limit. This should ensure minimal allocations in all but
|
||||
// extreme circumstances where widgets are nested with a significant
|
||||
|
|
|
|||
20
src/value.rs
20
src/value.rs
|
|
@ -22,7 +22,7 @@ use crate::animation::{AnimationHandle, DynamicTransition, IntoAnimate, LinearIn
|
|||
use crate::context::sealed::WindowHandle;
|
||||
use crate::context::{self, WidgetContext};
|
||||
use crate::utils::{run_in_bg, IgnorePoison, UnwindsafeCondvar, WithClone};
|
||||
use crate::widget::{Children, MakeWidget, MakeWidgetWithId, WidgetId, WidgetInstance};
|
||||
use crate::widget::{Children, MakeWidget, MakeWidgetWithTag, WidgetId, WidgetInstance};
|
||||
use crate::widgets::{Radio, Select, Space, Switcher};
|
||||
|
||||
/// An instance of a value that provides APIs to observe and react to its
|
||||
|
|
@ -377,7 +377,7 @@ impl<T> Dynamic<T> {
|
|||
/// This function panics if this value is already locked by the current
|
||||
/// thread.
|
||||
#[must_use]
|
||||
pub fn get_tracking_refresh(&self, context: &WidgetContext<'_, '_>) -> T
|
||||
pub fn get_tracking_redraw(&self, context: &WidgetContext<'_, '_>) -> T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
|
|
@ -638,20 +638,20 @@ impl Dynamic<WidgetInstance> {
|
|||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Dynamic<WidgetInstance> {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
self.into_switcher().make_with_id(id)
|
||||
impl MakeWidgetWithTag for Dynamic<WidgetInstance> {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
self.into_switcher().make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Dynamic<Option<WidgetInstance>> {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
impl MakeWidgetWithTag for Dynamic<Option<WidgetInstance>> {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
self.map_each(|widget| {
|
||||
widget
|
||||
.as_ref()
|
||||
.map_or_else(|| Space::clear().make_widget(), Clone::clone)
|
||||
})
|
||||
.make_with_id(id)
|
||||
.make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1260,7 +1260,7 @@ impl<T> DynamicReader<T> {
|
|||
/// This function panics if this value is already locked by the current
|
||||
/// thread.
|
||||
#[must_use]
|
||||
pub fn get_tracking_refresh(&mut self, context: &WidgetContext<'_, '_>) -> T
|
||||
pub fn get_tracking_redraw(&mut self, context: &WidgetContext<'_, '_>) -> T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
|
|
@ -1649,7 +1649,7 @@ impl<T> Value<T> {
|
|||
///
|
||||
/// If `self` is a dynamic, `context` will be refreshed when the value is
|
||||
/// updated.
|
||||
pub fn get_tracked(&self, context: &WidgetContext<'_, '_>) -> T
|
||||
pub fn get_tracking_redraw(&self, context: &WidgetContext<'_, '_>) -> T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
|
|
|
|||
267
src/widget.rs
267
src/widget.rs
|
|
@ -52,25 +52,214 @@ use crate::{ConstraintLimit, Run};
|
|||
/// This type can go by many names in other UI frameworks: View, Component,
|
||||
/// Control.
|
||||
///
|
||||
/// # Widgets are hierarchical
|
||||
///
|
||||
/// Gooey's widgets are organized in a hierarchical structure: widgets can
|
||||
/// contain other widgets. A window in Gooey contains a single root widget,
|
||||
/// which may contain one or more additional widgets.
|
||||
///
|
||||
/// # How Widgets are created
|
||||
///
|
||||
/// Gooey offers several approaches to creating widgets. The primary trait that
|
||||
/// is used to instantiate a widget is [`MakeWidget`]. This trait is
|
||||
/// automatically implemented for all types that implement [`Widget`].
|
||||
///
|
||||
/// [`MakeWidget::make_widget`] is responsible for returning a
|
||||
/// [`WidgetInstance`]. This is a wrapper for a type that implements [`Widget`]
|
||||
/// that can be used without knowing the original type of the [`Widget`].
|
||||
///
|
||||
/// While all [`MakeWidget`] is automatically implemented for all [`Widget`]
|
||||
/// types, it can also be implemented by types that do not implement [`Widget`].
|
||||
/// This is a useful strategy when designing reusable widgets that are able to
|
||||
/// be completely represented by composing existing widgets. The
|
||||
/// [`ProgressBar`](crate::widgets::ProgressBar) type uses this strategy, as it
|
||||
/// uses either a [`Spinner`](crate::widgets::progress::Spinner) or a
|
||||
/// [`Slider`](crate::widgets::Slider) to show its progress.
|
||||
///
|
||||
/// One last convenience trait is provided to help create widgets that contain
|
||||
/// exactly one child: [`WrapperWidget`]. [`WrapperWidget`] exposes most of the
|
||||
/// same functions, but provides purpose-built functions for tweaking child's
|
||||
/// layout and rendering behavior to minimize the amount of redundant code
|
||||
/// between these types of widgets.
|
||||
///
|
||||
/// # Identifying Widgets
|
||||
///
|
||||
/// Once a widget has been instantiated as a [`WidgetInstance`], it will be
|
||||
/// assigned a unique [`WidgetId`]. Sometimes, it may be helpful to pre-create a
|
||||
/// [`WidgetId`] before the widget has been created. For these situations,
|
||||
/// [`WidgetTag`] allows creating a tag that can be passed to
|
||||
/// [`MakeWidgetWithTag::make_with_tag`] to set the returned
|
||||
/// [`WidgetInstance`]'s id.
|
||||
///
|
||||
/// # How to "talk" to another widget
|
||||
///
|
||||
/// Once a widget has been wrapped inside of a [`WidgetInstance`], it is no
|
||||
/// longer possible to invoke [`Widget`]/s functions directly. Instead, a
|
||||
/// context must be created for that widget. In each of the [`Widget`]
|
||||
/// functions, a context is provided that represents the current widget. Each
|
||||
/// context type has a `for_other()` function that accepts any widget type: a
|
||||
/// [`WidgetId`], a [`WidgetInstance`], a [`MountedWidget`], or a [`WidgetRef`].
|
||||
/// The returned context will represent the associate widget, allowing access to
|
||||
/// the exposed APIs through the context.
|
||||
///
|
||||
/// While [`WidgetInstance::lock`] can be used to gain access to the underlying
|
||||
/// [`Widget`] type, this behavior should only be reserved for limited
|
||||
/// situations. It should be preferred to pass data between widgets using
|
||||
/// [`Dynamic`]s or style components if possible. This ensures that your code
|
||||
/// can work with as many other widgets as possible, instead of restricting
|
||||
/// features to a specific set of types.
|
||||
///
|
||||
/// # How layout and rendering works
|
||||
///
|
||||
/// TODO write layout + rendering docs
|
||||
/// When a window is rendered, the root widget has its
|
||||
/// [`layout()`](Self::layout) function called with both constraints specifying
|
||||
/// [`ConstraintLimit::SizeToFit`] with the window's inner size. The root widget
|
||||
/// measures its content to try to fit within the specified constraints, and
|
||||
/// returns its calculated size. If a widget has children, it can invoke
|
||||
/// [`LayoutContext::layout()`] on a context for each of its children to
|
||||
/// determine their required sizes.
|
||||
///
|
||||
/// # Hit Testing
|
||||
/// Next, the window sets the root's layout. When a widget contains another
|
||||
/// widget, it must call [`LayoutContext::set_child_layout`] for the child to be
|
||||
/// able to be rendered. This tells Gooey the location to draw the widget. While
|
||||
/// it is possible to provide any rectangle, Gooey clips all widgets and their
|
||||
/// children so that they cannot draw outside of their assigned bounds.
|
||||
///
|
||||
/// TODO write hit testing docs
|
||||
/// Once the layout has been determined, the window will invoke the root
|
||||
/// widget's [`redraw()`](Self::redraw) function. If a widget contains one or
|
||||
/// more children, it needs to invoke [`GraphicsContext::redraw()`] on a context
|
||||
/// for each of its children during its own render function. This allows full
|
||||
/// control over the order of drawing calls, allowing widgets to draw behind,
|
||||
/// in-between, or in front of their children.
|
||||
///
|
||||
/// The last responsibility the window has each frame is size adjustment. The
|
||||
/// window will potentially adjust its size automatically based on the root
|
||||
/// widget's [`root_behavior()`](Self::root_behavior).
|
||||
///
|
||||
/// # Controlling Invalidation and Redrawing
|
||||
///
|
||||
/// Gooey only redraws window contents when requested by the operating system or
|
||||
/// a tracked [`Dynamic`] is updated. Similarly, Gooey caches the known layout
|
||||
/// sizes and locations for widgets unless they are *invalidated*. Invalidation
|
||||
/// is done automatically when the window size changes or a tracked [`Dynamic`]
|
||||
/// is updated.
|
||||
///
|
||||
/// These systems require Gooey to track which [`Dynamic`] values a widget
|
||||
/// depends on for redrawing and invalidation. During a widget's redraw and
|
||||
/// layout functions, it needs to ensure that all depended upon [`Dynamic`]s are
|
||||
/// tracked using one of the various
|
||||
/// `*_tracking_redraw()`/`*_tracking_invalidate()` functions. For example,
|
||||
/// [`Dynamic::get_tracking_redraw()`] and
|
||||
/// [`Dynamic::get_tracking_invalidate()`].
|
||||
///
|
||||
/// # Hover State: Hit Testing
|
||||
///
|
||||
/// Before any cursor-related events are sent to a widget, the cursor's position
|
||||
/// is tested with [`Widget::hit_test`]. When a widget returns true for a
|
||||
/// position, it is eligible to receive events such as mouse buttons.
|
||||
///
|
||||
/// When a widget returns false, it will not receive any cursor related events
|
||||
/// with one exception: hover events. Hover events will fire for widgets whose
|
||||
/// children are currently being hovered, regardless of whether
|
||||
/// [`Widget::hit_test`] returned true.
|
||||
///
|
||||
/// The provided [`Widget::hit_test`] implementation returns false.
|
||||
///
|
||||
/// As the cursor moves across the window, the window will look at the render
|
||||
/// information to see what widgets are positioned under the cursor and the
|
||||
/// order in which they were drawn. Beginning at the topmost widget,
|
||||
/// [`Widget::hit_test`] is called on each widget.
|
||||
///
|
||||
/// The currently hovered widget state is tracked for events that target widgets
|
||||
/// beneath the current cursor.
|
||||
///
|
||||
/// # Mouse Button Events
|
||||
///
|
||||
/// TODO write mouse button docs
|
||||
/// When a window receives an event for a mouse button being pressed, it calls
|
||||
/// the hovered widget's [`mouse_down()`](Self::mouse_down) function. If the
|
||||
/// function returns [`HANDLED`]/[`ControlFlow::Break`], the widget becomes the
|
||||
/// *tracking* widget for that mouse button.
|
||||
///
|
||||
/// If the widget returns [`IGNORED`]/[`ControlFlow::Continue`], the window will
|
||||
/// call the parent's `mouse_down()` function. This repeats until the root
|
||||
/// widget is reached or a widget returns `HANDLED`.
|
||||
///
|
||||
/// Once a tracking widget is found, any cursor-related movements will cause
|
||||
/// [`Widget::mouse_drag()`] to be called. Upon the mouse button being released,
|
||||
/// the tracking widget's [`mouse_up()`](Self::mouse_up) function will be
|
||||
/// called.
|
||||
///
|
||||
/// # User Input Focus
|
||||
///
|
||||
/// TODO write focus docs
|
||||
/// A window can have a widget be *focused* for user input. For example, a text
|
||||
/// [`Input`](crate::widgets::Input) only responds to keyboard input once user
|
||||
/// input focus has been directed at the widget. This state is generally
|
||||
/// represented by drawing the theme's highlight color around the border of the
|
||||
/// widget. [`GraphicsContext::draw_focus_ring`] can be used to draw the
|
||||
/// standard focus ring for rectangular-shaped widgets.
|
||||
///
|
||||
/// The most direct way to give a widget focus is to call
|
||||
/// [`WidgetContext::focus`]. However, not all widgets can accept focus. If a
|
||||
/// widget returns true from its [`accept_focus()`](Self::accept_focus)
|
||||
/// function, focus will be given to it and its [`focus()`](Self::focus)
|
||||
/// function will be invoked.
|
||||
///
|
||||
/// If a widget returns false from its `accept_focus()` function, the window
|
||||
/// will perform these steps:
|
||||
///
|
||||
/// 1. If the widget has any children, sort its children visually and attempt to
|
||||
/// focus each one until a widget accepts focus. If any of these children
|
||||
/// have children, those children should also be checked.
|
||||
/// 2. The widget asks its parent to find the next focus after itself. The
|
||||
/// parent finds the current widget in that list and attempts to focus each
|
||||
/// widget after the current widget in the visual order.
|
||||
/// 3. This repeats until the root widget is reached, at which point focus is
|
||||
/// attempted using this algorithm until either a focused widget is found or
|
||||
/// the original widget is reached again. If no widget can be found in a full
|
||||
/// cycle of the widget tree, focus will be cleared.
|
||||
///
|
||||
/// When a window first opens, it call [`focus()`][WidgetContext::focus] on the
|
||||
/// root widget's context.
|
||||
///
|
||||
/// ## Losing Focus
|
||||
///
|
||||
/// A Widget can deny the ability for focus to be taken away from it by
|
||||
/// returning `false` from [`Widget::allow_blur()`]. In general, widgets should
|
||||
/// not do this. However, some user interfaces are designed to always keep focus
|
||||
/// on a single widget, and this feature enables that functionality.
|
||||
///
|
||||
/// When a widget currently has focused and loses it, its [`blur()`](Self::blur)
|
||||
/// function will be invoked.
|
||||
///
|
||||
/// # Styling
|
||||
///
|
||||
/// TODO write styling docs
|
||||
/// Gooey allows widgets to receive styling information through the widget
|
||||
/// hierarchy using [`Styles`]. Gooey calculates the effectives styles for each
|
||||
/// widget by inheriting all inheritable styles from its parent.
|
||||
///
|
||||
/// The [`Style`] widget allows assigining [`Styles`] to all of its children
|
||||
/// widget. It works by calling [`WidgetContext::attach_styles`], and Gooey
|
||||
/// takes care of the rest.
|
||||
///
|
||||
/// Styling in Gooey aims to be simple, easy-to-understand, and extensible.
|
||||
///
|
||||
/// # Color Themes
|
||||
///
|
||||
/// Gooey aims to make it easy for developers to customize the appearance of its
|
||||
/// applications. The way color themes work in Gooey begins with the
|
||||
/// [`ColorScheme`](crate::styles::ColorScheme). A color scheme is a set of
|
||||
/// [`ColorSource`](crate::styles::ColorSource) that are used to generate a
|
||||
/// variety of shades of colors for various roles color plays in a user
|
||||
/// interface. In a way, coloring Gooey apps is a bit like paint-by-number,
|
||||
/// where the number is the name of the color role.
|
||||
///
|
||||
/// A `ColorScheme` can be used to create a [`ThemePair`], which is theme
|
||||
/// definition that a theme for light and dark mode.
|
||||
///
|
||||
/// In [the repository][repo], the `theme` example is a good way to explore how
|
||||
/// the color system works in Gooey.
|
||||
///
|
||||
/// [repo]: https://github.com/khonsulabs/gooey
|
||||
pub trait Widget: Send + UnwindSafe + Debug + 'static {
|
||||
/// Redraw the contents of this widget.
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>);
|
||||
|
|
@ -1107,26 +1296,26 @@ pub trait MakeWidget: Sized {
|
|||
|
||||
/// A type that can create a [`WidgetInstance`] with a preallocated
|
||||
/// [`WidgetId`].
|
||||
pub trait MakeWidgetWithId: Sized {
|
||||
/// Returns a new [`WidgetInstance`] whose [`WidgetId`] is `id`.
|
||||
fn make_with_id(self, id: WidgetTag) -> WidgetInstance;
|
||||
pub trait MakeWidgetWithTag: Sized {
|
||||
/// Returns a new [`WidgetInstance`] whose [`WidgetId`] comes from `tag`.
|
||||
fn make_with_tag(self, tag: WidgetTag) -> WidgetInstance;
|
||||
}
|
||||
|
||||
impl<T> MakeWidgetWithId for T
|
||||
impl<T> MakeWidgetWithTag for T
|
||||
where
|
||||
T: Widget,
|
||||
{
|
||||
fn make_with_id(self, id: WidgetTag) -> WidgetInstance {
|
||||
fn make_with_tag(self, id: WidgetTag) -> WidgetInstance {
|
||||
WidgetInstance::with_id(self, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MakeWidget for T
|
||||
where
|
||||
T: MakeWidgetWithId,
|
||||
T: MakeWidgetWithTag,
|
||||
{
|
||||
fn make_widget(self) -> WidgetInstance {
|
||||
self.make_with_id(WidgetTag::unique())
|
||||
self.make_with_tag(WidgetTag::unique())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1136,9 +1325,9 @@ impl MakeWidget for WidgetInstance {
|
|||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Color {
|
||||
fn make_with_id(self, id: WidgetTag) -> WidgetInstance {
|
||||
Space::colored(self).make_with_id(id)
|
||||
impl MakeWidgetWithTag for Color {
|
||||
fn make_with_tag(self, id: WidgetTag) -> WidgetInstance {
|
||||
Space::colored(self).make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1490,19 +1679,19 @@ where
|
|||
|
||||
/// A [`Widget`] that has been attached to a widget hierarchy.
|
||||
#[derive(Clone)]
|
||||
pub struct ManagedWidget {
|
||||
pub struct MountedWidget {
|
||||
pub(crate) node_id: LotId,
|
||||
pub(crate) widget: WidgetInstance,
|
||||
pub(crate) tree: Tree,
|
||||
}
|
||||
|
||||
impl Debug for ManagedWidget {
|
||||
impl Debug for MountedWidget {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Debug::fmt(&self.widget, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ManagedWidget {
|
||||
impl MountedWidget {
|
||||
/// Locks the widget for exclusive access. Locking widgets should only be
|
||||
/// done for brief moments of time when you are certain no deadlocks can
|
||||
/// occur due to other widget locks being held.
|
||||
|
|
@ -1537,7 +1726,7 @@ impl ManagedWidget {
|
|||
/// This function returns the value set in
|
||||
/// [`MakeWidget::with_next_focus()`].
|
||||
#[must_use]
|
||||
pub fn next_focus(&self) -> Option<ManagedWidget> {
|
||||
pub fn next_focus(&self) -> Option<MountedWidget> {
|
||||
self.widget
|
||||
.next_focus()
|
||||
.and_then(|next_focus| self.tree.widget(next_focus))
|
||||
|
|
@ -1548,14 +1737,14 @@ impl ManagedWidget {
|
|||
/// There is no direct way to set this value. This relationship is created
|
||||
/// automatically using [`MakeWidget::with_next_focus()`].
|
||||
#[must_use]
|
||||
pub fn previous_focus(&self) -> Option<ManagedWidget> {
|
||||
pub fn previous_focus(&self) -> Option<MountedWidget> {
|
||||
self.tree.previous_focus(self.id())
|
||||
}
|
||||
|
||||
/// Returns the next or previous focus target, if one was set using
|
||||
/// [`MakeWidget::with_next_focus()`].
|
||||
#[must_use]
|
||||
pub fn explicit_focus_target(&self, advance: bool) -> Option<ManagedWidget> {
|
||||
pub fn explicit_focus_target(&self, advance: bool) -> Option<MountedWidget> {
|
||||
if advance {
|
||||
self.next_focus()
|
||||
} else {
|
||||
|
|
@ -1605,7 +1794,7 @@ impl ManagedWidget {
|
|||
|
||||
/// Returns the parent of this widget.
|
||||
#[must_use]
|
||||
pub fn parent(&self) -> Option<ManagedWidget> {
|
||||
pub fn parent(&self) -> Option<MountedWidget> {
|
||||
self.tree
|
||||
.parent(self.node_id)
|
||||
.and_then(|id| self.tree.widget_from_node(id))
|
||||
|
|
@ -1643,24 +1832,24 @@ impl ManagedWidget {
|
|||
self.tree.persist_layout(self.node_id, constraints, size);
|
||||
}
|
||||
|
||||
pub(crate) fn visually_ordered_children(&self, order: VisualOrder) -> Vec<ManagedWidget> {
|
||||
pub(crate) fn visually_ordered_children(&self, order: VisualOrder) -> Vec<MountedWidget> {
|
||||
self.tree.visually_ordered_children(self.node_id, order)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<WidgetId> for ManagedWidget {
|
||||
impl AsRef<WidgetId> for MountedWidget {
|
||||
fn as_ref(&self) -> &WidgetId {
|
||||
self.widget.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ManagedWidget {
|
||||
impl PartialEq for MountedWidget {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.widget == other.widget
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<WidgetInstance> for ManagedWidget {
|
||||
impl PartialEq<WidgetInstance> for MountedWidget {
|
||||
fn eq(&self, other: &WidgetInstance) -> bool {
|
||||
&self.widget == other
|
||||
}
|
||||
|
|
@ -1915,7 +2104,7 @@ pub enum ChildrenSyncChange {
|
|||
/// contain multiple children widgets. It is used in conjunction with a
|
||||
/// `Value<Children>`.
|
||||
#[derive(Debug)]
|
||||
pub struct MountedChildren<T = ManagedWidget> {
|
||||
pub struct MountedChildren<T = MountedWidget> {
|
||||
generation: Option<Generation>,
|
||||
children: Vec<T>,
|
||||
}
|
||||
|
|
@ -1990,23 +2179,23 @@ impl<T> Default for MountedChildren<T> {
|
|||
/// A child in a [`MountedChildren`] collection.
|
||||
pub trait MountableChild: Sized {
|
||||
/// Returns the mounted representation of `widget`.
|
||||
fn mount(widget: ManagedWidget, into: &MountedChildren<Self>, index: usize) -> Self;
|
||||
fn mount(widget: MountedWidget, into: &MountedChildren<Self>, index: usize) -> Self;
|
||||
/// Returns the widget and performs any other cleanup for this widget being unmounted.q
|
||||
fn unmount(self) -> ManagedWidget;
|
||||
fn unmount(self) -> MountedWidget;
|
||||
/// Returns a reference to the widget.
|
||||
fn widget(&self) -> &ManagedWidget;
|
||||
fn widget(&self) -> &MountedWidget;
|
||||
}
|
||||
|
||||
impl MountableChild for ManagedWidget {
|
||||
fn mount(widget: ManagedWidget, _into: &MountedChildren<Self>, _index: usize) -> Self {
|
||||
impl MountableChild for MountedWidget {
|
||||
fn mount(widget: MountedWidget, _into: &MountedChildren<Self>, _index: usize) -> Self {
|
||||
widget
|
||||
}
|
||||
|
||||
fn widget(&self) -> &ManagedWidget {
|
||||
fn widget(&self) -> &MountedWidget {
|
||||
self
|
||||
}
|
||||
|
||||
fn unmount(self) -> ManagedWidget {
|
||||
fn unmount(self) -> MountedWidget {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -2017,7 +2206,7 @@ pub enum WidgetRef {
|
|||
/// An unmounted child widget
|
||||
Unmounted(WidgetInstance),
|
||||
/// A mounted child widget
|
||||
Mounted(ManagedWidget),
|
||||
Mounted(MountedWidget),
|
||||
}
|
||||
|
||||
impl WidgetRef {
|
||||
|
|
@ -2037,7 +2226,7 @@ impl WidgetRef {
|
|||
pub fn mounted<'window>(
|
||||
&mut self,
|
||||
context: &mut impl AsEventContext<'window>,
|
||||
) -> ManagedWidget {
|
||||
) -> MountedWidget {
|
||||
self.mount_if_needed(context);
|
||||
|
||||
let Self::Mounted(widget) = self else {
|
||||
|
|
@ -2101,14 +2290,14 @@ impl WidgetId {
|
|||
|
||||
/// Finds this widget mounted in this window, if present.
|
||||
#[must_use]
|
||||
pub fn find_in(self, context: &WidgetContext<'_, '_>) -> Option<ManagedWidget> {
|
||||
pub fn find_in(self, context: &WidgetContext<'_, '_>) -> Option<MountedWidget> {
|
||||
context.widget().tree.widget(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`WidgetId`] that has not been assigned to a [`WidgetInstance`].
|
||||
///
|
||||
/// This type is passed to [`MakeWidgetWithId::make_with_id()`] to create a
|
||||
/// This type is passed to [`MakeWidgetWithTag::make_with_tag()`] to create a
|
||||
/// [`WidgetInstance`] with a preallocated id.
|
||||
///
|
||||
/// This type cannot be cloned or copied to ensure only a single widget can be
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ impl Button {
|
|||
}
|
||||
|
||||
fn determine_stateful_colors(&mut self, context: &mut WidgetContext<'_, '_>) -> ButtonColors {
|
||||
let kind = self.kind.get_tracked(context);
|
||||
let kind = self.kind.get_tracking_redraw(context);
|
||||
let visual_state = Self::visual_style(context);
|
||||
|
||||
self.cached_state = CacheState {
|
||||
|
|
@ -352,7 +352,7 @@ impl Widget for Button {
|
|||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
#![allow(clippy::similar_names)]
|
||||
|
||||
let current_style = self.kind.get_tracked(context);
|
||||
let current_style = self.kind.get_tracking_redraw(context);
|
||||
if self.cached_state.key != context.cache_key() || self.cached_state.kind != current_style {
|
||||
self.update_colors(context, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::context::{GraphicsContext, LayoutContext};
|
|||
use crate::styles::components::{LineHeight, OutlineColor, TextColor, WidgetAccentColor};
|
||||
use crate::styles::Dimension;
|
||||
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithId, Widget, WidgetInstance};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
|
||||
use crate::widgets::button::ButtonKind;
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
|
|
@ -51,8 +51,8 @@ impl Checkbox {
|
|||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Checkbox {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
impl MakeWidgetWithTag for Checkbox {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
CheckboxOrnament {
|
||||
value: self.state.create_reader(),
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ impl MakeWidgetWithId for Checkbox {
|
|||
*value = !*value;
|
||||
})
|
||||
.kind(self.kind)
|
||||
.make_with_id(id)
|
||||
.make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ impl Widget for CheckboxOrnament {
|
|||
);
|
||||
|
||||
let stroke_options = StrokeOptions::lp_wide(Lp::points(2)).into_px(context.gfx.scale());
|
||||
match self.value.get_tracking_refresh(context) {
|
||||
match self.value.get_tracking_redraw(context) {
|
||||
state @ (CheckboxState::Checked | CheckboxState::Indeterminant) => {
|
||||
let color = context.get(&WidgetAccentColor);
|
||||
context
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ impl Widget for ColorSourcePicker {
|
|||
let loupe_size = Lp::mm(3).into_px(context.gfx.scale());
|
||||
let size = context.gfx.region().size;
|
||||
|
||||
let value = self.value.get_tracking_refresh(context);
|
||||
let value = self.value.get_tracking_redraw(context);
|
||||
let value_pos = self.visible_rect.origin
|
||||
+ Point::new(
|
||||
if self.hue_is_360 {
|
||||
|
|
@ -84,7 +84,7 @@ impl Widget for ColorSourcePicker {
|
|||
self.visible_rect.size.height * *value.saturation.one_minus(),
|
||||
);
|
||||
|
||||
let lightness = self.lightness.get_tracked(context);
|
||||
let lightness = self.lightness.get_tracking_redraw(context);
|
||||
let value_color = value.color(lightness);
|
||||
|
||||
let outline_color = if context.focused(true) {
|
||||
|
|
|
|||
|
|
@ -544,7 +544,9 @@ impl WrapperWidget for Custom {
|
|||
}
|
||||
|
||||
fn background_color(&mut self, context: &WidgetContext<'_, '_>) -> Option<Color> {
|
||||
self.background.as_ref().map(|bg| bg.get_tracked(context))
|
||||
self.background
|
||||
.as_ref()
|
||||
.map(|bg| bg.get_tracking_redraw(context))
|
||||
}
|
||||
|
||||
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContex
|
|||
use crate::styles::components::IntrinsicPadding;
|
||||
use crate::styles::Dimension;
|
||||
use crate::value::{Generation, IntoValue, Value};
|
||||
use crate::widget::{MakeWidget, ManagedWidget, Widget, WidgetInstance};
|
||||
use crate::widget::{MakeWidget, MountedWidget, Widget, WidgetInstance};
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
/// A 2D grid of widgets.
|
||||
|
|
@ -24,7 +24,7 @@ use crate::ConstraintLimit;
|
|||
pub struct Grid<const ELEMENTS: usize> {
|
||||
columns: Value<[GridDimension; ELEMENTS]>,
|
||||
rows: Value<GridWidgets<ELEMENTS>>,
|
||||
live_rows: Vec<[ManagedWidget; ELEMENTS]>,
|
||||
live_rows: Vec<[MountedWidget; ELEMENTS]>,
|
||||
layout: GridLayout,
|
||||
layout_generation: Option<Generation>,
|
||||
spec_generation: Option<Generation>,
|
||||
|
|
|
|||
|
|
@ -1019,7 +1019,7 @@ where
|
|||
}
|
||||
|
||||
self.blink_state.update(context.elapsed());
|
||||
let window_focused = context.window().focused().get_tracking_refresh(context);
|
||||
let window_focused = context.window().focused().get_tracking_redraw(context);
|
||||
if window_focused != self.window_focused {
|
||||
if window_focused {
|
||||
self.blink_state.force_on();
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ impl Widget for Label {
|
|||
|
||||
macro_rules! impl_make_widget {
|
||||
($($type:ty),*) => {
|
||||
$(impl crate::widget::MakeWidgetWithId for $type {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
Label::new(self).make_with_id(id)
|
||||
$(impl crate::widget::MakeWidgetWithTag for $type {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
Label::new(self).make_with_tag(id)
|
||||
}
|
||||
})*
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContex
|
|||
use crate::utils::IgnorePoison;
|
||||
use crate::value::{Dynamic, DynamicGuard, IntoValue, Value};
|
||||
use crate::widget::{
|
||||
Callback, Children, MakeWidget, ManagedWidget, MountedChildren, Widget, WidgetId, WidgetRef,
|
||||
Callback, Children, MakeWidget, MountedChildren, MountedWidget, Widget, WidgetId, WidgetRef,
|
||||
WrapperWidget,
|
||||
};
|
||||
use crate::widgets::container::ContainerShadow;
|
||||
|
|
@ -182,7 +182,7 @@ impl Widget for OverlayLayer {
|
|||
continue;
|
||||
};
|
||||
|
||||
let opacity = child.opacity.get_tracking_refresh(context);
|
||||
let opacity = child.opacity.get_tracking_redraw(context);
|
||||
let mut context = context.for_other(mounted);
|
||||
context.apply_opacity(opacity);
|
||||
context.redraw();
|
||||
|
|
@ -376,7 +376,7 @@ impl OverlayState {
|
|||
fn layout_overlay_relative(
|
||||
&mut self,
|
||||
index: usize,
|
||||
widget: &ManagedWidget,
|
||||
widget: &MountedWidget,
|
||||
available_space: Size<UPx>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
relative_to: WidgetId,
|
||||
|
|
@ -495,7 +495,7 @@ impl OverlayState {
|
|||
fn layout_overlay(
|
||||
&mut self,
|
||||
index: usize,
|
||||
widget: &ManagedWidget,
|
||||
widget: &MountedWidget,
|
||||
available_space: Size<UPx>,
|
||||
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
|
||||
) -> Option<Rect<Px>> {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use crate::animation::{
|
|||
AnimationHandle, AnimationTarget, IntoAnimate, PercentBetween, Spawn, ZeroToOne,
|
||||
};
|
||||
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Value};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithId, Widget, WidgetInstance};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
|
||||
use crate::widgets::slider::{InactiveTrackColor, Slidable, TrackColor, TrackSize};
|
||||
use crate::widgets::Data;
|
||||
|
||||
|
|
@ -60,8 +60,8 @@ pub enum Progress<T = ZeroToOne> {
|
|||
Percent(T),
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for ProgressBar {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
impl MakeWidgetWithTag for ProgressBar {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
let start = Dynamic::new(ZeroToOne::ZERO);
|
||||
let end = Dynamic::new(ZeroToOne::ZERO);
|
||||
let value = (&start, &end).map_each(|(start, end)| *start..=*end);
|
||||
|
|
@ -76,12 +76,16 @@ impl MakeWidgetWithId for ProgressBar {
|
|||
end: end.clone(),
|
||||
degree_offset: degree_offset.clone(),
|
||||
}
|
||||
.make_with_id(id),
|
||||
.make_with_tag(id),
|
||||
Some(degree_offset),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
value.slider().knobless().non_interactive().make_with_id(id),
|
||||
value
|
||||
.slider()
|
||||
.knobless()
|
||||
.non_interactive()
|
||||
.make_with_tag(id),
|
||||
None,
|
||||
)
|
||||
};
|
||||
|
|
@ -332,8 +336,8 @@ impl Spinner {
|
|||
impl Widget for Spinner {
|
||||
fn redraw(&mut self, context: &mut crate::context::GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let track_size = context.get(&TrackSize).into_px(context.gfx.scale());
|
||||
let start = self.start.get_tracking_refresh(context);
|
||||
let end = self.end.get_tracking_refresh(context);
|
||||
let start = self.start.get_tracking_redraw(context);
|
||||
let end = self.end.get_tracking_redraw(context);
|
||||
let size = context.gfx.region().size;
|
||||
let render_size = size.width.min(size.height);
|
||||
let radius = render_size / 2 - track_size;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::context::{GraphicsContext, LayoutContext};
|
|||
use crate::styles::components::{LineHeight, OutlineColor, WidgetAccentColor};
|
||||
use crate::styles::Dimension;
|
||||
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithId, Widget, WidgetInstance};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithTag, Widget, WidgetInstance};
|
||||
use crate::widgets::button::ButtonKind;
|
||||
use crate::ConstraintLimit;
|
||||
|
||||
|
|
@ -51,11 +51,11 @@ impl<T> Radio<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> MakeWidgetWithId for Radio<T>
|
||||
impl<T> MakeWidgetWithTag for Radio<T>
|
||||
where
|
||||
T: Clone + Debug + Eq + UnwindSafe + Send + 'static,
|
||||
{
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
RadioOrnament {
|
||||
value: self.value.clone(),
|
||||
state: self.state.create_reader(),
|
||||
|
|
@ -67,7 +67,7 @@ where
|
|||
self.state.set(self.value.clone());
|
||||
})
|
||||
.kind(self.kind)
|
||||
.make_with_id(id)
|
||||
.make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use kludgine::Color;
|
|||
use crate::styles::components::OutlineColor;
|
||||
use crate::styles::{Component, DynamicComponent};
|
||||
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Value};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithId, WidgetInstance};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithTag, WidgetInstance};
|
||||
use crate::widgets::button::{ButtonBackground, ButtonHoverBackground, ButtonKind};
|
||||
|
||||
/// A selectable, labeled widget representing a value.
|
||||
|
|
@ -46,11 +46,11 @@ impl<T> Select<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> MakeWidgetWithId for Select<T>
|
||||
impl<T> MakeWidgetWithTag for Select<T>
|
||||
where
|
||||
T: Clone + Debug + Eq + RefUnwindSafe + UnwindSafe + Send + Sync + 'static,
|
||||
{
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
let selected = self.state.map_each({
|
||||
let value = self.value.clone();
|
||||
move |state| state == &value
|
||||
|
|
@ -58,7 +58,7 @@ where
|
|||
let selected_color = DynamicComponent::new({
|
||||
let selected = selected.clone();
|
||||
move |context| {
|
||||
if selected.get_tracking_refresh(context) {
|
||||
if selected.get_tracking_redraw(context) {
|
||||
Some(Component::Color(context.get(&SelectedColor)))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -80,7 +80,7 @@ where
|
|||
.kind(kind)
|
||||
.with_dynamic(&ButtonBackground, selected_color.clone())
|
||||
.with_dynamic(&ButtonHoverBackground, selected_color)
|
||||
.make_with_id(id)
|
||||
.make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -443,9 +443,9 @@ where
|
|||
let half_knob = knob_size / 2;
|
||||
|
||||
let (mut start_value, mut end_value) =
|
||||
T::into_parts(self.value.get_tracking_refresh(context));
|
||||
let min = self.minimum.get_tracked(context);
|
||||
let mut max = self.maximum.get_tracked(context);
|
||||
T::into_parts(self.value.get_tracking_redraw(context));
|
||||
let min = self.minimum.get_tracking_redraw(context);
|
||||
let mut max = self.maximum.get_tracking_redraw(context);
|
||||
|
||||
if max < min {
|
||||
self.maximum.map_mut(|max| *max = min.clone());
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ impl Space {
|
|||
|
||||
impl Widget for Space {
|
||||
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
|
||||
let color = self.color.get_tracked(context);
|
||||
let color = self.color.get_tracking_redraw(context);
|
||||
context.fill(color);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContex
|
|||
use crate::styles::components::IntrinsicPadding;
|
||||
use crate::styles::FlexibleDimension;
|
||||
use crate::value::{Generation, IntoValue, Value};
|
||||
use crate::widget::{Children, ChildrenSyncChange, ManagedWidget, Widget, WidgetRef};
|
||||
use crate::widget::{Children, ChildrenSyncChange, MountedWidget, Widget, WidgetRef};
|
||||
use crate::widgets::grid::{GridDimension, GridLayout, Orientation};
|
||||
use crate::widgets::{Expand, Resize};
|
||||
use crate::ConstraintLimit;
|
||||
|
|
@ -24,7 +24,7 @@ pub struct Stack {
|
|||
layout: GridLayout,
|
||||
layout_generation: Option<Generation>,
|
||||
// TODO Refactor synced_children into its own type.
|
||||
synced_children: Vec<ManagedWidget>,
|
||||
synced_children: Vec<MountedWidget>,
|
||||
}
|
||||
|
||||
impl Stack {
|
||||
|
|
@ -68,7 +68,7 @@ impl Stack {
|
|||
self.children.map(|children| {
|
||||
children.synchronize_with(
|
||||
&mut self.synced_children,
|
||||
|this, index| this.get(index).map(ManagedWidget::instance),
|
||||
|this, index| this.get(index).map(MountedWidget::instance),
|
||||
|this, change| match change {
|
||||
ChildrenSyncChange::Insert(index, widget) => {
|
||||
// This is a brand new child.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::styles::components::{
|
|||
};
|
||||
use crate::styles::Dimension;
|
||||
use crate::value::{Dynamic, IntoDynamic, IntoValue, MapEach, Validation, Value};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithId, WidgetInstance, WidgetRef, WrapperWidget};
|
||||
use crate::widget::{MakeWidget, MakeWidgetWithTag, WidgetInstance, WidgetRef, WrapperWidget};
|
||||
|
||||
/// A widget that displays validation information around another widget.
|
||||
///
|
||||
|
|
@ -46,8 +46,8 @@ impl Validated {
|
|||
}
|
||||
}
|
||||
|
||||
impl MakeWidgetWithId for Validated {
|
||||
fn make_with_id(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
impl MakeWidgetWithTag for Validated {
|
||||
fn make_with_tag(self, id: crate::widget::WidgetTag) -> WidgetInstance {
|
||||
let message = match self.hint {
|
||||
Value::Constant(hint) => self
|
||||
.validation
|
||||
|
|
@ -84,7 +84,7 @@ impl MakeWidgetWithId for Validated {
|
|||
error_color,
|
||||
default_color,
|
||||
}
|
||||
.make_with_id(id)
|
||||
.make_with_tag(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use crate::tree::Tree;
|
|||
use crate::utils::ModifiersExt;
|
||||
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
|
||||
use crate::widget::{
|
||||
EventHandling, ManagedWidget, RootBehavior, Widget, WidgetId, WidgetInstance, HANDLED, IGNORED,
|
||||
EventHandling, MountedWidget, RootBehavior, Widget, WidgetId, WidgetInstance, HANDLED, IGNORED,
|
||||
};
|
||||
use crate::window::sealed::WindowCommand;
|
||||
use crate::{initialize_tracing, ConstraintLimit, Run};
|
||||
|
|
@ -338,7 +338,7 @@ pub trait WindowBehavior: Sized + 'static {
|
|||
|
||||
struct GooeyWindow<T> {
|
||||
behavior: T,
|
||||
root: ManagedWidget,
|
||||
root: MountedWidget,
|
||||
contents: Drawing,
|
||||
should_close: bool,
|
||||
cursor: CursorState,
|
||||
|
|
@ -1221,7 +1221,7 @@ where
|
|||
fn recursively_handle_event(
|
||||
context: &mut EventContext<'_, '_>,
|
||||
mut each_widget: impl FnMut(&mut EventContext<'_, '_>) -> EventHandling,
|
||||
) -> Option<ManagedWidget> {
|
||||
) -> Option<MountedWidget> {
|
||||
match each_widget(context) {
|
||||
HANDLED => Some(context.widget().clone()),
|
||||
IGNORED => context.parent().and_then(|parent| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue