makepad_widgets/
keyboard_view.rs1use crate::{
2 makepad_derive_widget::*,
3 makepad_draw::*,
4 view::*,
5 widget::*,
6};
7
8live_design!{
9 link widgets;
10 pub KeyboardViewBase = {{KeyboardView}} {}
11 pub KeyboardView = <KeyboardViewBase>{}
12}
13
14
15#[derive(Live, LiveHook, Widget)]
16pub struct KeyboardView {
17 #[deref] view: View,
18 #[redraw] #[rust] area: Area,
19 #[live] outer_layout: Layout,
20 #[live] outer_walk: Walk,
21 #[live] keyboard_walk: Walk,
22 #[live] keyboard_min_shift: f64,
23 #[rust] next_frame: NextFrame,
24
25 #[rust] keyboard_shift: f64,
26 #[rust(AnimState::Closed)] anim_state: AnimState,
27 #[rust] draw_state: DrawStateWrap<Walk>,
28}
29
30enum AnimState{
31 Closed,
32 Opening{duration:f64, start_time:f64, ease:Ease, height:f64},
33 Open,
34 Closing{duration:f64, start_time:f64, ease:Ease, height:f64}
35}
36
37impl KeyboardView {
38
39 fn compute_max_height(&self, height:f64, cx:&Cx)->f64{
40 let self_rect = self.area.rect(cx);
41 let ime_rect = cx.get_ime_area_rect();
42 let av_height = self_rect.size.y - height;
43 let ime_height = ime_rect.size.y + ime_rect.pos.y + self.keyboard_min_shift;
44 if ime_height > av_height {
45 return ime_height - av_height
46 }
47 0.0
48 }
49
50 fn begin(&mut self, cx: &mut Cx2d, walk: Walk) {
51 cx.begin_turtle(walk, self.outer_layout.with_scroll(dvec2(0.,self.keyboard_shift)));
52 }
53
54 fn end(&mut self, cx: &mut Cx2d) {
55 cx.end_turtle_with_area(&mut self.area);
56 }
57}
58
59impl Widget for KeyboardView {
60
61 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
62 if let Some(e) = self.next_frame.is_event(event){
63 match &self.anim_state{
64 AnimState::Opening{duration, start_time, ease, height}=>{
65 if e.time - start_time < *duration{
66 self.keyboard_shift = ease.map((e.time - start_time)/duration) * height;
67 self.next_frame = cx.new_next_frame();
68 }
69 else{
70 self.keyboard_shift = *height;
71 self.anim_state = AnimState::Open;
72 }
73 self.redraw(cx);
74 }
75 AnimState::Closing{duration, start_time, ease, height}=>{
76 if e.time - start_time < *duration{
77 self.keyboard_shift = (1.0-ease.map((e.time - start_time)/duration)) * height;
78 self.next_frame = cx.new_next_frame();
79 }
80 else{
81 self.keyboard_shift = 0.0;
82 self.anim_state = AnimState::Closed;
83 }
84 self.redraw(cx);
85 }
86 _=>()
87 }
88 }
89 match event{
90 Event::VirtualKeyboard(vk)=>{
91 match vk{
92 VirtualKeyboardEvent::WillShow{time, height, ease, duration}=>{
93 let height = self.compute_max_height(*height, cx);
95 self.anim_state = AnimState::Opening{
96 duration: *duration,
97 start_time: *time,
98 ease: *ease,
99 height: height
100 };
101 self.next_frame = cx.new_next_frame();
102 }
103 VirtualKeyboardEvent::WillHide{time, height:_, ease, duration}=>{
104 self.anim_state = AnimState::Closing{
105 height: self.keyboard_shift,
106 duration: *duration,
107 start_time: *time,
108 ease: *ease,
109 };
110 self.next_frame = cx.new_next_frame();
111 }
112 VirtualKeyboardEvent::DidShow{time:_, height}=>{
113 if let AnimState::Closed = self.anim_state{
114 self.keyboard_shift = self.compute_max_height(*height, cx);
115 }
116 self.anim_state = AnimState::Open;
117 self.redraw(cx);
118 }
119 VirtualKeyboardEvent::DidHide{time:_}=>{
120 self.anim_state = AnimState::Closed;
121 self.keyboard_shift = 0.0;
122 self.redraw(cx);
123 }
124 }
125 }
126 _=>()
127 }
128 self.view.handle_event(cx, event, scope);
129 }
130
131
132 fn draw_walk(&mut self, cx: &mut Cx2d, scope:&mut Scope, walk: Walk) -> DrawStep {
133 if self.draw_state.begin_with(cx, &(), |cx,_|{
134 self.view.walk(cx)
135 }){
136 self.begin(cx, walk);
137 }
138 if let Some(walk) = self.draw_state.get() {
139 self.view.draw_walk(cx, scope, walk)?;
140 }
141 self.end(cx);
142 DrawStep::done()
143 }
144}
145