Skip to content

Commit

Permalink
Merge pull request #465 from kas-gui/work5
Browse files Browse the repository at this point in the history
Remove Deref impls
  • Loading branch information
dhardy authored Jan 9, 2025
2 parents 92c424e + e996d06 commit f133edc
Show file tree
Hide file tree
Showing 27 changed files with 428 additions and 393 deletions.
1 change: 1 addition & 0 deletions crates/kas-core/src/core/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl WidgetStatus {
*self = WidgetStatus::SetRect;
}

/// Require that set_rect has been called
pub fn require_rect(&self, id: &Id) {
self.require(id, WidgetStatus::SetRect);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/kas-core/src/draw/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl Rgba8Srgb {

const fn byte(a: u8, b: u8) -> Result<u8, ()> {
match (val(a), val(b)) {
(Ok(hi), Ok(lo)) => Ok(hi << 4 | lo),
(Ok(hi), Ok(lo)) => Ok((hi << 4) | lo),
_ => Err(()),
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/kas-core/src/event/cx/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ impl<'a> ConfigCx<'a> {
/// [`Events::make_child_id`].
#[inline]
pub fn configure(&mut self, mut widget: Node<'_>, id: Id) {
widget._configure(self, id);
if id.is_valid() {
widget._configure(self, id);
}
}

/// Update a widget
Expand Down
126 changes: 15 additions & 111 deletions crates/kas-core/src/hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
//! not supported (i.e. **changes are not considered breaking**).
use crate::classes::HasStr;
use crate::event::{ConfigCx, Event, EventCx, IsUsed};
use crate::event::ConfigCx;
use crate::geom::Rect;
use crate::layout::{Align, AlignHints, AxisInfo, SizeRules};
use crate::theme::{DrawCx, SizeCx, Text, TextClass};
use crate::{Events, Id, Layout, NavAdvance, Node, Widget};
use crate::{Events, Layout, Widget};
use kas_macros::{autoimpl, impl_scope};

impl_scope! {
Expand Down Expand Up @@ -75,11 +75,24 @@ impl_scope! {

impl_scope! {
/// Map any input data to `()`
///
/// This is a generic data-mapping widget-wrapper with fixed `()` input
/// data type.
///
/// This struct is a thin wrapper around the inner widget without its own
/// [`Id`](crate::Id). It supports [`Deref`](std::ops::Deref) and
/// [`DerefMut`](std::ops::DerefMut) to the inner widget.
#[autoimpl(Deref, DerefMut using self.inner)]
#[autoimpl(class_traits using self.inner where W: trait)]
#[derive(Clone, Default)]
#[widget {
Data = A;
data_expr = &();
derive = self.inner;
}]
pub struct MapAny<A, W: Widget<Data = ()>> {
_a: std::marker::PhantomData<A>,
/// The inner widget
pub inner: W,
}

Expand All @@ -92,113 +105,4 @@ impl_scope! {
}
}
}

impl Layout for Self {
#[inline]
fn as_layout(&self) -> &dyn ::kas::Layout {
self
}
#[inline]
fn id_ref(&self) -> &::kas::Id {
self.inner.id_ref()
}
#[inline]
fn rect(&self) -> ::kas::geom::Rect {
self.inner.rect()
}

#[inline]
fn widget_name(&self) -> &'static str {
"MapAny"
}

#[inline]
fn num_children(&self) -> usize {
self.inner.num_children()
}
#[inline]
fn get_child(&self, index: usize) -> Option<&dyn ::kas::Layout> {
self.inner.get_child(index)
}
#[inline]
fn find_child_index(&self, id: &::kas::Id) -> Option<usize> {
self.inner.find_child_index(id)
}

#[inline]
fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
self.inner.size_rules(sizer, axis)
}

#[inline]
fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
self.inner.set_rect(cx, rect, hints);
}

#[inline]
fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
self.inner.nav_next(reverse, from)
}

#[inline]
fn translation(&self) -> ::kas::geom::Offset {
self.inner.translation()
}

// NOTE: fn probe is left unimplemented since it should not be called directly

#[inline]
fn try_probe(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> {
self.inner.try_probe(coord)
}

#[inline]
fn draw(&mut self, draw: DrawCx) {
self.inner.draw(draw);
}
}

impl Widget for Self {
type Data = A;

fn as_node<'a>(&'a mut self, _: &'a A) -> Node<'a> {
self.inner.as_node(&())
}

#[inline]
fn for_child_node(
&mut self,
_: &A,
index: usize,
closure: Box<dyn FnOnce(Node<'_>) + '_>,
) {
self.inner.for_child_node(&(), index, closure)
}

fn _configure(&mut self, cx: &mut ConfigCx, _: &A, id: Id) {
self.inner._configure(cx, &(), id);
}

fn _update(&mut self, cx: &mut ConfigCx, _: &A) {
self.inner._update(cx, &());
}

fn _send(&mut self, cx: &mut EventCx, _: &A, id: Id, event: Event) -> IsUsed {
self.inner._send(cx, &(), id, event)
}

fn _replay(&mut self, cx: &mut EventCx, _: &A, id: Id) {
self.inner._replay(cx, &(), id);
}

fn _nav_next(
&mut self,
cx: &mut ConfigCx,
_: &A,
focus: Option<&Id>,
advance: NavAdvance,
) -> Option<Id> {
self.inner._nav_next(cx, &(), focus, advance)
}
}
}
6 changes: 3 additions & 3 deletions crates/kas-core/src/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use crate::dir::Direction;
use crate::event::{ConfigCx, Event, EventCx, IsUsed, Scroll, Unused, Used};
use crate::{Events, Id, LayoutExt, Widget, WindowId};
use kas_macros::{autoimpl, impl_scope, widget_index};
use kas_macros::{impl_scope, widget_index};

#[allow(unused)] use crate::event::EventState;

Expand All @@ -34,15 +34,15 @@ impl_scope! {
/// NOTE: currently only the emulated approach is implemented.
///
/// A popup receives input data from its parent like any other widget.
#[autoimpl(Deref, DerefMut using self.inner)]
#[widget {
layout = frame!(self.inner, style = kas::theme::FrameStyle::Popup);
}]
pub struct Popup<W: Widget> {
core: widget_core!(),
direction: Direction,
/// The inner widget
#[widget]
inner: W,
pub inner: W,
win_id: Option<WindowId>,
}

Expand Down
17 changes: 15 additions & 2 deletions crates/kas-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub fn impl_scope(input: TokenStream) -> TokenStream {
/// Supported arguments (_WidgetAttrArg_) are:
///
/// - <code>Data = Type</code>: the `Widget::Data` associated type
/// - <code>data_expr = expr</code>: a mapping expression for the derived
/// widget's input data; requires `derive` and `Data` arguments.
/// Inputs available to this expression are `self` and `data`.
/// - <code>derive = self.<em>field</em></code> where
/// <code><em>field</em></code> is the name (or number) of a field:
/// enables "derive mode" ([see below](#derive)) over the given field
Expand Down Expand Up @@ -276,7 +279,6 @@ pub fn impl_scope(input: TokenStream) -> TokenStream {
/// ```ignore
/// impl_scope! {
/// /// A frame around content
/// #[autoimpl(Deref, DerefMut using self.inner)]
/// #[autoimpl(class_traits using self.inner where W: trait)]
/// #[derive(Clone, Default)]
/// #[widget{
Expand Down Expand Up @@ -316,7 +318,17 @@ pub fn impl_scope(input: TokenStream) -> TokenStream {
/// ```
///
/// This is a special mode where most features of `#[widget]` are not
/// available.
/// available; most notably, the deriving widget does not have its own `Id`.
///
/// ### A note on `Deref`
///
/// The "derive" example implements [`Deref`] over the inner widget. This is
/// acceptable for a simple wrapping "derive widget". It is not recommended to
/// implement [`Deref`] outside of derive mode (i.e. when the outer widget has
/// its own `Id`) due to the potential for method collision (e.g. `outer.id()`
/// may resolve to `outer.deref().id()` when the trait providing `fn id` is not
/// in scope, yet is available through a bound on the field).
///
///
/// ## Debugging
///
Expand All @@ -335,6 +347,7 @@ pub fn impl_scope(input: TokenStream) -> TokenStream {
/// [`CursorIcon`]: https://docs.rs/kas/latest/kas/event/enum.CursorIcon.html
/// [`IsUsed`]: https://docs.rs/kas/latest/kas/event/enum.IsUsed.html
/// [`CoreData`]: https://docs.rs/kas/latest/kas/struct.CoreData.html
/// [`Deref`]: std::ops::Deref
#[proc_macro_attribute]
#[proc_macro_error]
pub fn widget(_: TokenStream, item: TokenStream) -> TokenStream {
Expand Down
6 changes: 2 additions & 4 deletions crates/kas-macros/src/make_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ impl Tree {
#core_impl
#num_children
fn get_child(&self, index: usize) -> Option<&dyn ::kas::Layout> {
use ::kas::Layout;
match index {
#get_rules
_ => None,
Expand Down Expand Up @@ -196,14 +195,13 @@ impl Tree {
}

fn probe(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id {
use ::kas::{Layout, LayoutExt, layout::LayoutVisitor};
#[cfg(debug_assertions)]
#core_path.status.require_rect(&#core_path.id);

let coord = coord + self.translation();
self.layout_visitor()
::kas::layout::LayoutVisitor::layout_visitor(self)
.try_probe(coord)
.unwrap_or_else(|| self.id())
.unwrap_or_else(|| ::kas::LayoutExt::id(self))
}

fn draw(&mut self, draw: ::kas::theme::DrawCx) {
Expand Down
17 changes: 9 additions & 8 deletions crates/kas-macros/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
let name = &scope.ident;
let mut data_ty = args.data_ty.map(|data_ty| data_ty.ty);

if let Some(ref item) = args.data_expr {
emit_error!(item, "only supported in `derive` mode");
}

let mut widget_impl = None;
let mut layout_impl = None;
let mut events_impl = None;
Expand Down Expand Up @@ -340,7 +344,6 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
#count
}
fn get_child(&self, index: usize) -> Option<&dyn ::kas::Layout> {
use ::kas::Layout;
match index {
#get_rules
_ => None,
Expand Down Expand Up @@ -384,8 +387,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
let mut fn_size_rules = None;
let mut set_rect = quote! { self.#core.rect = rect; };
let mut probe = quote! {
use ::kas::{Layout, LayoutExt};
self.id()
::kas::LayoutExt::id(self)
};
let mut fn_draw = None;
if let Some(Layout { tree, .. }) = args.layout.take() {
Expand Down Expand Up @@ -423,12 +425,10 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul
::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints);
};
probe = quote! {
use ::kas::{Layout, LayoutExt, layout::LayoutVisitor};

let coord = coord + self.translation();
self.layout_visitor()
::kas::layout::LayoutVisitor::layout_visitor(self)
.try_probe(coord)
.unwrap_or_else(|| self.id())
.unwrap_or_else(|| ::kas::LayoutExt::id(self))
};
fn_draw = Some(quote! {
fn draw(&mut self, draw: ::kas::theme::DrawCx) {
Expand Down Expand Up @@ -735,7 +735,6 @@ pub fn impl_widget(
index: usize,
closure: Box<dyn FnOnce(::kas::Node<'_>) + '_>,
) {
use ::kas::Layout;
match index {
#get_mut_rules
_ => (),
Expand Down Expand Up @@ -777,6 +776,8 @@ fn widget_recursive_methods(core_path: &Toks) -> Toks {
data: &Self::Data,
id: ::kas::Id,
) {
debug_assert!(id.is_valid(), "Widget::_configure called with invalid id!");

#core_path.id = id;
#[cfg(debug_assertions)]
#core_path.status.configure(&#core_path.id);
Expand Down
Loading

0 comments on commit f133edc

Please sign in to comment.