1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
use crate::{MenuIndexFromScreenCoord, MenuInstance, MenuInstanceChoose}; use prototty_event_routine::{event_or_peek_with_handled, EventOrPeek, EventRoutine, Handled, ViewSelector}; use prototty_input::Input; use prototty_render::{ColModify, Frame, View, ViewContext}; use std::marker::PhantomData; #[derive(Default)] pub struct MenuInstanceRoutine<V, C> { view: PhantomData<V>, choose: PhantomData<C>, } impl<V, C> MenuInstanceRoutine<V, C> where C: MenuInstanceChoose, for<'a> V: View<&'a MenuInstance<C::Entry>>, V: MenuIndexFromScreenCoord, { pub fn new() -> Self { Self { view: PhantomData, choose: PhantomData, } } } impl<V, C> Clone for MenuInstanceRoutine<V, C> where C: MenuInstanceChoose, for<'a> V: View<&'a MenuInstance<C::Entry>>, V: MenuIndexFromScreenCoord, { fn clone(&self) -> Self { Self::new() } } impl<V, C> Copy for MenuInstanceRoutine<V, C> where C: MenuInstanceChoose, for<'a> V: View<&'a MenuInstance<C::Entry>>, V: MenuIndexFromScreenCoord, { } impl<V, C> EventRoutine for MenuInstanceRoutine<V, C> where C: MenuInstanceChoose, for<'a> V: View<&'a MenuInstance<C::Entry>>, V: MenuIndexFromScreenCoord, { type Return = C::Output; type Data = C; type View = V; type Event = Input; fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self> where EP: EventOrPeek<Event = Self::Event>, { event_or_peek_with_handled(event_or_peek, self, |s, event| { if let Some(menu_output) = data.choose(view, event) { Handled::Return(menu_output) } else { Handled::Continue(s) } }) } fn view<F, CM>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<CM>, frame: &mut F) where F: Frame, CM: ColModify, { view.view(data.menu_instance(), context, frame); } } pub trait MenuInstanceExtraSelect { type DataInput; type Extra; type Choose: MenuInstanceChoose; fn choose<'a>(&self, input: &'a Self::DataInput) -> &'a Self::Choose; fn choose_mut<'a>(&self, input: &'a mut Self::DataInput) -> &'a mut Self::Choose; fn extra<'a>(&self, input: &'a Self::DataInput) -> &'a Self::Extra; } pub struct MenuInstanceExtraRoutine<S> { s: S, } impl<S> MenuInstanceExtraRoutine<S> where S: MenuInstanceExtraSelect + ViewSelector, S::ViewOutput: MenuIndexFromScreenCoord, for<'a> S::ViewOutput: View<(&'a MenuInstance<<S::Choose as MenuInstanceChoose>::Entry>, &'a S::Extra)>, { pub fn new(s: S) -> Self { Self { s } } } impl<S> EventRoutine for MenuInstanceExtraRoutine<S> where S: MenuInstanceExtraSelect + ViewSelector, S::ViewOutput: MenuIndexFromScreenCoord, for<'a> S::ViewOutput: View<(&'a MenuInstance<<S::Choose as MenuInstanceChoose>::Entry>, &'a S::Extra)>, { type Return = <S::Choose as MenuInstanceChoose>::Output; type Data = S::DataInput; type View = S::ViewInput; type Event = Input; fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self> where EP: EventOrPeek<Event = Self::Event>, { event_or_peek_with_handled(event_or_peek, self, |s, event| { let choose = s.s.choose_mut(data); let menu_view = s.s.view(view); if let Some(menu_output) = choose.choose(menu_view, event) { Handled::Return(menu_output) } else { Handled::Continue(s) } }) } fn view<F, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut F) where F: Frame, C: ColModify, { let menu_view = self.s.view_mut(view); let menu_instance = self.s.choose(data).menu_instance(); let extra = self.s.extra(data); menu_view.view((menu_instance, extra), context, frame) } }