1use zng_txt::Txt;
4use zng_view_api::access::AccessCmd;
5
6pub use zng_view_api::access::ScrollCmd;
7
8use crate::{
9 event::{event, event_args},
10 widget::{WidgetId, info::WidgetPath},
11 window::{WINDOWS_APP, WindowId},
12};
13
14pub(super) fn on_access_init(window_id: WindowId) {
15 let args = AccessInitedArgs::now(window_id);
16 ACCESS_INITED_EVENT.notify(args)
17}
18
19pub(super) fn on_access_deinit(window_id: WindowId) {
20 let args = AccessDeinitedArgs::now(window_id);
21 ACCESS_DEINITED_EVENT.notify(args)
22}
23
24fn find_wgt(window_id: WindowId, widget_id: WidgetId) -> Option<WidgetPath> {
25 WINDOWS_APP.widget_tree(window_id)?.get(widget_id).map(|w| w.path())
26}
27
28pub(super) fn on_access_command(window_id: WindowId, widget_id: WidgetId, command: AccessCmd) {
29 let widget = match find_wgt(window_id, widget_id) {
30 Some(w) => w,
31 None => return,
32 };
33 match command {
34 AccessCmd::Click(primary) => {
35 let args = AccessClickArgs::now(widget, primary);
36 ACCESS_CLICK_EVENT.notify(args)
37 }
38 AccessCmd::Focus(focus) => {
39 let args = AccessFocusArgs::now(widget, focus);
40 ACCESS_FOCUS_EVENT.notify(args)
41 }
42 AccessCmd::FocusNavOrigin => {
43 let args = AccessFocusNavOriginArgs::now(widget);
44 ACCESS_FOCUS_NAV_ORIGIN_EVENT.notify(args)
45 }
46 AccessCmd::SetExpanded(expanded) => {
47 let args = AccessExpanderArgs::now(widget, expanded);
48 ACCESS_EXPANDER_EVENT.notify(args)
49 }
50 AccessCmd::Increment(inc) => {
51 let args = AccessIncrementArgs::now(widget, inc);
52 ACCESS_INCREMENT_EVENT.notify(args)
53 }
54 AccessCmd::SetToolTipVis(vis) => {
55 let args = AccessToolTipArgs::now(widget, vis);
56 ACCESS_TOOLTIP_EVENT.notify(args)
57 }
58 AccessCmd::ReplaceSelectedText(s) => {
59 let args = AccessTextArgs::now(widget, s, true);
60 ACCESS_TEXT_EVENT.notify(args)
61 }
62 AccessCmd::Scroll(s) => {
63 let args = AccessScrollArgs::now(widget, s);
64 ACCESS_SCROLL_EVENT.notify(args)
65 }
66 AccessCmd::SelectText {
67 start: (start_wgt, start_idx),
68 caret: (caret_wgt, caret_idx),
69 } => {
70 let start_wgt = match find_wgt(window_id, WidgetId::from_raw(start_wgt.0)) {
71 Some(w) => w,
72 None => return,
73 };
74 let caret_wgt = match find_wgt(window_id, WidgetId::from_raw(caret_wgt.0)) {
75 Some(w) => w,
76 None => return,
77 };
78 let args = AccessSelectionArgs::now((start_wgt, start_idx), (caret_wgt, caret_idx));
79 ACCESS_SELECTION_EVENT.notify(args)
80 }
81 AccessCmd::SetString(s) => {
82 let args = AccessTextArgs::now(widget, s, false);
83 ACCESS_TEXT_EVENT.notify(args)
84 }
85 AccessCmd::SetNumber(n) => {
86 let args = AccessNumberArgs::now(widget, n);
87 ACCESS_NUMBER_EVENT.notify(args)
88 }
89 a => {
90 tracing::warn!("access command `{a:?}` not implemented");
91 }
92 }
93}
94
95event_args! {
96 pub struct AccessInitedArgs {
98 pub window_id: WindowId,
100
101 ..
102
103 fn is_in_target(&self, _id: WidgetId) -> bool {
105 true
106 }
107 }
108
109 pub struct AccessDeinitedArgs {
111 pub window_id: WindowId,
113
114 ..
115
116 fn is_in_target(&self, _id: WidgetId) -> bool {
118 true
119 }
120 }
121
122 pub struct AccessClickArgs {
124 pub target: WidgetPath,
126
127 pub is_primary: bool,
131
132 ..
133
134 fn is_in_target(&self, id: WidgetId) -> bool {
136 self.target.contains(id)
137 }
138 }
139
140 pub struct AccessFocusArgs {
142 pub target: WidgetPath,
144
145 pub focus: bool,
149
150 ..
151
152 fn is_in_target(&self, id: WidgetId) -> bool {
154 self.target.contains(id)
155 }
156 }
157
158 pub struct AccessFocusNavOriginArgs {
160 pub target: WidgetPath,
162
163 ..
164
165 fn is_in_target(&self, id: WidgetId) -> bool {
167 self.target.contains(id)
168 }
169 }
170
171 pub struct AccessExpanderArgs {
173 pub target: WidgetPath,
175
176 pub expanded: bool,
178
179 ..
180
181 fn is_in_target(&self, id: WidgetId) -> bool {
183 self.target.contains(id)
184 }
185 }
186
187 pub struct AccessIncrementArgs {
189 pub target: WidgetPath,
191
192 pub delta: i32,
196
197 ..
198
199 fn is_in_target(&self, id: WidgetId) -> bool {
201 self.target.contains(id)
202 }
203 }
204
205 pub struct AccessToolTipArgs {
207 pub target: WidgetPath,
209
210 pub visible: bool,
212
213 ..
214
215 fn is_in_target(&self, id: WidgetId) -> bool {
217 self.target.contains(id)
218 }
219 }
220
221 pub struct AccessScrollArgs {
223 pub target: WidgetPath,
225
226 pub command: ScrollCmd,
228
229 ..
230
231 fn is_in_target(&self, id: WidgetId) -> bool {
233 self.target.contains(id)
234 }
235 }
236
237 pub struct AccessTextArgs {
239 pub target: WidgetPath,
241
242 pub txt: Txt,
244
245 pub selection_only: bool,
250
251 ..
252
253 fn is_in_target(&self, id: WidgetId) -> bool {
255 self.target.contains(id)
256 }
257 }
258
259 pub struct AccessNumberArgs {
261 pub target: WidgetPath,
263
264 pub num: f64,
266
267 ..
268
269 fn is_in_target(&self, id: WidgetId) -> bool {
271 self.target.contains(id)
272 }
273 }
274
275 pub struct AccessSelectionArgs {
277 pub start: (WidgetPath, usize),
281 pub caret: (WidgetPath, usize),
285
286 ..
287
288 fn is_in_target(&self, id: WidgetId) -> bool {
290 self.start.0.contains(id) || self.caret.0.contains(id)
291 }
292 }
293}
294impl AccessClickArgs {
295 pub fn is_context(&self) -> bool {
297 !self.is_primary
298 }
299}
300
301event! {
302 pub static ACCESS_INITED_EVENT: AccessInitedArgs;
304
305 pub static ACCESS_DEINITED_EVENT: AccessDeinitedArgs;
307
308 pub static ACCESS_CLICK_EVENT: AccessClickArgs;
310
311 pub static ACCESS_FOCUS_EVENT: AccessFocusArgs;
313
314 pub static ACCESS_FOCUS_NAV_ORIGIN_EVENT: AccessFocusNavOriginArgs;
316
317 pub static ACCESS_EXPANDER_EVENT: AccessExpanderArgs;
319
320 pub static ACCESS_INCREMENT_EVENT: AccessIncrementArgs;
322
323 pub static ACCESS_TOOLTIP_EVENT: AccessToolTipArgs;
325
326 pub static ACCESS_SCROLL_EVENT: AccessScrollArgs;
328
329 pub static ACCESS_TEXT_EVENT: AccessTextArgs;
331
332 pub static ACCESS_NUMBER_EVENT: AccessNumberArgs;
334
335 pub static ACCESS_SELECTION_EVENT: AccessSelectionArgs;
337}
338
339pub struct ACCESS;
341
342impl ACCESS {
343 pub fn click(&self, widget: WidgetPath, is_primary: bool) {
347 ACCESS_CLICK_EVENT.notify(AccessClickArgs::now(widget, is_primary));
348 }
349
350 pub fn show_tooltip(&self, widget: WidgetPath) {
354 ACCESS_TOOLTIP_EVENT.notify(AccessToolTipArgs::now(widget, true));
355 }
356
357 pub fn hide_tooltip(&self, widget: WidgetPath) {
359 ACCESS_TOOLTIP_EVENT.notify(AccessToolTipArgs::now(widget, false));
360 }
361}