Skip to content

Commit 37877f7

Browse files
authored
Rework commands and make them statically typed. (#993)
1 parent acc2db7 commit 37877f7

File tree

15 files changed

+285
-222
lines changed

15 files changed

+285
-222
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
7272
- Replaced `NEW_WINDOW`, `SET_MENU` and `SHOW_CONTEXT_MENU` commands with methods on `EventCtx` and `DelegateCtx`. ([#931] by [@finnerale])
7373
- Replaced `Command::one_shot` and `::take_object` with a `SingleUse` payload wrapper type. ([#959] by [@finnerale])
7474
- Renamed `WidgetPod` methods: `paint` to `paint_raw`, `paint_with_offset` to `paint`, `paint_with_offset_always` to `paint_always`. ([#980] by [@totsteps])
75+
- `Command` and `Selector` have been reworked and are now statically typed, similarly to `Env` and `Key`. ([#993] by [@finnerale])
7576

7677
### Deprecated
7778

@@ -242,6 +243,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
242243
[#984]: https://github.com/xi-editor/druid/pull/984
243244
[#990]: https://github.com/xi-editor/druid/pull/990
244245
[#991]: https://github.com/xi-editor/druid/pull/991
246+
[#993]: https://github.com/xi-editor/druid/pull/993
245247

246248
## [0.5.0] - 2020-04-01
247249

druid/examples/blocking_function.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ use druid::{
2323

2424
use druid::widget::{Button, Either, Flex, Label};
2525

26-
const START_SLOW_FUNCTION: Selector = Selector::new("start_slow_function");
26+
const START_SLOW_FUNCTION: Selector<u32> = Selector::new("start_slow_function");
2727

28-
const FINISH_SLOW_FUNCTION: Selector = Selector::new("finish_slow_function");
28+
const FINISH_SLOW_FUNCTION: Selector<u32> = Selector::new("finish_slow_function");
2929

3030
struct Delegate {
3131
eventsink: ExtEventSink,
@@ -61,20 +61,15 @@ impl AppDelegate<AppState> for Delegate {
6161
data: &mut AppState,
6262
_env: &Env,
6363
) -> bool {
64-
match cmd.selector {
65-
START_SLOW_FUNCTION => {
66-
data.processing = true;
67-
wrapped_slow_function(self.eventsink.clone(), data.value);
68-
true
69-
}
70-
FINISH_SLOW_FUNCTION => {
71-
data.processing = false;
72-
let number = cmd.get_object::<u32>().expect("api violation");
73-
data.value = *number;
74-
true
75-
}
76-
_ => true,
64+
if cmd.is(START_SLOW_FUNCTION) {
65+
data.processing = true;
66+
wrapped_slow_function(self.eventsink.clone(), data.value);
7767
}
68+
if let Some(number) = cmd.get(FINISH_SLOW_FUNCTION) {
69+
data.processing = false;
70+
data.value = *number;
71+
}
72+
true
7873
}
7974
}
8075

druid/examples/ext_event.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use druid::kurbo::RoundedRect;
2222
use druid::widget::prelude::*;
2323
use druid::{AppLauncher, Color, Data, LocalizedString, Rect, Selector, WidgetExt, WindowDesc};
2424

25-
const SET_COLOR: Selector = Selector::new("event-example.set-color");
25+
const SET_COLOR: Selector<Color> = Selector::new("event-example.set-color");
2626

2727
/// A widget that displays a color.
2828
struct ColorWell;
@@ -53,8 +53,8 @@ impl ColorWell {
5353
impl Widget<MyColor> for ColorWell {
5454
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut MyColor, _env: &Env) {
5555
match event {
56-
Event::Command(cmd) if cmd.selector == SET_COLOR => {
57-
data.0 = cmd.get_object::<Color>().unwrap().clone();
56+
Event::Command(cmd) if cmd.is(SET_COLOR) => {
57+
data.0 = cmd.get_unchecked(SET_COLOR).clone();
5858
ctx.request_paint();
5959
}
6060
_ => (),

druid/examples/identity.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use druid::{
4040

4141
const CYCLE_DURATION: Duration = Duration::from_millis(100);
4242

43-
const FREEZE_COLOR: Selector = Selector::new("identity-example.freeze-color");
43+
const FREEZE_COLOR: Selector<Color> = Selector::new("identity-example.freeze-color");
4444
const UNFREEZE_COLOR: Selector = Selector::new("identity-example.unfreeze-color");
4545

4646
/// Honestly: it's just a color in fancy clothing.
@@ -109,20 +109,13 @@ impl Widget<OurData> for ColorWell {
109109
self.token = ctx.request_timer(CYCLE_DURATION);
110110
ctx.request_paint();
111111
}
112-
113112
Event::WindowConnected if self.randomize => {
114113
self.token = ctx.request_timer(CYCLE_DURATION);
115114
}
116-
117-
Event::Command(cmd) if cmd.selector == FREEZE_COLOR => {
118-
self.frozen = cmd
119-
.get_object::<Color>()
120-
.ok()
121-
.cloned()
122-
.expect("payload is always a Color")
123-
.into();
115+
Event::Command(cmd) if cmd.is(FREEZE_COLOR) => {
116+
self.frozen = cmd.get(FREEZE_COLOR).cloned();
124117
}
125-
Event::Command(cmd) if cmd.selector == UNFREEZE_COLOR => self.frozen = None,
118+
Event::Command(cmd) if cmd.is(UNFREEZE_COLOR) => self.frozen = None,
126119
_ => (),
127120
}
128121
}

druid/examples/multiwin.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use druid::{
2525
};
2626
use log::info;
2727

28-
const MENU_COUNT_ACTION: Selector = Selector::new("menu-count-action");
28+
const MENU_COUNT_ACTION: Selector<usize> = Selector::new("menu-count-action");
2929
const MENU_INCREMENT_ACTION: Selector = Selector::new("menu-increment-action");
3030
const MENU_DECREMENT_ACTION: Selector = Selector::new("menu-decrement-action");
3131
const MENU_SWITCH_GLOW_ACTION: Selector = Selector::new("menu-switch-glow");
@@ -155,16 +155,16 @@ impl AppDelegate<State> for Delegate {
155155
data: &mut State,
156156
_env: &Env,
157157
) -> bool {
158-
match cmd.selector {
159-
sys_cmds::NEW_FILE => {
158+
match cmd {
159+
_ if cmd.is(sys_cmds::NEW_FILE) => {
160160
let new_win = WindowDesc::new(ui_builder)
161161
.menu(make_menu(data))
162162
.window_size((data.selected as f64 * 100.0 + 300.0, 500.0));
163163
ctx.new_window(new_win);
164164
false
165165
}
166-
MENU_COUNT_ACTION => {
167-
data.selected = *cmd.get_object().unwrap();
166+
_ if cmd.is(MENU_COUNT_ACTION) => {
167+
data.selected = *cmd.get_unchecked(MENU_COUNT_ACTION);
168168
let menu = make_menu::<State>(data);
169169
for id in &self.windows {
170170
ctx.set_menu(menu.clone(), *id);
@@ -173,23 +173,23 @@ impl AppDelegate<State> for Delegate {
173173
}
174174
// wouldn't it be nice if a menu (like a button) could just mutate state
175175
// directly if desired?
176-
MENU_INCREMENT_ACTION => {
176+
_ if cmd.is(MENU_INCREMENT_ACTION) => {
177177
data.menu_count += 1;
178178
let menu = make_menu::<State>(data);
179179
for id in &self.windows {
180180
ctx.set_menu(menu.clone(), *id);
181181
}
182182
false
183183
}
184-
MENU_DECREMENT_ACTION => {
184+
_ if cmd.is(MENU_DECREMENT_ACTION) => {
185185
data.menu_count = data.menu_count.saturating_sub(1);
186186
let menu = make_menu::<State>(data);
187187
for id in &self.windows {
188188
ctx.set_menu(menu.clone(), *id);
189189
}
190190
false
191191
}
192-
MENU_SWITCH_GLOW_ACTION => {
192+
_ if cmd.is(MENU_SWITCH_GLOW_ACTION) => {
193193
data.glow_hot = !data.glow_hot;
194194
false
195195
}

druid/examples/open_save.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use druid::widget::{Align, Button, Flex, TextBox};
1616
use druid::{
17-
AppDelegate, AppLauncher, Command, DelegateCtx, Env, FileDialogOptions, FileInfo, FileSpec,
17+
commands, AppDelegate, AppLauncher, Command, DelegateCtx, Env, FileDialogOptions, FileSpec,
1818
LocalizedString, Target, Widget, WindowDesc,
1919
};
2020

@@ -77,30 +77,24 @@ impl AppDelegate<String> for Delegate {
7777
data: &mut String,
7878
_env: &Env,
7979
) -> bool {
80-
match cmd.selector {
81-
druid::commands::SAVE_FILE => {
82-
if let Ok(file_info) = cmd.get_object::<FileInfo>() {
83-
if let Err(e) = std::fs::write(file_info.path(), &data[..]) {
84-
println!("Error writing file: {}", e);
85-
}
86-
}
87-
true
80+
if let Some(Some(file_info)) = cmd.get(commands::SAVE_FILE) {
81+
if let Err(e) = std::fs::write(file_info.path(), &data[..]) {
82+
println!("Error writing file: {}", e);
8883
}
89-
druid::commands::OPEN_FILE => {
90-
if let Ok(file_info) = cmd.get_object::<FileInfo>() {
91-
match std::fs::read_to_string(file_info.path()) {
92-
Ok(s) => {
93-
let first_line = s.lines().next().unwrap_or("");
94-
*data = first_line.to_owned();
95-
}
96-
Err(e) => {
97-
println!("Error opening file: {}", e);
98-
}
99-
}
84+
return true;
85+
}
86+
if let Some(file_info) = cmd.get(commands::OPEN_FILE) {
87+
match std::fs::read_to_string(file_info.path()) {
88+
Ok(s) => {
89+
let first_line = s.lines().next().unwrap_or("");
90+
*data = first_line.to_owned();
91+
}
92+
Err(e) => {
93+
println!("Error opening file: {}", e);
10094
}
101-
true
10295
}
103-
_ => false,
96+
return true;
10497
}
98+
false
10599
}
106100
}

druid/src/app_delegate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'a> DelegateCtx<'a> {
5757
pub fn new_window<T: Any>(&mut self, desc: WindowDesc<T>) {
5858
if self.app_data_type == TypeId::of::<T>() {
5959
self.submit_command(
60-
Command::new(commands::NEW_WINDOW, SingleUse::new(desc)),
60+
Command::new(commands::NEW_WINDOW, SingleUse::new(Box::new(desc))),
6161
Target::Global,
6262
);
6363
} else {
@@ -77,7 +77,7 @@ impl<'a> DelegateCtx<'a> {
7777
pub fn set_menu<T: Any>(&mut self, menu: MenuDesc<T>, window: WindowId) {
7878
if self.app_data_type == TypeId::of::<T>() {
7979
self.submit_command(
80-
Command::new(commands::SET_MENU, menu),
80+
Command::new(commands::SET_MENU, Box::new(menu)),
8181
Target::Window(window),
8282
);
8383
} else {

0 commit comments

Comments
 (0)