makepad_widgets/
widget.rs

1use {
2    crate::makepad_draw::*,
3    std::fmt::{Formatter, Debug, Error},
4    std::collections::BTreeMap,
5    std::any::TypeId,
6    std::cell::RefCell,
7    std::rc::Rc
8};
9pub use crate::register_widget;
10
11#[derive(Clone, Copy)]
12pub enum WidgetCache {
13    Yes,
14    No,
15    Clear
16}
17
18#[derive(Clone, Debug, Copy, PartialEq)]
19pub struct WidgetUid(pub u64);
20
21pub trait WidgetDesign {
22}
23
24pub trait Widget: LiveApply {
25    fn handle_widget_event_with(
26        &mut self,
27        _cx: &mut Cx,
28        _event: &Event,
29        _fn_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)
30    ) {}
31    
32    fn handle_widget_event(&mut self, cx: &mut Cx, event: &Event) -> WidgetActions {
33        let mut actions = Vec::new();
34        self.handle_widget_event_with(cx, event, &mut | _, action | {
35            actions.push(action);
36        });
37        actions
38    }
39    
40    fn find_widgets(&mut self, _path: &[LiveId], _cached: WidgetCache, _results: &mut WidgetSet) {
41    }
42    
43    fn widget(&mut self, path: &[LiveId]) -> WidgetRef {
44        let mut results = WidgetSet::default();
45        self.find_widgets(path, WidgetCache::Yes, &mut results);
46        return results.into_first()
47    }
48    
49    fn widgets(&mut self, paths: &[&[LiveId]]) -> WidgetSet {
50        let mut results = WidgetSet::default();
51        for path in paths {
52            self.find_widgets(path, WidgetCache::Yes, &mut results);
53        }
54        results
55    }
56    
57    // fn widget_uid(&self)->WidgetUid;
58    fn widget_uid(&self) -> WidgetUid {return WidgetUid(self as *const _ as *const () as u64)}
59    
60    fn widget_to_data(&self, _cx: &mut Cx, _actions: &WidgetActions, _nodes: &mut LiveNodeVec, _path: &[LiveId]) -> bool {false}
61    fn data_to_widget(&mut self, _cx: &mut Cx, _nodes: &[LiveNode], _path: &[LiveId]) {}
62    
63    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw;
64    fn walk(&mut self, _cx:&mut Cx) -> Walk {Walk::default()}
65    fn redraw(&mut self, _cx: &mut Cx);
66    
67    fn is_visible(&self) -> bool {
68        true
69    }
70    
71    fn draw_widget(&mut self, cx: &mut Cx2d) -> WidgetDraw {
72        let walk = self.walk(cx);
73        self.draw_walk_widget(cx, walk)
74    }
75    
76    fn draw_widget_all(&mut self, cx: &mut Cx2d) {
77        while self.draw_widget(cx).is_hook() {};
78    }
79    
80    fn text(&self) -> String {
81        String::new()
82    }
83    
84    fn set_text(&mut self, _v: &str) {
85    }
86    
87    fn set_text_and_redraw(&mut self, cx: &mut Cx, v: &str) {
88        self.set_text(v);
89        self.redraw(cx);
90    }
91    /*
92    fn create_child(
93        &mut self,
94        _cx: &mut Cx,
95        _live_ptr: LivePtr,
96        _at: CreateAt,
97        _new_id: LiveId,
98        _nodes: &[LiveNode]
99    ) -> WidgetRef {
100        WidgetRef::empty()
101    }
102    
103    fn find_template(&self, _id: &[LiveId; 1]) -> Option<LivePtr> {
104        None
105    }*/
106    
107    fn type_id(&self) -> LiveType where Self: 'static {LiveType::of::<Self>()}
108}
109
110#[derive(Clone, Copy)]
111pub enum CreateAt {
112    Template,
113    Begin,
114    After(LiveId),
115    Before(LiveId),
116    End
117}
118
119pub trait WidgetDrawApi {
120    fn done() -> WidgetDraw {Result::Ok(())}
121    fn hook(arg: WidgetRef) -> WidgetDraw {Result::Err(arg)}
122    fn hook_above() -> WidgetDraw {Result::Err(WidgetRef::empty())}
123    fn is_done(&self) -> bool;
124    fn is_hook(&self) -> bool;
125    fn hook_widget(self) -> Option<WidgetRef>;
126}
127
128impl WidgetDrawApi for WidgetDraw {
129    fn is_done(&self) -> bool {
130        match *self {
131            Result::Ok(_) => true,
132            Result::Err(_) => false
133        }
134    }
135    fn is_hook(&self) -> bool {
136        match *self {
137            Result::Ok(_) => false,
138            Result::Err(_) => true
139        }
140    }
141    fn hook_widget(self) -> Option<WidgetRef> {
142        match self {
143            Result::Ok(_) => None,
144            Result::Err(nd) => Some(nd)
145        }
146    }
147}
148
149/*
150pub type WidgetResult = Result<(), WidgetRef>;
151pub trait WidgetResultApi {
152    fn found(found: WidgetRef) -> WidgetResult {Result::Err(found)}
153    fn not_found() -> WidgetResult {Result::Ok(())}
154    fn into_found(self) -> Option<WidgetRef>;
155}
156
157impl WidgetResultApi for WidgetResult {
158    fn into_found(self) -> Option<WidgetRef> {
159        match self {
160            Result::Ok(_) => None,
161            Result::Err(found) => Some(found)
162        }
163    }
164}*/
165
166pub type WidgetDraw = Result<(), WidgetRef>;
167
168generate_ref_cast_api!(Widget);
169
170pub trait WidgetFactory {
171    fn new(&self, cx: &mut Cx) -> Box<dyn Widget>;
172}
173
174#[derive(Default, LiveComponentRegistry)]
175pub struct WidgetRegistry {
176    pub map: BTreeMap<LiveType, (LiveComponentInfo, Box<dyn WidgetFactory>)>
177}
178
179pub trait WidgetAction: 'static {
180    fn type_id(&self) -> TypeId;
181    fn box_clone(&self) -> Box<dyn WidgetAction>;
182}
183
184impl<T: 'static + ? Sized + Clone> WidgetAction for T {
185    fn type_id(&self) -> TypeId {
186        TypeId::of::<T>()
187    }
188    
189    fn box_clone(&self) -> Box<dyn WidgetAction> {
190        Box::new((*self).clone())
191    }
192}
193
194generate_clone_cast_api!(WidgetAction);
195
196impl Clone for Box<dyn WidgetAction> {
197    fn clone(&self) -> Box<dyn WidgetAction> {
198        self.as_ref().box_clone()
199    }
200}
201
202#[derive(Clone, Default)]
203pub struct WidgetRef(Rc<RefCell<Option<Box<dyn Widget >> >>);
204
205impl Debug for WidgetRef {
206    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
207        write!(f, "WidgetRef {}", self.widget_uid().0)
208    }
209}
210
211#[derive(Clone)]
212pub enum WidgetSet {
213    Inline {
214        set: [Option<WidgetRef>; 4],
215        len: usize
216    },
217    Vec(Vec<WidgetRef>),
218    Empty
219}
220
221impl std::fmt::Debug for WidgetSet {
222    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
223        match self {
224            Self::Inline {len, ..} => {
225                let _ = write!(f, "WidgetSet::Inline: {}", len);
226            },
227            Self::Vec(vec) => {
228                let _ = write!(f, "WidgetSet::Vec: {}", vec.len());
229            },
230            Self::Empty => {
231                let _ = write!(f, "WidgetSet::Empty");
232            }
233        }
234        Ok(())
235    }
236}
237
238impl Default for WidgetSet {
239    fn default() -> Self {Self::Empty}
240}
241
242impl WidgetSet {
243    pub fn is_empty(&mut self) -> bool {
244        if let Self::Empty = self {
245            true
246        }
247        else {
248            false
249        }
250    }
251    pub fn push(&mut self, item: WidgetRef) {
252        match self {
253            Self::Empty => {
254                *self = Self::Inline {
255                    set: [Some(item), None, None, None],
256                    len: 1
257                }
258            }
259            Self::Inline {len, set} => {
260                if *len == set.len() {
261                    let mut vec = Vec::new();
262                    for item in set {
263                        vec.push(item.clone().unwrap());
264                    }
265                    vec.push(item);
266                    *self = Self::Vec(vec);
267                }
268                else {
269                    set[*len] = Some(item);
270                    *len += 1;
271                }
272            }
273            Self::Vec(vec) => {
274                vec.push(item);
275            }
276        }
277    }
278    
279    pub fn extend_from_set(&mut self, other: &WidgetSet) {
280        for item in other.iter() {
281            self.push(item);
282        }
283    }
284    
285    pub fn into_first(self) -> WidgetRef {
286        match self {
287            Self::Empty => {
288                WidgetRef::empty()
289            }
290            Self::Inline {len: _, mut set} => {
291                set[0].take().unwrap()
292            }
293            Self::Vec(mut vec) => {
294                vec.remove(0)
295            }
296        }
297    }
298    
299    pub fn widgets(&self, paths: &[&[LiveId]]) -> WidgetSet {
300        let mut results = WidgetSet::default();
301        for widget in self.iter() {
302            if let Some(inner) = widget.0.borrow_mut().as_mut() {
303                for path in paths {
304                    inner.find_widgets(path, WidgetCache::Yes, &mut results);
305                }
306            }
307        }
308        results
309    }
310    
311    pub fn contains(&self, widget: &WidgetRef) -> bool {
312        for item in self.iter() {
313            if item == *widget {
314                return true
315            }
316        }
317        false
318    }
319}
320
321impl LiveHook for WidgetSet {}
322impl LiveApply for WidgetSet {
323    fn apply(&mut self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
324        for inner in self.iter() {
325            let mut inner = inner.0.borrow_mut();
326            if let Some(component) = &mut *inner {
327                return component.apply(cx, from, index, nodes)
328            }
329        }
330        nodes.skip_node(index)
331    }
332}
333
334impl WidgetSet {
335    pub fn empty() -> Self {Self::Empty}
336    pub fn iter(&self) -> WidgetSetIterator {
337        WidgetSetIterator {
338            widget_set: self,
339            index: 0
340        }
341    }
342    
343    pub fn set_text(&self, v: &str) {
344        for item in self.iter(){
345            item.set_text(v)
346        }
347    }
348    
349    pub fn set_text_and_redraw(&self, cx: &mut Cx, v: &str) {
350        for item in self.iter(){
351            item.set_text_and_redraw(cx, v)
352        }
353    }
354}
355
356pub struct WidgetSetIterator<'a> {
357    widget_set: &'a WidgetSet,
358    index: usize
359}
360
361impl<'a> Iterator for WidgetSetIterator<'a> {
362    // We can refer to this type using Self::Item
363    type Item = WidgetRef;
364    fn next(&mut self) -> Option<Self::Item> {
365        match self.widget_set {
366            WidgetSet::Empty => {
367                return None;
368            }
369            WidgetSet::Inline {set, len} => {
370                if self.index >= *len {
371                    return None
372                }
373                let ret = set[self.index].as_ref().unwrap();
374                self.index += 1;
375                return Some(ret.clone())
376            }
377            WidgetSet::Vec(vec) => {
378                if self.index >= vec.len() {
379                    return None
380                }
381                let ret = &vec[self.index];
382                self.index += 1;
383                return Some(ret.clone())
384            }
385        }
386    }
387}
388
389impl PartialEq for WidgetRef {
390    fn eq(&self, other: &WidgetRef) -> bool {
391        Rc::ptr_eq(&self.0, &other.0)
392    }
393    
394    fn ne(&self, other: &WidgetRef) -> bool {
395        !Rc::ptr_eq(&self.0, &other.0)
396    }
397}
398
399impl WidgetRef {
400    pub fn empty() -> Self {Self (Rc::new(RefCell::new(None)))}
401    
402    pub fn is_empty(&self) -> bool {
403        self.0.borrow().as_ref().is_none()
404    }
405    pub fn new_with_inner(widget: Box<dyn Widget>) -> Self {
406        Self (Rc::new(RefCell::new(Some(widget))))
407    }
408    
409    pub fn handle_widget_event_with(&self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
410        if let Some(inner) = self.0.borrow_mut().as_mut() {
411            return inner.handle_widget_event_with(cx, event, dispatch_action)
412        }
413    }
414    
415    pub fn handle_widget_event(&self, cx: &mut Cx, event: &Event) -> Vec<WidgetActionItem> {
416        if let Some(inner) = self.0.borrow_mut().as_mut() {
417            return inner.handle_widget_event(cx, event)
418        }
419        Vec::new()
420    }
421    
422    pub fn widget_uid(&self) -> WidgetUid {
423        if let Some(inner) = self.0.borrow().as_ref() {
424            return inner.widget_uid()
425        }
426        WidgetUid(0)
427    }
428    
429    pub fn widget_to_data(&self, cx: &mut Cx, actions: &WidgetActions, nodes: &mut LiveNodeVec, path: &[LiveId]) -> bool {
430        if let Some(inner) = self.0.borrow_mut().as_mut() {
431            return inner.widget_to_data(cx, actions, nodes, path);
432        }
433        false
434    }
435    
436    pub fn data_to_widget(&self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
437        if let Some(inner) = self.0.borrow_mut().as_mut() {
438            inner.data_to_widget(cx, nodes, path);
439        }
440    }
441    
442    pub fn find_widgets(
443        &mut self,
444        path: &[LiveId],
445        cached: WidgetCache,
446        results: &mut WidgetSet
447    ) {
448        if let Some(inner) = self.0.borrow_mut().as_mut() {
449            inner.find_widgets(path, cached, results)
450        }
451    }
452    
453    pub fn widget(&self, path: &[LiveId]) -> WidgetRef {
454        if let Some(inner) = self.0.borrow_mut().as_mut() {
455            return inner.widget(path);
456        }
457        WidgetRef::empty()
458    }
459    
460    pub fn widgets(&self, paths: &[&[LiveId]]) -> WidgetSet {
461        if let Some(inner) = self.0.borrow_mut().as_mut() {
462            return inner.widgets(paths);
463        }
464        WidgetSet::default()
465    }
466    
467    pub fn draw_walk_widget(&self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
468        if let Some(inner) = self.0.borrow_mut().as_mut() {
469            if let Some(nd) = inner.draw_walk_widget(cx, walk).hook_widget() {
470                if nd.is_empty() {
471                    return WidgetDraw::hook(self.clone())
472                }
473                return WidgetDraw::hook(nd);
474            }
475        }
476        WidgetDraw::done()
477    }
478    
479    pub fn walk(&self, cx:&mut Cx) -> Walk {
480        if let Some(inner) = self.0.borrow_mut().as_mut() {
481            return inner.walk(cx)
482        }
483        Walk::default()
484    }
485    
486    // forwarding Widget trait
487    pub fn redraw(&self, cx: &mut Cx) {
488        if let Some(inner) = self.0.borrow_mut().as_mut() {
489            return inner.redraw(cx)
490        }
491    }
492    
493    
494    pub fn is_visible(&self) -> bool {
495        if let Some(inner) = self.0.borrow().as_ref() {
496            return inner.is_visible()
497        }
498        true
499    }
500    
501    pub fn draw_widget_all(&self, cx: &mut Cx2d) {
502        if let Some(inner) = self.0.borrow_mut().as_mut() {
503            return inner.draw_widget_all(cx)
504        }
505    }
506    
507    pub fn draw_widget(&self, cx: &mut Cx2d) -> WidgetDraw {
508        if let Some(inner) = self.0.borrow_mut().as_mut() {
509            if let Some(nd) = inner.draw_widget(cx).hook_widget() {
510                if nd.is_empty() {
511                    return WidgetDraw::hook(self.clone())
512                }
513                return WidgetDraw::hook(nd);
514            }
515        }
516        WidgetDraw::done()
517    }
518    
519    pub fn text(&self) -> String {
520        if let Some(inner) = self.0.borrow_mut().as_mut() {
521            inner.text()
522        }
523        else {
524            String::new()
525        }
526    }
527    
528    pub fn set_text(&self, v: &str) {
529        if let Some(inner) = self.0.borrow_mut().as_mut() {
530            inner.set_text(v)
531        }
532    }
533    
534    pub fn set_text_and_redraw(&self, cx: &mut Cx, v: &str) {
535        if let Some(inner) = self.0.borrow_mut().as_mut() {
536            inner.set_text_and_redraw(cx, v);
537        }
538    }
539    
540    pub fn borrow_mut<T: 'static + Widget>(&self) -> Option<std::cell::RefMut<'_, T >> {
541        if let Ok(ret) = std::cell::RefMut::filter_map(self.0.borrow_mut(), | inner | {
542            if let Some(inner) = inner.as_mut() {
543                inner.cast_mut::<T>()
544            }
545            else {
546                None
547            }
548        }) {
549            Some(ret)
550        }
551        else {
552            None
553        }
554    }
555    
556    pub fn borrow<T: 'static + Widget>(&self) -> Option<std::cell::Ref<'_, T >> {
557        if let Ok(ret) = std::cell::Ref::filter_map(self.0.borrow(), | inner | {
558            if let Some(inner) = inner.as_ref() {
559                inner.cast::<T>()
560            }
561            else {
562                None
563            }
564        }) {
565            Some(ret)
566        }
567        else {
568            None
569        }
570    }
571    
572    pub fn apply_over(&self, cx: &mut Cx, nodes: &[LiveNode]) {
573        self.apply(cx, ApplyFrom::ApplyOver, 0, nodes);
574    }
575
576    pub fn apply_over_and_redraw(&self, cx: &mut Cx, nodes: &[LiveNode]) {
577        self.apply(cx, ApplyFrom::ApplyOver, 0, nodes);
578        self.redraw(cx);
579    }
580    
581    fn apply(&self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
582        let mut inner = self.0.borrow_mut();
583        if let LiveValue::Class {live_type, ..} = nodes[index].value {
584            if let Some(component) = &mut *inner {
585                if component.type_id() != live_type {
586                    *inner = None; // type changed, drop old component
587                    log!("TYPECHANGE");
588                }
589                else {
590                    return component.apply(cx, from, index, nodes);
591                }
592            }
593            if let Some(component) = cx.live_registry.clone().borrow()
594                .components.get::<WidgetRegistry>().new(cx, live_type) {
595                    if cx.debug.marker() == 1{
596                        panic!()
597                    }
598                *inner = Some(component);
599                if let Some(component) = &mut *inner {
600                    return component.apply(cx, from, index, nodes);
601                }
602            }
603            else {
604                cx.apply_error_cant_find_target(live_error_origin!(), index, nodes, nodes[index].id);
605            }
606        }
607        else if let Some(component) = &mut *inner {
608            return component.apply(cx, from, index, nodes)
609        }
610        cx.apply_error_cant_find_target(live_error_origin!(), index, nodes, nodes[index].id);
611        nodes.skip_node(index)
612    }
613}
614
615impl LiveHook for WidgetRef {}
616impl LiveApply for WidgetRef {
617    fn apply(&mut self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
618        <WidgetRef>::apply(self, cx, from, index, nodes)
619    }
620}
621
622impl LiveNew for WidgetRef {
623    fn new(_cx: &mut Cx) -> Self {
624        Self (Rc::new(RefCell::new(None)))
625    }
626    
627    fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
628        LiveTypeInfo {
629            module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
630            live_type: LiveType::of::<dyn Widget>(),
631            fields: Vec::new(),
632            live_ignore: true,
633            type_name: LiveId(0)
634        }
635    }
636}
637
638#[derive(Clone)]
639pub struct WidgetActionItem {
640    pub widget_uid: WidgetUid,
641    pub container_uid: WidgetUid,
642    pub item_uid: WidgetUid,
643    pub action: Box<dyn WidgetAction>
644}
645
646impl Debug for WidgetActionItem {
647    fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
648        write!(f, "WidgetActionItem{{wiget_uid: {:?}, container_uid: {:?}, item_uid:{:?}}}", self.widget_uid, self.container_uid, self.item_uid)
649    }
650}
651
652pub type WidgetActions = Vec<WidgetActionItem>;
653
654pub trait WidgetActionsApi {
655    fn find_single_action(&self, widget_uid: WidgetUid) -> Option<&WidgetActionItem>;
656    fn single_action<T: WidgetAction + 'static >(&self, widget_uid: WidgetUid) -> T where T: Default + Clone;
657    fn not_empty(&self) -> bool;
658}
659
660impl WidgetActionsApi for WidgetActions {
661    fn find_single_action(&self, widget_uid: WidgetUid) -> Option<&WidgetActionItem> {
662        self.iter().find( | v | v.widget_uid == widget_uid)
663    }
664    
665    fn single_action<T: WidgetAction + 'static >(&self, widget_uid: WidgetUid) -> T where T: Default + Clone {
666        if let Some(item) = self.find_single_action(widget_uid) {
667            item.action.cast::<T>()
668        }
669        else {
670            T::default()
671        }
672    }
673    
674    fn not_empty(&self) -> bool {
675        self.len()>0
676    }
677}
678
679impl WidgetActionItem {
680    pub fn new(action: Box<dyn WidgetAction>, widget_uid: WidgetUid) -> Self {
681        Self {
682            container_uid: WidgetUid(0),
683            item_uid: WidgetUid(0),
684            widget_uid,
685            action
686        }
687    }
688    pub fn with_container(self, container_uid: WidgetUid) -> Self {
689        Self {
690            container_uid,
691            ..self
692        }
693    }
694    
695    pub fn with_item(self, item_uid: WidgetUid) -> Self {
696        Self {
697            item_uid,
698            ..self
699        }
700    }
701    
702    pub fn action<T: WidgetAction + 'static >(&self) -> T where T: Default + Clone {
703        self.action.cast::<T>()
704    }
705}
706
707
708pub struct DrawStateWrap<T: Clone> {
709    state: Option<T>,
710    redraw_id: u64
711}
712
713impl<T: Clone> Default for DrawStateWrap<T> {
714    fn default() -> Self {
715        Self {
716            state: None,
717            redraw_id: 0
718        }
719    }
720}
721
722impl<T: Clone> DrawStateWrap<T> {
723    pub fn begin(&mut self, cx: &mut Cx2d, init: T) -> bool {
724        if self.redraw_id != cx.redraw_id() {
725            self.redraw_id = cx.redraw_id();
726            self.state = Some(init);
727            true
728        }
729        else {
730            false
731        }
732    }
733    
734    pub fn begin_with<F, S>(&mut self, cx: &mut Cx2d, v: &S, init: F) -> bool where F: FnOnce(&mut Cx2d, &S) -> T {
735        if self.redraw_id != cx.redraw_id() {
736            self.redraw_id = cx.redraw_id();
737            self.state = Some(init(cx, v));
738            true
739        }
740        else {
741            false
742        }
743    }
744    
745    pub fn get(&self) -> Option<T> {
746        self.state.clone()
747    }
748    
749    pub fn as_ref(&self) -> Option<&T> {
750        self.state.as_ref()
751    }
752    
753    pub fn as_mut(&mut self) -> Option<&mut T> {
754        self.state.as_mut()
755    }
756    
757    pub fn set(&mut self, value: T) {
758        self.state = Some(value);
759    }
760    
761    pub fn end(&mut self) {
762        self.state = None;
763    }
764}
765
766#[macro_export]
767macro_rules!register_widget {
768    ( $ cx: ident, $ ty: ty) => {
769        {
770            struct Factory();
771            impl WidgetFactory for Factory {
772                fn new(&self, cx: &mut Cx) -> Box<dyn Widget> {
773                    Box::new(< $ ty>::new(cx))
774                }
775            }
776            register_component_factory!( $ cx, WidgetRegistry, $ ty, Factory);
777        }
778    }
779}