Continued implementation work on CloseWindowCommand and Commands in general.

This commit is contained in:
Well 2021-06-24 01:21:46 -03:00
parent fe598d84e4
commit 79142cf332
6 changed files with 95 additions and 13 deletions

View File

@ -58,6 +58,37 @@ macro_rules! command {
pub fn notify(self, events: &mut $crate::event::Events, parameter: Option<std::rc::Rc<dyn std::any::Any>>) {
<Self as $crate::event::Event>::notify(self, events, $crate::command::CommandArgs::now(parameter));
}
/// Gets a read-only variable that indicates if the command has at least one enabled handler.
///
/// When this is `false` but [`has_handlers`](Self::has_handlers) is `true` the command can be considered
/// *relevant* in the current app state but not enabled, associated command trigger widgets should be
/// visible but disabled.
#[inline]
#[allow(unused)]
pub fn enabled(self) -> $crate::var::ReadOnlyVar<bool, $crate::var::RcVar<bool>> {
<Self as $crate::command::Command>::enabled(self)
}
/// Gets a read-only variable that indicates if the command has at least one handler.
///
/// When this is `false` the command can be considered *not relevant* in the current app state
/// and associated command trigger widgets can be hidden.
#[inline]
#[allow(unused)]
pub fn has_handlers(self) -> $crate::var::ReadOnlyVar<bool, $crate::var::RcVar<bool>> {
<Self as $crate::command::Command>::has_handlers(self)
}
/// Create a new handle to this command.
///
/// A handle indicates that there is an active *handler* for the event, the handle can also
/// be used to set the [`enabled`](Self::enabled) state.
#[inline]
#[allow(unused)]
pub fn new_handle<Evs: $crate::event::WithEvents>(self, events: &mut Evs) -> $crate::command::CommandHandle {
<Self as $crate::command::Command>::new_handle(self, events)
}
}
impl $crate::event::Event for $Command {
type Args = $crate::command::CommandArgs;
@ -99,7 +130,7 @@ macro_rules! command {
}
#[inline]
fn new_handle(self, events: &mut $crate::event::Events) -> $crate::command::CommandHandle {
fn new_handle<Evs: $crate::event::WithEvents>(self, events: &mut Evs) -> $crate::command::CommandHandle {
Self::COMMAND.with(|c| c.new_handle(events, &Self::COMMAND))
}
@ -145,7 +176,7 @@ pub trait Command: Event<Args = CommandArgs> {
///
/// A handle indicates that there is an active *handler* for the event, the handle can also
/// be used to set the [`enabled`](Self::enabled) state.
fn new_handle(self, events: &mut Events) -> CommandHandle;
fn new_handle<Evs: WithEvents>(self, events: &mut Evs) -> CommandHandle;
/// Gets a [`AnyCommand`] that represents this command.
fn as_any(self) -> AnyCommand;
@ -185,8 +216,8 @@ impl AnyCommand {
/// Schedule an event update for the command represented by `self`.
#[inline]
pub fn notify(self, events: &mut Events, args: CommandArgs) {
Event::notify(self, events, args)
pub fn notify(self, events: &mut Events, parameter: Option<Rc<dyn Any>>) {
Event::notify(self, events, CommandArgs::now(parameter))
}
}
impl fmt::Debug for AnyCommand {
@ -233,7 +264,7 @@ impl Command for AnyCommand {
self.0.with(|c| c.has_handlers_value())
}
fn new_handle(self, events: &mut Events) -> CommandHandle {
fn new_handle<Evs: WithEvents>(self, events: &mut Evs) -> CommandHandle {
self.0.with(|c| c.new_handle(events, self.0))
}
@ -321,6 +352,14 @@ impl CommandHandle {
};
}
}
/// Returns a dummy [`CommandHandle`] that is not connected to any command.
pub fn dummy() -> Self {
CommandHandle {
handle: Handle::dummy(AtomicUsize::new(0)),
local_enabled: Cell::new(false),
}
}
}
impl Drop for CommandHandle {
fn drop(&mut self) {
@ -361,10 +400,10 @@ impl CommandValue {
self.enabled.set_ne(vars, self.enabled_value());
}
pub fn new_handle(&self, events: &mut Events, key: &'static LocalKey<CommandValue>) -> CommandHandle {
if self.registered.get() {
pub fn new_handle<Evs: WithEvents>(&self, events: &mut Evs, key: &'static LocalKey<CommandValue>) -> CommandHandle {
if !self.registered.get() {
self.registered.set(true);
events.register_command(AnyCommand(key));
events.with_events(|e| e.register_command(AnyCommand(key)));
}
CommandHandle {
handle: self.handle.reanimate(),

View File

@ -994,6 +994,14 @@ impl Events {
retain
});
}
/// Commands that had handles generated in this app.
///
/// When [`Command::new_handle`] is called for the first time in an app, the command gets regitered here.
#[inline]
pub fn commands(&self) -> impl Iterator<Item = AnyCommand> + '_ {
self.commands.values().copied()
}
}
/// Represents a type that can provide access to a [`Events`] inside the window of function call.

View File

@ -804,6 +804,15 @@ impl AppExtension for GestureManager {
args.target.clone(),
),
);
} else {
let command = ctx
.events
.commands()
.find(|c| c.enabled_value() && c.shortcut().get(ctx.vars).0.contains(&args.shortcut));
if let Some(command) = command {
command.notify(ctx.events, None);
args.stop_propagation()
}
}
}
}

View File

@ -717,8 +717,8 @@ where
/// the input is the same syntax.
///
/// The handler generates a future for each event, the future is polled immediately if it does not finish it is scheduled
/// to update in [`on_pre_update`](crate::context::Updates::on_pre_update). Note that this means
/// [`stop_propagation`](crate::event::EventArgs::stop_propagation) can only be meaningfully called before the first `.await`,
/// to update in [`on_pre_update`](crate::context::Updates::on_pre_update). Note that this means
/// [`stop_propagation`](crate::event::EventArgs::stop_propagation) can only be meaningfully called before the first `.await`,
/// after the event has already propagated.
///
/// # Examples

View File

@ -16,9 +16,9 @@
//!
//! # Handlers
//!
//! A property event handler is any type that implements [`WidgetHandler`](crate::core::handler::WidgetHandler), usually they are a
//! closure declared with the assistance of a macro, the widget handler macros are [`hn!`](crate::core::handler::hn!),
//! [`hn_once!`](crate::core::handler::hn_once!), [`async_hn!`](crate::core::handler::async_hn!) and
//! A property event handler is any type that implements [`WidgetHandler`](crate::core::handler::WidgetHandler), usually they are a
//! closure declared with the assistance of a macro, the widget handler macros are [`hn!`](crate::core::handler::hn!),
//! [`hn_once!`](crate::core::handler::hn_once!), [`async_hn!`](crate::core::handler::async_hn!) and
//! [`async_hn_once!`](crate::core::handler::async_hn_once!).
//!
//! ```

View File

@ -24,6 +24,11 @@ use crate::properties::events::window::*;
/// See [`run_window`](crate::core::window::AppRunWindow::run_window) for more details.
#[widget($crate::widgets::window)]
pub mod window {
use zero_ui_core::window::WindowsExt;
use crate::core::command::CommandHandle;
use crate::properties::commands::CloseWindowCommand;
use super::*;
inherit!(container);
@ -259,6 +264,27 @@ pub mod window {
on_pre_redraw: impl FnMut(&mut RedrawArgs) + 'static,
on_redraw: impl FnMut(&mut RedrawArgs) + 'static,
) -> Window {
struct OnCloseWindowNode<C: UiNode> {
child: C,
handle: CommandHandle,
}
#[impl_ui_node(child)]
impl<C: UiNode> UiNode for OnCloseWindowNode<C> {
fn init(&mut self, ctx: &mut WidgetContext) {
self.handle = CloseWindowCommand.new_handle(ctx);
self.handle.set_enabled(true);
self.child.init(ctx)
}
fn event<A: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &A) {
if let Some(args) = CloseWindowCommand.update(args) {
let _ = ctx.services.windows().close(ctx.path.window_id());
self.child.event(ctx, args)
} else {
self.child.event(ctx, args)
}
}
}
let child = OnCloseWindowNode{child, handle: CommandHandle::dummy()};
Window::new(
root_id,
start_position,