Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 21 additions & 84 deletions crates/kas-core/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,76 +7,34 @@

#[allow(unused)]
use crate::event::{ConfigCx, EventCx, EventState};
use std::ops::{BitOr, BitOrAssign, Deref};

/// Action: widget has moved/opened/closed
///
/// When the state is `true`, this indicates that the following should happen:
/// This action indicates that the following should happen:
///
/// - Re-probe which widget is under the mouse / any touch instance / any
/// other location picker since widgets may have moved
/// - Redraw the window
#[must_use]
#[derive(Copy, Clone, Debug, Default)]
pub struct ActionMoved(pub bool);

impl BitOr for ActionMoved {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
ActionMoved(self.0 | rhs.0)
}
}

impl BitOrAssign for ActionMoved {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}

impl Deref for ActionMoved {
type Target = bool;
#[inline]
fn deref(&self) -> &bool {
&self.0
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct ActionMoved;

/// Action: widget must be resized
///
/// This type implies that either a local or full-window resize is required.
#[must_use]
#[derive(Copy, Clone, Debug, Default)]
pub struct ActionResize(pub bool);

impl ActionResize {
#[inline]
pub(crate) fn clear(&mut self) {
self.0 = false;
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct ActionResize;

impl BitOr for ActionResize {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
ActionResize(self.0 | rhs.0)
}
}

impl BitOrAssign for ActionResize {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
/// Action: content must be redrawn
#[must_use]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct ActionRedraw;

impl Deref for ActionResize {
type Target = bool;
#[inline]
fn deref(&self) -> &bool {
&self.0
}
}
/// Action: close window
#[must_use]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct ActionClose;

bitflags! {
/// Action: configuration data updates must be applied
Expand All @@ -92,31 +50,10 @@ bitflags! {
}
}

bitflags! {
/// Action required after processing
///
/// Some methods operate directly on a context ([`ConfigCx`] or [`EventCx`])
/// while others don't reqiure a context but do require that some *action*
/// is performed afterwards. This enum is used to convey that action.
///
/// A `WindowAction` produced at run-time should be passed to a context, usually
/// via [`EventState::action`] (to associate the `WindowAction` with a widget)
/// or [`EventState::window_action`] (if no particular widget is relevant).
///
/// A `WindowAction` produced before starting the GUI may be discarded, for
/// example: `let _ = runner.config_mut().font.set_size(24.0);`.
///
/// Two `WindowAction` values may be combined via bit-or (`a | b`).
#[must_use]
#[derive(Copy, Clone, Debug, Default)]
pub struct WindowAction: u32 {
/// The whole window requires redrawing
///
/// See also [`EventState::redraw`].
const REDRAW = 1 << 0;
/// The current window should be closed
///
/// See also [`EventState::exit`] which closes the UI (all windows).
const CLOSE = 1 << 30;
}
/// Set of actions which may affect a window
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub(crate) struct WindowActions {
pub resize: Option<ActionResize>,
pub redraw: Option<ActionRedraw>,
pub close: Option<ActionClose>,
}
11 changes: 6 additions & 5 deletions crates/kas-core/src/core/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,15 @@ pub trait Events: Widget + Sized {
/// locally and should implement this method to do so
/// (thus avoiding the need for a full-window resize).
///
/// Return `ActionResize(true)` if further resizing is needed, or
/// `ActionResize(false)` if resizing is complete.
/// Return `Some(ActionResize)` if further resizing is needed, or `None` if
/// resizing is complete.
///
/// The default implementation simply returns `ActionResize(true)`.
/// The default implementation simply returns `Some(ActionResize)`.
#[inline]
fn handle_resize(&mut self, cx: &mut ConfigCx, data: &Self::Data) -> ActionResize {
#[must_use]
fn handle_resize(&mut self, cx: &mut ConfigCx, data: &Self::Data) -> Option<ActionResize> {
let _ = (cx, data);
ActionResize(true)
Some(ActionResize)
}

/// Handler for scrolling
Expand Down
6 changes: 3 additions & 3 deletions crates/kas-core/src/core/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn _update<W: Events>(widget: &mut W, cx: &mut ConfigCx, data: &W::Data) {
cx.update(node);
}

if *cx.resize && widget.status().is_sized() {
if cx.resize.is_some() && widget.status().is_sized() {
cx.resize = widget.handle_resize(cx, data);
}
}
Expand Down Expand Up @@ -96,7 +96,7 @@ pub fn _send<W: Events>(
);
}

if *cx.resize {
if cx.resize.is_some() {
debug_assert!(widget.status().is_sized());
cx.resize = widget.handle_resize(cx, data);
}
Expand Down Expand Up @@ -144,7 +144,7 @@ pub fn _replay<W: Events>(widget: &mut W, cx: &mut EventCx, data: &<W as Widget>
);
}

if *cx.resize && widget.status().is_sized() {
if cx.resize.is_some() && widget.status().is_sized() {
cx.resize = widget.handle_resize(cx, data);
}

Expand Down
23 changes: 16 additions & 7 deletions crates/kas-core/src/event/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,11 @@ impl ScrollComponent {
/// - `content_size`: size of scroll region on the inside (usually larger)
///
/// Returns an [`ActionMoved`] indicating whether the scroll offset changed.
pub fn set_sizes(&mut self, window_size: Size, content_size: Size) -> ActionMoved {
#[must_use]
pub fn set_sizes(&mut self, window_size: Size, content_size: Size) -> Option<ActionMoved> {
let max_offset = (Offset::conv(content_size) - Offset::conv(window_size)).max(Offset::ZERO);
if max_offset == self.max_offset {
return ActionMoved(false);
return None;
}
self.max_offset = max_offset;
self.set_offset(self.offset)
Expand All @@ -212,14 +213,15 @@ impl ScrollComponent {
///
/// Also cancels any kinetic scrolling, but only if `offset` is not equal
/// to the current offset.
pub fn set_offset(&mut self, offset: Offset) -> ActionMoved {
#[must_use]
pub fn set_offset(&mut self, offset: Offset) -> Option<ActionMoved> {
let offset = offset.clamp(Offset::ZERO, self.max_offset);
if offset == self.offset {
ActionMoved(false)
None
} else {
self.kinetic.stop();
self.offset = offset;
ActionMoved(true)
Some(ActionMoved)
}
}

Expand All @@ -231,7 +233,13 @@ impl ScrollComponent {
/// - `window_rect`: the rect of the scroll window
///
/// Sets [`Scroll::Rect`] to ensure correct scrolling of parents.
pub fn focus_rect(&mut self, cx: &mut EventCx, rect: Rect, window_rect: Rect) -> ActionMoved {
#[must_use]
pub fn focus_rect(
&mut self,
cx: &mut EventCx,
rect: Rect,
window_rect: Rect,
) -> Option<ActionMoved> {
let action = self.self_focus_rect(rect, window_rect);
cx.set_scroll(Scroll::Rect(rect - self.offset));
action
Expand All @@ -243,7 +251,8 @@ impl ScrollComponent {
/// [`EventCx::set_scroll`], thus will not affect ancestors.
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
pub fn self_focus_rect(&mut self, rect: Rect, window_rect: Rect) -> ActionMoved {
#[must_use]
pub fn self_focus_rect(&mut self, rect: Rect, window_rect: Rect) -> Option<ActionMoved> {
self.kinetic.stop();
let max_vis = rect.pos - window_rect.pos;
let extra_size = Offset::conv(rect.size) - Offset::conv(window_rect.size);
Expand Down
18 changes: 9 additions & 9 deletions crates/kas-core/src/event/config_cx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use crate::event::EventState;
use crate::text::format::FormattableText;
use crate::theme::{SizeCx, Text, ThemeSize};
use crate::{ActionResize, Id, Node};
use crate::{ActionRedraw, ActionResize, Id, Node};
use std::any::TypeId;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
Expand All @@ -23,8 +23,8 @@ use std::ops::{Deref, DerefMut};
pub struct ConfigCx<'a> {
pub(super) theme: &'a dyn ThemeSize,
pub(crate) state: &'a mut EventState,
pub(crate) resize: ActionResize,
pub(crate) redraw: bool,
pub(crate) resize: Option<ActionResize>,
pub(crate) redraw: Option<ActionRedraw>,
}

impl<'a> ConfigCx<'a> {
Expand All @@ -35,8 +35,8 @@ impl<'a> ConfigCx<'a> {
ConfigCx {
theme: sh,
state: ev,
resize: ActionResize(false),
redraw: false,
resize: None,
redraw: None,
}
}

Expand Down Expand Up @@ -64,7 +64,7 @@ impl<'a> ConfigCx<'a> {
// (Except redraw: this doesn't matter.)
let start_resize = std::mem::take(&mut self.resize);
widget._configure(self, id);
self.resize |= start_resize;
self.resize = self.resize.or(start_resize);
}

/// Update a widget
Expand All @@ -77,7 +77,7 @@ impl<'a> ConfigCx<'a> {
// (Except redraw: this doesn't matter.)
let start_resize = std::mem::take(&mut self.resize);
widget._update(self);
self.resize |= start_resize;
self.resize = self.resize.or(start_resize);
}

/// Configure a text object
Expand Down Expand Up @@ -126,7 +126,7 @@ impl<'a> ConfigCx<'a> {
/// during the traversal unwind if possible.
#[inline]
pub fn redraw(&mut self) {
self.redraw = true;
self.redraw = Some(ActionRedraw);
}

/// Require that the current widget (and its descendants) be resized
Expand All @@ -136,7 +136,7 @@ impl<'a> ConfigCx<'a> {
/// during the traversal unwind if possible.
#[inline]
pub fn resize(&mut self) {
self.resize = ActionResize(true);
self.resize = Some(ActionResize);
}
}

Expand Down
Loading