diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d3fa3d2a..70e91e0248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ You can find its changes [documented below](#070---2021-01-01). ### Changed +- Warn on unhandled Commands ([#1533] by [@Maan2003]) + ### Deprecated ### Removed @@ -603,6 +605,7 @@ Last release without a changelog :( [#1523]: https://github.com/linebender/druid/pull/1523 [#1526]: https://github.com/linebender/druid/pull/1526 [#1532]: https://github.com/linebender/druid/pull/1532 +[#1533]: https://github.com/linebender/druid/pull/1533 [#1534]: https://github.com/linebender/druid/pull/1534 [#1254]: https://github.com/linebender/druid/pull/1254 diff --git a/druid/src/command.rs b/druid/src/command.rs index 16ee68b416..c043b66c87 100644 --- a/druid/src/command.rs +++ b/druid/src/command.rs @@ -25,7 +25,18 @@ use crate::{WidgetId, WindowId}; /// The identity of a [`Selector`]. /// /// [`Selector`]: struct.Selector.html -pub(crate) type SelectorSymbol = &'static str; +#[derive(Copy, Clone, PartialEq, Eq)] +pub(crate) struct SelectorSymbol { + str: &'static str, + must_use: bool, +} + +impl std::fmt::Debug for SelectorSymbol { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let must_use = if self.must_use { " (must_use)" } else { "" }; + write!(f, "{}{}", self.str, must_use) + } +} /// An identifier for a particular command. /// @@ -329,8 +340,25 @@ impl Selector<()> { impl Selector { /// Create a new `Selector` with the given string. - pub const fn new(s: &'static str) -> Selector { - Selector(s, PhantomData) + pub const fn new(str: &'static str) -> Selector { + Selector( + SelectorSymbol { + str, + must_use: false, + }, + PhantomData, + ) + } + + /// Create a `Selector` that must be used. + pub const fn must_use(str: &'static str) -> Selector { + Selector( + SelectorSymbol { + str, + must_use: true, + }, + PhantomData, + ) } /// Returns the `SelectorSymbol` identifying this `Selector`. @@ -384,6 +412,11 @@ impl Command { .default_to(Target::Global) } + /// Checks if this command must be used. + pub fn must_be_used(&self) -> bool { + self.symbol.must_use + } + /// A helper method for creating a `Notification` from a `Command`. /// /// This is slightly icky; it lets us do `SOME_SELECTOR.with(SOME_PAYLOAD)` @@ -408,6 +441,14 @@ impl Command { self } + /// Make the `Command` must use. + /// + /// this will log warning if this `Command` is not handled. + pub fn must_use(mut self, must_use: bool) -> Self { + self.symbol.must_use = must_use; + self + } + /// Set the correct default target when target is `Auto`. pub(crate) fn default_to(mut self, target: Target) -> Self { self.target.default(target); @@ -446,7 +487,7 @@ impl Command { if self.symbol == selector.symbol() { Some(self.payload.downcast_ref().unwrap_or_else(|| { panic!( - "The selector \"{}\" exists twice with different types. See druid::Command::get for more information", + "The selector {:?} exists twice with different types. See druid::Command::get for more information", selector.symbol() ); })) @@ -472,7 +513,7 @@ impl Command { pub fn get_unchecked(&self, selector: Selector) -> &T { self.get(selector).unwrap_or_else(|| { panic!( - "Expected selector \"{}\" but the command was \"{}\".", + "Expected selector {:?} but the command was {:?}.", selector.symbol(), self.symbol ) @@ -499,7 +540,7 @@ impl Notification { if self.symbol == selector.symbol() { Some(self.payload.downcast_ref().unwrap_or_else(|| { panic!( - "The selector \"{}\" exists twice with different types. \ + "The selector {:?} exists twice with different types. \ See druid::Command::get for more information", selector.symbol() ); @@ -541,7 +582,7 @@ impl From for Command { impl std::fmt::Display for Selector { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "Selector(\"{}\", {})", self.0, any::type_name::()) + write!(f, "Selector({:?}, {})", self.0, any::type_name::()) } } @@ -591,7 +632,7 @@ impl std::fmt::Debug for Notification { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, - "Notification: Selector {} from {:?}", + "Notification: Selector {:?} from {:?}", self.symbol, self.source ) } diff --git a/druid/src/win_handler.rs b/druid/src/win_handler.rs index 03af420d53..bcf0f9759e 100644 --- a/druid/src/win_handler.rs +++ b/druid/src/win_handler.rs @@ -643,7 +643,10 @@ impl AppState { log::warn!("SHOW_WINDOW command must target a window.") } _ => { - self.inner.borrow_mut().dispatch_cmd(cmd); + let handled = self.inner.borrow_mut().dispatch_cmd(cmd.clone()); + if !handled.is_handled() && cmd.must_be_used() { + log::warn!("{:?} was not handled.", cmd); + } } } }