Skip to content

Commit

Permalink
Merge pull request #306 from kas-gui/work2
Browse files Browse the repository at this point in the history
make_layout: support inline text; doc; #[autoimpl(Storage)]
  • Loading branch information
dhardy committed Apr 19, 2022
2 parents 905e877 + 3b139bb commit 8de2d60
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 357 deletions.
8 changes: 1 addition & 7 deletions crates/kas-core/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,6 @@ pub trait Component {
/// Apply a given `rect` to self
fn set_rect(&mut self, mgr: &mut SetRectMgr, rect: Rect, align: AlignHints);

/// True if the layout direction is up/left (reverse reading direction)
///
/// TODO: replace with spatial_nav?
fn is_reversed(&self) -> bool {
false
}

/// Translate a coordinate to a [`WidgetId`]
fn find_id(&mut self, coord: Coord) -> Option<WidgetId>;

Expand All @@ -41,6 +34,7 @@ impl_scope! {
/// A label component
#[impl_default(where T: trait)]
#[autoimpl(Clone, Debug where T: trait)]
#[autoimpl(Storage where T: 'static)]
pub struct Label<T: format::FormattableText> {
text: Text<T>,
class: TextClass = TextClass::Label(false),
Expand Down
35 changes: 11 additions & 24 deletions crates/kas-core/src/core/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,17 @@ pub trait Layout: WidgetChildren {

/// Navigation in spatial order
///
/// Returns the index of the "next" child in iteration order within the
/// widget's rect, if any. (Pop-up widgets should be excluded.)
/// Controls <kbd>Tab</kbd> navigation order of children.
/// This method should:
///
/// If `reverse` is true, move in left/up direction, otherwise right/down.
/// If `from.is_some()`, return its next sibling in iteration order,
/// otherwise return the first or last child.
/// - Return `None` if there is no next child
/// - Determine the next child after `from` (if provided) or the whole
/// range, optionally in `reverse` order
/// - Ensure that the selected widget is addressable through
/// [`WidgetChildren::get_child`]
///
/// Both `from` and the return value use the widget index, as used by
/// [`WidgetChildren::get_child`].
///
/// The default implementation often suffices: it will navigate through
/// children in order.
Expand All @@ -333,25 +338,7 @@ pub trait Layout: WidgetChildren {
from: Option<usize>,
) -> Option<usize> {
let _ = mgr;
let last = self.num_children().wrapping_sub(1);
if last == usize::MAX {
return None;
}

let reverse = reverse ^ self.layout().is_reversed();

if let Some(index) = from {
match reverse {
false if index < last => Some(index + 1),
true if 0 < index => Some(index - 1),
_ => None,
}
} else {
match reverse {
false => Some(0),
true => Some(last),
}
}
crate::util::spatial_nav(reverse, from, self.num_children())
}

/// Translate a coordinate to a [`WidgetId`]
Expand Down
38 changes: 3 additions & 35 deletions crates/kas-core/src/layout/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ pub struct StorageChain(Option<(Box<StorageChain>, Box<dyn Storage>)>);
impl StorageChain {
/// Access layout storage
///
/// This storage is allocated and initialised on first access.
/// This storage is allocated and initialised via `f()` on first access.
///
/// Panics if the type `T` differs from the initial usage.
pub fn storage<T: Storage + Default>(&mut self) -> (&mut T, &mut StorageChain) {
pub fn storage<T: Storage, F: FnOnce() -> T>(&mut self, f: F) -> (&mut T, &mut StorageChain) {
if let StorageChain(Some(ref mut b)) = self {
let storage =
b.1.downcast_mut()
Expand All @@ -45,7 +45,7 @@ impl StorageChain {
}
// TODO(rust#42877): store (StorageChain, dyn Storage) tuple in a single box
let s = Box::new(StorageChain(None));
let t: Box<dyn Storage> = Box::new(T::default());
let t: Box<dyn Storage> = Box::new(f());
*self = StorageChain(Some((s, t)));
match self {
StorageChain(Some(b)) => (b.1.downcast_mut::<T>().unwrap(), &mut b.0),
Expand Down Expand Up @@ -247,25 +247,6 @@ impl<'a> Layout<'a> {
}
}

/// Return true if layout is up/left
///
/// This is a lazy method of implementing tab order for reversible layouts.
#[inline]
pub fn is_reversed(mut self) -> bool {
self.is_reversed_()
}
fn is_reversed_(&mut self) -> bool {
match &mut self.layout {
LayoutType::None => false,
LayoutType::Component(component) => component.is_reversed(),
LayoutType::BoxComponent(layout) => layout.is_reversed(),
LayoutType::Single(_) | LayoutType::AlignSingle(_, _) => false,
LayoutType::AlignLayout(layout, _) => layout.is_reversed_(),
LayoutType::Frame(layout, _, _) => layout.is_reversed_(),
LayoutType::Button(layout, _, _) => layout.is_reversed_(),
}
}

/// Find a widget by coordinate
///
/// Does not return the widget's own identifier. See example usage in
Expand Down Expand Up @@ -344,10 +325,6 @@ where
}
}

fn is_reversed(&self) -> bool {
self.direction.is_reversed()
}

fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
// TODO(opt): more efficient search strategy?
self.children.find_map(|child| child.find_id(coord))
Expand Down Expand Up @@ -386,10 +363,6 @@ impl<'a, W: WidgetConfig, D: Directional> Component for Slice<'a, W, D> {
}
}

fn is_reversed(&self) -> bool {
self.direction.is_reversed()
}

fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
let solver = RowPositionSolver::new(self.direction);
solver
Expand Down Expand Up @@ -429,11 +402,6 @@ where
}
}

fn is_reversed(&self) -> bool {
// TODO: replace is_reversed with direct implementation of spatial_nav
false
}

fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
// TODO(opt): more efficient search strategy?
self.children.find_map(|(_, child)| child.find_id(coord))
Expand Down
2 changes: 2 additions & 0 deletions crates/kas-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#![cfg_attr(feature = "gat", feature(generic_associated_types))]
#![cfg_attr(feature = "spec", feature(specialization))]

extern crate self as kas;

#[macro_use]
extern crate bitflags;

Expand Down
21 changes: 21 additions & 0 deletions crates/kas-core/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,24 @@ impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for TryFormat<'a, T> {
write!(f, "{:?}", self.0)
}
}

/// Generic implementation of [`crate::Layout::spatial_nav`]
pub fn spatial_nav(reverse: bool, from: Option<usize>, len: usize) -> Option<usize> {
let last = len.wrapping_sub(1);
if last == usize::MAX {
return None;
}

if let Some(index) = from {
match reverse {
false if index < last => Some(index + 1),
true if 0 < index => Some(index - 1),
_ => None,
}
} else {
match reverse {
false => Some(0),
true => Some(last),
}
}
}
Loading

0 comments on commit 8de2d60

Please sign in to comment.