makepad_widgets/
toggle_panel.rs1use crate::{button::*, makepad_derive_widget::*, makepad_draw::*, view::*, widget::*};
2
3live_design!{
4 link widgets;
5 use link::theme::*;
6 use makepad_draw::shader::std::*;
7
8 use crate::view_ui::CachedView;
9 use crate::view_ui::View;
10 use crate::button::Button;
11
12 pub TogglePanelBase = {{TogglePanel}} {}
13 pub TOGGLE_PANEL_CLOSE_ICON = dep("crate://self/resources/icons/close_left_panel.svg")
14 pub TOGGLE_PANEL_OPEN_ICON = dep("crate://self/resources/icons/open_left_panel.svg")
15 pub TogglePanel = <TogglePanelBase> {
16 flow: Overlay,
17 width: 300,
18 height: Fill,
19
20 open_content = <CachedView> {
21 width: Fill
22 height: Fill
23
24 draw_bg: {
25 instance opacity: 1.0
26
27 fn pixel(self) -> vec4 {
28 return #f00;
29 let color = sample2d(self.image, self.pos * self.scale + self.shift) + vec4(self.marked, 0.0, 0.0, 0.0);
30 return Pal::premul(vec4(color.xyz, color.w * self.opacity))
31 }
32 }
33 }
34
35 persistent_content = <View> {
36 height: Fit
37 width: Fill
38 default = <View> {
39 height: Fit,
40 width: Fill,
41 padding: {top: 58, left: 15, right: 15}
42 spacing: 10,
43
44 before = <View> {
45 height: Fit,
46 width: Fit,
47 spacing: 10,
48 }
49
50 close = <Button> {
51 draw_icon: {
52 svg_file: (TOGGLE_PANEL_CLOSE_ICON),
53 }
54 }
55
56 open = <Button> {
57 visible: false,
58 draw_icon: {
59 svg_file: (TOGGLE_PANEL_OPEN_ICON),
60 }
61 }
62
63 after = <View> {
64 height: Fit,
65 width: Fit,
66 spacing: 10,
67 }
68 }
69 }
70
71 animator: {
72 panel = {
73 default: open,
74 open = {
75 redraw: true,
76 from: {all: Forward {duration: 0.3}}
77 ease: ExpDecay {d1: 0.80, d2: 0.97}
78 apply: {animator_panel_progress: 1.0, open_content = { draw_bg: {opacity: 1.0} }}
79 }
80 close = {
81 redraw: true,
82 from: {all: Forward {duration: 0.3}}
83 ease: ExpDecay {d1: 0.80, d2: 0.97}
84 apply: {animator_panel_progress: 0.0, open_content = { draw_bg: {opacity: 0.0} }}
85 }
86 }
87 }
88 }
89}
90
91#[derive(Live, Widget)]
93pub struct TogglePanel {
94 #[deref]
95 view: View,
96
97 #[live]
101 animator_panel_progress: f32,
102
103 #[live(300.0)]
105 open_size: f32,
106
107 #[live(110.0)]
109 close_size: f32,
110
111 #[animator]
112 animator: Animator,
113}
114
115impl LiveHook for TogglePanel {
116 fn after_new_from_doc(&mut self, cx: &mut Cx) {
117 if self.is_open(cx) {
118 self.animator_panel_progress = 1.0;
119 } else {
120 self.animator_panel_progress = 0.0;
121 };
122 }
123}
124
125impl Widget for TogglePanel {
126 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
127 if self.animator_handle_event(cx, event).must_redraw() {
128 self.redraw(cx)
129 };
130
131 if let Event::Actions(actions) = event {
132 let open = self.button(id!(open));
133 let close = self.button(id!(close));
134
135 if open.clicked(actions) {
136 open.set_visible(cx, false);
137 close.set_visible(cx, true);
138 self.set_open(cx, true);
139 }
140
141 if close.clicked(actions) {
142 close.set_visible(cx, false);
143 open.set_visible(cx, true);
144 self.set_open(cx, false);
145 }
146 }
147
148 self.view.handle_event(cx, event, scope);
149 }
150
151 fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
152 let mut walk = walk;
153
154 let size_range = self.open_size - self.close_size;
155 let size = self.close_size + size_range * self.animator_panel_progress;
156 walk.width = Size::Fixed(size.into());
157
158 self.view.draw_walk(cx, scope, walk)
159 }
160}
161
162impl TogglePanel {
163 pub fn is_open(&self, cx: &Cx) -> bool {
165 self.animator_in_state(cx, id!(panel.open))
166 }
167
168 pub fn set_open(&mut self, cx: &mut Cx, open: bool) {
170 if open {
171 self.animator_play(cx, id!(panel.open));
172 } else {
173 self.animator_play(cx, id!(panel.close));
174 }
175 }
176}
177
178impl TogglePanelRef {
179 pub fn is_open(&self, cx: &Cx) -> bool {
181 if let Some(inner) = self.borrow() {
182 inner.is_open(cx)
183 } else {
184 false
185 }
186 }
187
188 pub fn set_open(&self, cx: &mut Cx, open: bool) {
190 if let Some(mut inner) = self.borrow_mut() {
191 inner.set_open(cx, open);
192 }
193 }
194}