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}