pixcil/widget/
move_camera.rs

1use super::{VariableSizeWidget, Widget};
2use crate::{
3    app::App,
4    event::{Event, MouseAction},
5};
6use pagurus::image::Canvas;
7use pagurus::{
8    Result,
9    spatial::{Position, Region},
10};
11
12#[derive(Debug)]
13pub struct MoveCameraWidget {
14    region: Region,
15    cursor: Option<Position>,
16    start: Option<Position>,
17}
18
19impl MoveCameraWidget {
20    pub fn new(app: &App) -> Self {
21        Self {
22            region: app.screen_size().to_region(),
23            cursor: None,
24            start: None,
25        }
26    }
27}
28
29impl Widget for MoveCameraWidget {
30    fn region(&self) -> Region {
31        self.region
32    }
33
34    fn render(&self, app: &App, canvas: &mut Canvas) {
35        if let Some(cursor) = self.cursor {
36            let sprite = if self.start.is_none() {
37                &app.assets().hand.open
38            } else {
39                &app.assets().hand.close
40            };
41            canvas
42                .offset(cursor - (sprite.size().width / 2) as i32)
43                .draw_sprite(sprite);
44        }
45    }
46
47    fn handle_event(&mut self, app: &mut App, event: &mut Event) -> Result<()> {
48        // NOTE: This widget never consume events.
49        match event {
50            Event::Mouse {
51                consumed: false,
52                action: MouseAction::Down,
53                position,
54                ..
55            } => {
56                self.start = Some(*position);
57            }
58            Event::Mouse {
59                consumed: false,
60                action: MouseAction::Move,
61                position,
62                ..
63            } if self.start.is_some() => {
64                let start = self.start.expect("unreachable");
65                let end = *position;
66                app.models_mut().config.camera.r#move(start - end);
67                app.request_redraw(self.region);
68                self.start = Some(end);
69            }
70            Event::Mouse { .. } => {
71                self.start = None;
72            }
73            _ => {}
74        }
75
76        if let Some(position) = event.position() {
77            let old = self.cursor;
78            if event.is_consumed() {
79                self.cursor = None;
80            } else {
81                self.cursor = Some(position);
82            }
83            if self.cursor != old {
84                let sprite_size = app.assets().hand.open.size();
85                for &position in old.iter().chain(self.cursor.iter()) {
86                    app.request_redraw(Region::new(
87                        position - (sprite_size.width / 2) as i32,
88                        sprite_size,
89                    ));
90                }
91            }
92        }
93
94        Ok(())
95    }
96
97    fn children(&mut self) -> Vec<&mut dyn Widget> {
98        vec![]
99    }
100}
101
102impl VariableSizeWidget for MoveCameraWidget {
103    fn set_region(&mut self, _app: &App, region: Region) {
104        self.region = region;
105    }
106}