Skip to content

Commit de51699

Browse files
committed
fix: implement moving, resizing and shrinking with keybindings
1 parent 6a19fe5 commit de51699

File tree

5 files changed

+232
-69
lines changed

5 files changed

+232
-69
lines changed

default.kdl

+27-27
Original file line numberDiff line numberDiff line change
@@ -46,35 +46,35 @@ keys {
4646
shrink right 1 mod=ctrl key=l
4747
shrink right 1 mod=ctrl key=<right>
4848

49-
// move rectangle in direction by 10px
50-
move left 10 mod=alt key=h
51-
move left 10 mod=alt key=<left>
52-
move down 10 mod=alt key=j
53-
move down 10 mod=alt key=<down>
54-
move up 10 mod=alt key=k
55-
move up 10 mod=alt key=<up>
56-
move right 10 mod=alt key=l
57-
move right 10 mod=alt key=<right>
49+
// move rectangle in direction by 100px
50+
move left 100 mod=alt key=h
51+
move left 100 mod=alt key=<left>
52+
move down 100 mod=alt key=j
53+
move down 100 mod=alt key=<down>
54+
move up 100 mod=alt key=k
55+
move up 100 mod=alt key=<up>
56+
move right 100 mod=alt key=l
57+
move right 100 mod=alt key=<right>
5858

59-
// extend a side by 10px
60-
extend left 10 mod=alt key=H
61-
extend left 10 mod=alt key=<left>
62-
extend down 10 mod=alt key=J
63-
extend down 10 mod=alt key=<down>
64-
extend up 10 mod=alt key=K
65-
extend up 10 mod=alt key=<up>
66-
extend right 10 mod=alt key=L
67-
extend right 10 mod=alt key=<right>
59+
// extend a side by 100px
60+
extend left 100 mod=alt key=H
61+
extend left 100 mod=alt key=<left>
62+
extend down 100 mod=alt key=J
63+
extend down 100 mod=alt key=<down>
64+
extend up 100 mod=alt key=K
65+
extend up 100 mod=alt key=<up>
66+
extend right 100 mod=alt key=L
67+
extend right 100 mod=alt key=<right>
6868

69-
// shrink a side by 10px
70-
shrink left 10 mod=ctrl+alt key=h
71-
shrink left 10 mod=ctrl+alt key=<left>
72-
shrink down 10 mod=ctrl+alt key=j
73-
shrink down 10 mod=ctrl+alt key=<down>
74-
shrink up 10 mod=ctrl+alt key=k
75-
shrink up 10 mod=ctrl+alt key=<up>
76-
shrink right 10 mod=ctrl+alt key=l
77-
shrink right 10 mod=ctrl+alt key=<right>
69+
// shrink a side by 100px
70+
shrink left 100 mod=ctrl+alt key=h
71+
shrink left 100 mod=ctrl+alt key=<left>
72+
shrink down 100 mod=ctrl+alt key=j
73+
shrink down 100 mod=ctrl+alt key=<down>
74+
shrink up 100 mod=ctrl+alt key=k
75+
shrink up 100 mod=ctrl+alt key=<up>
76+
shrink right 100 mod=ctrl+alt key=l
77+
shrink right 100 mod=ctrl+alt key=<right>
7878

7979
// move selection as far as it can go
8080
move left key=gh

key.txt

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
ctrl j
2+
3+
```rs
4+
[src/canvas.rs:115:13] event = Keyboard(
5+
KeyPressed {
6+
key: Character(
7+
"j",
8+
),
9+
modified_key: Character(
10+
"j",
11+
),
12+
physical_key: Code(
13+
KeyJ,
14+
),
15+
location: Standard,
16+
modifiers: Modifiers(
17+
CTRL,
18+
),
19+
text: Some(
20+
"\n",
21+
),
22+
},
23+
)
24+
```
25+
26+
ctrl alt j
27+
28+
```rs
29+
[src/canvas.rs:115:13] event = Keyboard(
30+
KeyPressed {
31+
key: Character(
32+
"j",
33+
),
34+
modified_key: Character(
35+
"j",
36+
),
37+
physical_key: Code(
38+
KeyJ,
39+
),
40+
location: Standard,
41+
modifiers: Modifiers(
42+
CTRL | ALT,
43+
),
44+
text: Some(
45+
"\n",
46+
),
47+
},
48+
)
49+
```
50+
51+
ctrl alt J
52+
53+
```rs
54+
[src/canvas.rs:115:13] event = Keyboard(
55+
KeyPressed {
56+
key: Character(
57+
"j",
58+
),
59+
modified_key: Character(
60+
"J",
61+
),
62+
physical_key: Code(
63+
KeyJ,
64+
),
65+
location: Standard,
66+
modifiers: Modifiers(
67+
SHIFT | CTRL | ALT,
68+
),
69+
text: Some(
70+
"\n",
71+
),
72+
},
73+
)
74+
```
75+
76+
<
77+
78+
```rs
79+
[src/canvas.rs:115:13] event = Keyboard(
80+
KeyPressed {
81+
key: Character(
82+
",",
83+
),
84+
modified_key: Character(
85+
"<",
86+
),
87+
physical_key: Code(
88+
Comma,
89+
),
90+
location: Standard,
91+
modifiers: Modifiers(
92+
SHIFT,
93+
),
94+
text: Some(
95+
"<",
96+
),
97+
},
98+
)
99+
```
100+
101+
ctrl <
102+
103+
```rs
104+
[src/canvas.rs:115:13] event = Keyboard(
105+
KeyPressed {
106+
key: Character(
107+
",",
108+
),
109+
modified_key: Character(
110+
"<",
111+
),
112+
physical_key: Code(
113+
Comma,
114+
),
115+
location: Standard,
116+
modifiers: Modifiers(
117+
SHIFT | CTRL,
118+
),
119+
text: Some(
120+
"<",
121+
),
122+
},
123+
)
124+
```
125+
126+
ctrl alt <
127+
128+
```rs
129+
[src/canvas.rs:115:13] event = Keyboard(
130+
KeyPressed {
131+
key: Character(
132+
",",
133+
),
134+
modified_key: Character(
135+
"<",
136+
),
137+
physical_key: Code(
138+
Comma,
139+
),
140+
location: Standard,
141+
modifiers: Modifiers(
142+
SHIFT | CTRL | ALT,
143+
),
144+
text: Some(
145+
"<",
146+
),
147+
},
148+
)
149+
```

src/app.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,6 @@ impl App {
335335
}
336336
KeyAction::Exit => return Self::exit(),
337337
KeyAction::Move(direction, amount) => {
338-
println!("{direction:?}, {amount:?}");
339338
let Some(selection) = self.selection.as_mut() else {
340339
self.error("Nothing is selected.");
341340
return Task::none();
@@ -388,17 +387,18 @@ impl App {
388387
self.error("Nothing is selected.");
389388
return Task::none();
390389
};
391-
let (image_width, image_height, _) = self.screenshot.raw();
392-
let image_height = image_height as f32;
393-
let image_width = image_width as f32;
394390
let sel = selection.norm();
395391
let amount = amount as f32;
396392

397393
*selection = match direction {
398-
Direction::Up => todo!(),
399-
Direction::Down => todo!(),
400-
Direction::Left => todo!(),
401-
Direction::Right => todo!(),
394+
Direction::Up => sel
395+
.with_y(|y| (y + amount).min(sel.rect.y + sel.rect.height))
396+
.with_height(|h| (h - amount).max(0.0)),
397+
Direction::Down => sel.with_height(|h| (h - amount).max(0.0)),
398+
Direction::Left => sel
399+
.with_x(|x| (x + amount).min(sel.rect.x + sel.rect.width))
400+
.with_width(|w| (w - amount).max(0.0)),
401+
Direction::Right => sel.with_width(|w| (w - amount).max(0.0)),
402402
}
403403
}
404404
},

src/canvas.rs

+47-33
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use iced::keyboard::Event::KeyPressed;
44
use iced::keyboard::Event::KeyReleased;
55
use iced::keyboard::Key::{self, Named};
66
use iced::keyboard::Modifiers;
7-
use iced::keyboard::key::Named::Shift;
7+
use iced::keyboard::key::Named::{Alt, Control, Shift};
88
use iced::mouse::Button::{Left, Right};
99
use iced::mouse::Event::ButtonPressed;
1010
use iced::mouse::Event::ButtonReleased;
@@ -22,6 +22,10 @@ pub struct KeysState {
2222
is_left_down: bool,
2323
/// Left mouse click is currently being held down
2424
is_right_down: bool,
25+
/// Alt key is currently being held down
26+
is_alt_down: bool,
27+
/// Ctrl key is currently being held down
28+
is_ctrl_down: bool,
2529
/// Shift key is currently being held down
2630
is_shift_down: bool,
2731
/// The last key that was pressed
@@ -110,8 +114,7 @@ impl canvas::Program<Message> for App {
110114
// handle keybindings first
111115
if let Keyboard(KeyPressed {
112116
modifiers,
113-
text,
114-
key,
117+
modified_key,
115118
..
116119
}) = event
117120
{
@@ -122,46 +125,31 @@ impl canvas::Program<Message> for App {
122125
// - `G` will also trigger the `SHIFT` modifier
123126
modifiers.remove(Modifiers::SHIFT);
124127

125-
let key = if let Key::Named(name) = key {
126-
// named key takes priority over anything.
127-
//
128-
// For example, if we input `Escape` it will send the `text`
129-
// `\u{1b}` which won't match any of the keys that we have. So we must
130-
// intercept before that happens
131-
Key::Named(*name)
132-
} else {
133-
// if we input `G` for example, it actually sends:
134-
// - modifier: `shift`
135-
// - key: `g`
136-
// - text: `G`
137-
//
138-
// if we input `<` it sends:
139-
// - modifier: `shift`
140-
// - key: `,`
141-
// - text: `<`
142-
//
143-
// So `text` is our source of truth. However, sometimes it is not available.
144-
// If `key != Key::Named` and `text == None` then we use the actual `key`
145-
// as a fallback.
146-
//
147-
// It is unknown when this fallback might be used, but it is kept just in case.
148-
text.as_ref()
149-
.map_or_else(|| key.clone(), |ch| Key::Character(ch.clone()))
150-
};
128+
// we have to do this because if you hold down these keys while
129+
// pressing another key, it won't have them in the `modifiers` field
130+
// if state.is_alt_down {
131+
// modifiers.insert(Modifiers::ALT);
132+
// }
133+
// if state.is_ctrl_down {
134+
// modifiers.insert(Modifiers::CTRL);
135+
// }
151136

152137
if let Some(action) = CONFIG
153138
.keys
154139
.keys
155140
// e.g. for instance keybind for `g` should take priority over `gg`
156-
.get(&(KeySequence((key.clone(), None)), KeyMods(modifiers)))
141+
.get(&(
142+
KeySequence((modified_key.clone(), None)),
143+
KeyMods(modifiers),
144+
))
157145
// e.g. in this case we try the `gg` keybinding since `g` does not exist
158146
.or_else(|| {
159147
state
160148
.last_key_pressed
161149
.as_ref()
162150
.and_then(|last_key_pressed| {
163151
CONFIG.keys.keys.get(&(
164-
KeySequence((last_key_pressed.clone(), Some(key.clone()))),
152+
KeySequence((last_key_pressed.clone(), Some(modified_key.clone()))),
165153
KeyMods(modifiers),
166154
))
167155
})
@@ -182,8 +170,8 @@ impl canvas::Program<Message> for App {
182170
// the "Shift" is already included in the modifiers
183171
//
184172
// This way pressing e.g. `G` would only set the last_key_pressed once
185-
if key != Named(Shift) {
186-
state.last_key_pressed = Some(key);
173+
if *modified_key != Named(Shift) {
174+
state.last_key_pressed = Some(modified_key.clone());
187175
}
188176
}
189177

@@ -230,6 +218,32 @@ impl canvas::Program<Message> for App {
230218
state.is_shift_down = false;
231219
Message::NoOp
232220
}
221+
Keyboard(KeyPressed {
222+
key: Named(Control),
223+
..
224+
}) => {
225+
state.is_ctrl_down = true;
226+
Message::NoOp
227+
}
228+
Keyboard(KeyReleased {
229+
key: Named(Control),
230+
..
231+
}) => {
232+
state.is_ctrl_down = false;
233+
Message::NoOp
234+
}
235+
Keyboard(KeyPressed {
236+
key: Named(Alt), ..
237+
}) => {
238+
state.is_alt_down = true;
239+
Message::NoOp
240+
}
241+
Keyboard(KeyReleased {
242+
key: Named(Alt), ..
243+
}) => {
244+
state.is_alt_down = false;
245+
Message::NoOp
246+
}
233247
Keyboard(KeyPressed {
234248
key: Named(Shift), ..
235249
}) => {

src/config/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ pub static CONFIG: LazyLock<Config> = LazyLock::new(|| {
126126
let default_config =
127127
knus::parse::<DefaultKdlConfig>("<default-config>", DEFAULT_KDL_CONFIG_STR)?;
128128

129-
// if there is no config file, act as if it's simply empty
130129
let user_config = knus::parse::<UserKdlConfig>(
131130
&CLI.config_file,
131+
// if there is no config file, act as if it's simply empty
132132
&fs::read_to_string(&config_file_path).unwrap_or_default(),
133133
)?;
134134

0 commit comments

Comments
 (0)