appcui/ui/canvas/
canvas.rs1use crate::prelude::*;
2use crate::ui::canvas::initialization_flags::Flags;
3
4use self::components::ScrollBars;
5
6#[CustomControl(overwrite=OnPaint+OnKeyPressed+OnMouseEvent+OnResize, internal=true)]
7pub struct Canvas {
8 surface: Surface,
9 x: i32,
10 y: i32,
11 background: Option<Character>,
12 flags: Flags,
13 drag_point: Option<Point>,
14 scrollbars: ScrollBars
15}
16impl Canvas {
17 pub fn new(canvas_size: Size, layout: Layout, flags: Flags) -> Self {
29 Self {
30 base: ControlBase::with_status_flags(
31 layout,
32 (StatusFlags::Visible | StatusFlags::Enabled | StatusFlags::AcceptInput)
33 | if flags == Flags::ScrollBars {
34 StatusFlags::IncreaseBottomMarginOnFocus | StatusFlags::IncreaseRightMarginOnFocus
35 } else {
36 StatusFlags::None
37 },
38 ),
39 surface: Surface::new(canvas_size.width, canvas_size.height),
40 x: 0,
41 y: 0,
42 flags,
43 background: None,
44 drag_point: None,
45 scrollbars: ScrollBars::new(flags == Flags::ScrollBars)
46 }
47 }
48
49
50 pub fn resize_surface(&mut self, new_size: Size) {
58 self.surface.resize(new_size);
59 let sz = self.surface.size();
60 self.scrollbars.update(sz.width as u64, sz.height as u64, self.size());
61 self.move_scroll_to(self.x, self.y);
62 }
63
64 #[inline(always)]
66 pub fn drawing_surface_mut(&mut self) -> &mut Surface {
67 &mut self.surface
68 }
69
70 pub fn set_background(&mut self, backgroud_char: Character) {
78 self.background = Some(backgroud_char);
79 }
80
81 pub fn clear_background(&mut self) {
83 self.background = None;
84 }
85
86 fn move_scroll_to(&mut self, x: i32, y: i32) {
87 let sz = self.size();
88 let surface_size = self.surface.size();
89 self.x = if surface_size.width <= sz.width {
90 0
91 } else {
92 x.max((sz.width as i32) - (surface_size.width as i32))
93 };
94 self.y = if surface_size.height <= sz.height {
95 0
96 } else {
97 y.max((sz.height as i32) - (surface_size.height as i32))
98 };
99 self.x = self.x.min(0);
100 self.y = self.y.min(0);
101 self.scrollbars.set_indexes((-self.x) as u64, (-self.y) as u64);
102 }
103 fn update_scroll_pos_from_scrollbars(&mut self) {
104 let h = -(self.scrollbars.horizontal_index() as i32);
105 let v = -(self.scrollbars.vertical_index() as i32);
106 self.move_scroll_to(h,v);
107 }
108}
109impl OnResize for Canvas {
110 fn on_resize(&mut self, _old_size: Size, _new_size: Size) {
111 let paint_sz = self.surface.size();
112 self.scrollbars.resize(paint_sz.width as u64, paint_sz.height as u64,&self.base);
113 self.move_scroll_to(self.x, self.y);
114 }
115}
116impl OnPaint for Canvas {
117 fn on_paint(&self, surface: &mut Surface, theme: &Theme) {
118 if (self.has_focus()) && (self.flags == Flags::ScrollBars) {
119 self.scrollbars.paint(surface, theme, self);
120 surface.reduce_clip_by(0,0,1,1);
121 }
122 if let Some(back) = self.background {
123 surface.clear(back);
124 }
125 surface.draw_surface(self.x, self.y, &self.surface);
126 }
127}
128impl OnKeyPressed for Canvas {
129 fn on_key_pressed(&mut self, key: Key, _character: char) -> EventProcessStatus {
130 match key.value() {
131 key!("Left") => {
132 self.move_scroll_to(self.x + 1, self.y);
133 EventProcessStatus::Processed
134 }
135 key!("Right") => {
136 self.move_scroll_to(self.x - 1, self.y);
137 EventProcessStatus::Processed
138 }
139 key!("Up") => {
140 self.move_scroll_to(self.x, self.y + 1);
141 EventProcessStatus::Processed
142 }
143 key!("Down") => {
144 self.move_scroll_to(self.x, self.y - 1);
145 EventProcessStatus::Processed
146 }
147 key!("Shift+Left") => {
148 self.move_scroll_to(0, self.y);
149 EventProcessStatus::Processed
150 }
151 key!("Shift+Right") => {
152 self.move_scroll_to(i32::MIN, self.y);
153 EventProcessStatus::Processed
154 }
155 key!("Shift+Up") => {
156 self.move_scroll_to(self.x, 0);
157 EventProcessStatus::Processed
158 }
159 key!("Shift+Down") => {
160 self.move_scroll_to(self.x, i32::MIN);
161 EventProcessStatus::Processed
162 }
163 key!("Ctrl+Left") => {
164 self.move_scroll_to(self.x + self.size().width as i32, self.y);
165 EventProcessStatus::Processed
166 }
167 key!("Ctrl+Right") => {
168 self.move_scroll_to(self.x - self.size().width as i32, self.y);
169 EventProcessStatus::Processed
170 }
171 key!("Ctrl+Up") | key!("PageUp")=> {
172 self.move_scroll_to(self.x, self.y + self.size().height as i32);
173 EventProcessStatus::Processed
174 }
175 key!("Ctrl+Down") | key!("PageDown")=> {
176 self.move_scroll_to(self.x, self.y - self.size().height as i32);
177 EventProcessStatus::Processed
178 }
179 key!("Home") => {
180 self.move_scroll_to(0, 0);
181 EventProcessStatus::Processed
182 }
183 key!("End") => {
184 self.move_scroll_to(i32::MIN, i32::MIN);
185 EventProcessStatus::Processed
186 }
187 _ => EventProcessStatus::Ignored,
188 }
189 }
190}
191impl OnMouseEvent for Canvas {
192 fn on_mouse_event(&mut self, event: &MouseEvent) -> EventProcessStatus {
193 if self.scrollbars.process_mouse_event(event) {
194 self.update_scroll_pos_from_scrollbars();
195 return EventProcessStatus::Processed;
196 }
197 let response = match event {
198 MouseEvent::Enter => EventProcessStatus::Ignored,
199 MouseEvent::Leave => EventProcessStatus::Ignored,
200 MouseEvent::Over(_) => EventProcessStatus::Ignored,
201 MouseEvent::Pressed(data) => {
202 if (self.flags == Flags::ScrollBars) && (self.has_focus()) {
203 let sz = self.size();
204 if (data.x == sz.width as i32) || (data.y == sz.height as i32) {
205 return EventProcessStatus::Ignored;
206 }
207 }
208 self.drag_point = Some(Point::new(data.x, data.y));
209 EventProcessStatus::Processed
210 }
211 MouseEvent::Released(data) => {
212 if let Some(p) = self.drag_point {
213 self.move_scroll_to(self.x + data.x - p.x, self.y + data.y - p.y);
214 }
215 self.drag_point = None;
216 EventProcessStatus::Processed
217 }
218 MouseEvent::DoubleClick(_) => EventProcessStatus::Ignored,
219 MouseEvent::Drag(data) => {
220 if let Some(p) = self.drag_point {
221 self.move_scroll_to(self.x + data.x - p.x, self.y + data.y - p.y);
222 }
223 self.drag_point = Some(Point::new(data.x, data.y));
224 EventProcessStatus::Processed
225 }
226 MouseEvent::Wheel(dir) => {
227 match dir {
228 MouseWheelDirection::Left => self.move_scroll_to(self.x + 1, self.y),
229 MouseWheelDirection::Right => self.move_scroll_to(self.x - 1, self.y),
230 MouseWheelDirection::Up => self.move_scroll_to(self.x, self.y + 1),
231 MouseWheelDirection::Down => self.move_scroll_to(self.x, self.y - 1),
232 };
233 EventProcessStatus::Processed
234 }
235 };
236 if self.scrollbars.should_repaint() {
238 EventProcessStatus::Processed
239 } else {
240 response
241 }
242 }
243}
244