kas_core/
messages.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! # Standard messages
7//!
8//! These are pre-defined message types which may be sent to a widget via
9//! [`EventCx::push`] or [`EventState::send`] in order to trigger some action.
10//!
11//! [`Erased`] is the type-erasure container allowing any type supporting
12//! [`Any`] + [`Debug`] to be sent or placed on the message stack.
13
14use crate::event::PhysicalKey;
15#[allow(unused)] use crate::event::{EventCx, EventState};
16use crate::geom::Offset;
17use crate::window::Icon;
18use std::any::Any;
19use std::fmt::Debug;
20
21/// Synthetically trigger a "click" action
22///
23/// This message may be used to trigger a "click" action, for example to press a
24/// button or toggle a check box state.
25///
26/// Payload: the key press which caused this message to be emitted, if any.
27/// (This allows a visual state change to be bound to the key's release.)
28#[derive(Copy, Clone, Debug)]
29pub struct Activate(pub Option<PhysicalKey>);
30
31/// Increment value by one step
32#[derive(Copy, Clone, Debug)]
33pub struct IncrementStep;
34
35/// Decrement value by one step
36#[derive(Copy, Clone, Debug)]
37pub struct DecrementStep;
38
39/// Set an input value from `f64`
40///
41/// This message may be used to set a numeric value to an input field.
42#[derive(Copy, Clone, Debug)]
43pub struct SetValueF64(pub f64);
44
45/// Set an input value from a `String`
46///
47/// This message may be used to set a text value to an input field.
48#[derive(Clone, Debug)]
49pub struct SetValueText(pub String);
50
51/// Replace selected text in an input value
52///
53/// This acts the same as typing or pasting the text: replace an existing
54/// selection or insert at the cursor position.
55#[derive(Clone, Debug)]
56pub struct ReplaceSelectedText(pub String);
57
58/// Set an index
59#[derive(Clone, Debug)]
60pub struct SetIndex(pub usize);
61
62/// Expand a collapsible list or open a menu
63#[derive(Clone, Debug)]
64pub struct Expand;
65
66/// Collapse a collapsible list or close a menu
67#[derive(Clone, Debug)]
68pub struct Collapse;
69
70/// Request selection of the sender
71///
72/// This is only useful when pushed by a child widget or sent to a child widget
73/// for usage by a parent container supporting selection. The recipient must use
74/// [`EventCx::last_child`] to determine the selection target.
75///
76/// Example: a list supports selection; a child emits this to cause itself to be selected.
77#[derive(Clone, Debug)]
78pub struct Select;
79
80/// Set the scroll offset
81#[derive(Clone, Debug)]
82pub struct SetScrollOffset(pub Offset);
83
84/// Change the window's title
85#[derive(Clone, Debug)]
86pub struct SetWindowTitle(pub String);
87/// Change the window's icon
88#[derive(Clone, Debug)]
89pub struct SetWindowIcon(pub Option<Icon>);
90
91trait AnyDebug: Any + Debug {}
92impl<T: Any + Debug> AnyDebug for T {}
93
94/// A type-erased message
95///
96/// This is vaguely a wrapper over `Box<dyn (Any + Debug)>`, except that Rust
97/// doesn't (yet) support multi-trait objects.
98#[derive(Debug)]
99pub struct Erased(Box<dyn AnyDebug>);
100
101impl Erased {
102    /// Construct
103    pub fn new<V: Any + Debug>(v: V) -> Self {
104        Erased(Box::new(v))
105    }
106
107    /// Returns `true` if the inner type is the same as `T`.
108    pub fn is<T: 'static>(&self) -> bool {
109        (&*self.0 as &dyn Any).is::<T>()
110    }
111
112    /// Attempt to downcast self to a concrete type.
113    pub fn downcast<T: 'static>(self) -> Result<Box<T>, Box<dyn Any>> {
114        (self.0 as Box<dyn Any>).downcast::<T>()
115    }
116
117    /// Returns some reference to the inner value if it is of type `T`, or `None` if it isn’t.
118    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
119        (&*self.0 as &dyn Any).downcast_ref::<T>()
120    }
121
122    pub(crate) fn debug(&self) -> &dyn Debug {
123        &self.0
124    }
125}
126
127trait AnySendDebug: AnyDebug + Send {}
128impl<T: Any + Send + Debug> AnySendDebug for T {}
129
130/// Like Erased, but supporting Send
131#[derive(Debug)]
132pub(crate) struct SendErased(Box<dyn AnySendDebug>);
133
134impl SendErased {
135    /// Construct
136    pub fn new<V: Any + Send + Debug>(v: V) -> Self {
137        SendErased(Box::new(v))
138    }
139
140    /// Convert to [`Erased`]
141    pub fn into_erased(self) -> Erased {
142        Erased(self.0)
143    }
144}