1use super::ink_events::InkEvent;
2use super::{InkPoint, InkPresenter};
3use ferroui_base::input::PointerType;
4use ferroui_base::reactive::IDisposable;
5use std::cell::Cell;
6use std::rc::{Rc, Weak};
7
8bitflags::bitflags! {
9 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11 pub struct CoreInputDeviceTypes: u32 {
12 const NONE = 0;
13 const TOUCH = 1;
14 const PEN = 2;
15 const MOUSE = 4;
16 }
17}
18
19#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
20#[repr(i32)]
21pub enum InkInputProcessingMode {
22 None = 0,
23 #[default]
24 Inking = 1,
25 Erasing = 2,
26}
27
28#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
29#[repr(i32)]
30pub enum InkInputRightDragAction {
31 #[default]
32 LeaveUnprocessed = 0,
33 AllowProcessing = 1,
34}
35
36#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
37#[repr(i32)]
38pub enum InkHighContrastAdjustment {
39 #[default]
40 UseSystemColorsWhenNecessary = 0,
41 UseSystemColors = 1,
42 UseOriginalColors = 2,
43}
44
45#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
46#[repr(i32)]
47pub enum InkPresenterPredefinedConfiguration {
48 #[default]
49 SimpleSinglePointer = 0,
50 SimpleMultiplePointer = 1,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
54pub enum InkPointerPhase {
55 Entered,
56 Hovered,
57 Exited,
58 Pressed,
59 Moved,
60 Released,
61 Lost,
62}
63
64#[derive(Clone, Debug, PartialEq)]
67pub struct InkPointerEventArgs {
68 pub pointer_id: i32,
69 pub device_type: PointerType,
70 pub point: InkPoint,
71 pub is_barrel_button_pressed: bool,
72 pub is_eraser: bool,
73 pub is_right_button_pressed: bool,
74 handled: Rc<Cell<bool>>,
75}
76
77macro_rules! identity_equality {
78 ($($type:ty),* $(,)?) => { $(impl PartialEq for $type {
79 fn eq(&self, other: &Self) -> bool { std::ptr::eq(self, other) }
80 })* };
81}
82identity_equality!(
83 InkInputProcessingConfiguration,
84 InkInputConfiguration,
85 InkStrokeInput,
86 InkUnprocessedInput
87);
88
89impl InkPointerEventArgs {
90 pub fn new(pointer_id: i32, device_type: PointerType, point: InkPoint) -> Self {
91 Self {
92 pointer_id,
93 device_type,
94 point,
95 is_barrel_button_pressed: false,
96 is_eraser: false,
97 is_right_button_pressed: false,
98 handled: Rc::new(Cell::new(false)),
99 }
100 }
101 pub fn handled(&self) -> bool {
102 self.handled.get()
103 }
104 pub fn set_handled(&self, value: bool) {
105 self.handled.set(value);
106 }
107}
108
109pub struct InkInputProcessingConfiguration {
110 presenter: Weak<InkPresenter>,
111 mode: Cell<InkInputProcessingMode>,
112 right_drag_action: Cell<InkInputRightDragAction>,
113}
114
115impl InkInputProcessingConfiguration {
116 pub(crate) fn new(presenter: Weak<InkPresenter>) -> Self {
117 Self {
118 presenter,
119 mode: Cell::new(InkInputProcessingMode::Inking),
120 right_drag_action: Cell::new(InkInputRightDragAction::LeaveUnprocessed),
121 }
122 }
123 pub fn mode(&self) -> InkInputProcessingMode {
124 self.mode.get()
125 }
126 pub fn set_mode(&self, value: InkInputProcessingMode) {
127 if self.mode.replace(value) != value {
128 if let Some(p) = self.presenter.upgrade() {
129 p.cancel_all();
130 }
131 }
132 }
133 pub fn right_drag_action(&self) -> InkInputRightDragAction {
134 self.right_drag_action.get()
135 }
136 pub fn set_right_drag_action(&self, value: InkInputRightDragAction) {
137 if self.right_drag_action.replace(value) != value {
138 if let Some(p) = self.presenter.upgrade() {
139 p.cancel_all();
140 }
141 }
142 }
143}
144
145pub struct InkInputConfiguration {
146 primary_barrel: Cell<bool>,
147 eraser: Cell<bool>,
148}
149
150impl Default for InkInputConfiguration {
151 fn default() -> Self {
152 Self {
153 primary_barrel: Cell::new(true),
154 eraser: Cell::new(true),
155 }
156 }
157}
158
159impl InkInputConfiguration {
160 pub fn is_primary_barrel_button_input_enabled(&self) -> bool {
161 self.primary_barrel.get()
162 }
163 pub fn set_is_primary_barrel_button_input_enabled(&self, value: bool) {
164 self.primary_barrel.set(value);
165 }
166 pub fn is_eraser_input_enabled(&self) -> bool {
167 self.eraser.get()
168 }
169 pub fn set_is_eraser_input_enabled(&self, value: bool) {
170 self.eraser.set(value);
171 }
172}
173
174pub struct InkStrokeInput {
176 presenter: Weak<InkPresenter>,
177 pub(crate) started: InkEvent<InkPointerEventArgs>,
178 pub(crate) continued: InkEvent<InkPointerEventArgs>,
179 pub(crate) ended: InkEvent<InkPointerEventArgs>,
180 pub(crate) canceled: InkEvent<InkPointerEventArgs>,
181}
182
183impl InkStrokeInput {
184 pub(crate) fn new(presenter: Weak<InkPresenter>) -> Self {
185 Self {
186 presenter,
187 started: InkEvent::default(),
188 continued: InkEvent::default(),
189 ended: InkEvent::default(),
190 canceled: InkEvent::default(),
191 }
192 }
193 pub fn ink_presenter(&self) -> Option<Rc<InkPresenter>> {
194 self.presenter.upgrade()
195 }
196 pub fn stroke_started(
197 &self,
198 handler: impl Fn(&InkPointerEventArgs) + 'static,
199 ) -> Rc<dyn IDisposable> {
200 self.started.subscribe(handler)
201 }
202 pub fn stroke_continued(
203 &self,
204 handler: impl Fn(&InkPointerEventArgs) + 'static,
205 ) -> Rc<dyn IDisposable> {
206 self.continued.subscribe(handler)
207 }
208 pub fn stroke_ended(
209 &self,
210 handler: impl Fn(&InkPointerEventArgs) + 'static,
211 ) -> Rc<dyn IDisposable> {
212 self.ended.subscribe(handler)
213 }
214 pub fn stroke_canceled(
215 &self,
216 handler: impl Fn(&InkPointerEventArgs) + 'static,
217 ) -> Rc<dyn IDisposable> {
218 self.canceled.subscribe(handler)
219 }
220}
221
222pub struct InkUnprocessedInput {
223 presenter: Weak<InkPresenter>,
224 entered: InkEvent<InkPointerEventArgs>,
225 hovered: InkEvent<InkPointerEventArgs>,
226 exited: InkEvent<InkPointerEventArgs>,
227 pressed: InkEvent<InkPointerEventArgs>,
228 moved: InkEvent<InkPointerEventArgs>,
229 released: InkEvent<InkPointerEventArgs>,
230 lost: InkEvent<InkPointerEventArgs>,
231}
232
233impl InkUnprocessedInput {
234 pub(crate) fn new(presenter: Weak<InkPresenter>) -> Self {
235 Self {
236 presenter,
237 entered: InkEvent::default(),
238 hovered: InkEvent::default(),
239 exited: InkEvent::default(),
240 pressed: InkEvent::default(),
241 moved: InkEvent::default(),
242 released: InkEvent::default(),
243 lost: InkEvent::default(),
244 }
245 }
246 pub fn ink_presenter(&self) -> Option<Rc<InkPresenter>> {
247 self.presenter.upgrade()
248 }
249 pub fn pointer_entered(
250 &self,
251 h: impl Fn(&InkPointerEventArgs) + 'static,
252 ) -> Rc<dyn IDisposable> {
253 self.entered.subscribe(h)
254 }
255 pub fn pointer_hovered(
256 &self,
257 h: impl Fn(&InkPointerEventArgs) + 'static,
258 ) -> Rc<dyn IDisposable> {
259 self.hovered.subscribe(h)
260 }
261 pub fn pointer_exited(
262 &self,
263 h: impl Fn(&InkPointerEventArgs) + 'static,
264 ) -> Rc<dyn IDisposable> {
265 self.exited.subscribe(h)
266 }
267 pub fn pointer_pressed(
268 &self,
269 h: impl Fn(&InkPointerEventArgs) + 'static,
270 ) -> Rc<dyn IDisposable> {
271 self.pressed.subscribe(h)
272 }
273 pub fn pointer_moved(&self, h: impl Fn(&InkPointerEventArgs) + 'static) -> Rc<dyn IDisposable> {
274 self.moved.subscribe(h)
275 }
276 pub fn pointer_released(
277 &self,
278 h: impl Fn(&InkPointerEventArgs) + 'static,
279 ) -> Rc<dyn IDisposable> {
280 self.released.subscribe(h)
281 }
282 pub fn pointer_lost(&self, h: impl Fn(&InkPointerEventArgs) + 'static) -> Rc<dyn IDisposable> {
283 self.lost.subscribe(h)
284 }
285 pub(crate) fn raise(&self, phase: InkPointerPhase, e: &InkPointerEventArgs) {
286 match phase {
287 InkPointerPhase::Entered => &self.entered,
288 InkPointerPhase::Hovered => &self.hovered,
289 InkPointerPhase::Exited => &self.exited,
290 InkPointerPhase::Pressed => &self.pressed,
291 InkPointerPhase::Moved => &self.moved,
292 InkPointerPhase::Released => &self.released,
293 InkPointerPhase::Lost => &self.lost,
294 }
295 .raise(e);
296 }
297}