Skip to content

Commit

Permalink
Refactoring key handling traits
Browse files Browse the repository at this point in the history
  • Loading branch information
nick42d committed Nov 25, 2024
1 parent 5a9c2a0 commit a494305
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 56 deletions.
91 changes: 49 additions & 42 deletions youtui/src/app/component/actionhandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,13 @@ pub trait Action {
/// NOTE: To implment this, the component can only have a single Action type.
// XXX: Could possibly be a part of EventHandler instead.
// XXX: Does this actually need to be a keyhandler?
pub trait KeyRouter<A: Action> {
pub trait KeyRouter<A: Action + 'static> {
/// Get the list of active keybinds that the component and its route
/// contain.
fn get_active_keybinds<'a>(&'a self) -> Box<dyn Iterator<Item = &'a KeyCommand<A>> + 'a>;
fn get_active_keybinds<'a>(&'a self) -> impl Iterator<Item = &'a KeyCommand<A>> + 'a;
/// Get the list of keybinds that the component and any child items can
/// contain, regardless of current route.
fn get_all_keybinds<'a>(&'a self) -> Box<dyn Iterator<Item = &'a KeyCommand<A>> + 'a>;
// e.g - for use in help menu.
fn get_all_visible_keybinds<'a>(&'a self) -> Box<dyn Iterator<Item = &'a KeyCommand<A>> + 'a> {
Box::new(
self.get_all_keybinds()
.filter(|kb| kb.visibility != CommandVisibility::Hidden),
)
}
// e.g - for use in header.
fn get_routed_global_keybinds<'a>(
&'a self,
) -> Box<dyn Iterator<Item = &'a KeyCommand<A>> + 'a> {
Box::new(
self.get_active_keybinds()
.filter(|kb| kb.visibility == CommandVisibility::Global),
)
}
fn get_all_keybinds<'a>(&'a self) -> impl Iterator<Item = &'a KeyCommand<A>> + 'a;
}

/// A component of the application that can block parent keybinds.
Expand All @@ -72,28 +56,51 @@ pub trait DominantKeyRouter {
fn dominant_keybinds_active(&self) -> bool;
}

/// A component of the application that can display all it's keybinds.
/// Not every KeyHandler/KeyRouter is a DisplayableKeyRouter - as
/// DisplayAbleKeyRouter unables conversion of typed Actions to generic.
// TODO: Type safety
// Could possibly be a part of EventHandler instead.
pub trait KeyDisplayer {
// XXX: Can these all just be derived from KeyRouter?
/// Get the list of all keybinds that the KeyHandler and any child items can
/// contain, regardless of context.
fn get_all_visible_keybinds_as_readable_iter<'a>(
&'a self,
) -> Box<dyn Iterator<Item = DisplayableCommand<'a>> + 'a>;
/// Get the list of all non-hidden keybinds that the KeyHandler and any
/// child items can contain, regardless of context.
fn get_all_keybinds_as_readable_iter<'a>(
&'a self,
) -> Box<dyn Iterator<Item = DisplayableCommand<'a>> + 'a>;
/// Get a context-specific list of all keybinds marked global.
// TODO: Put under DisplayableKeyHandler
fn get_context_global_keybinds_as_readable_iter<'a>(
&'a self,
) -> Box<dyn Iterator<Item = DisplayableCommand<'a>> + 'a>;
// XXX: Can these all just be derived from KeyRouter?
/// Get the list of all keybinds that the KeyHandler and any child items can
/// contain, regardless of context.
fn get_all_visible_keybinds_as_readable_iter<'a, K: KeyRouter<A>, A: Action + 'static>(
component: &'a K,
) -> Box<dyn Iterator<Item = DisplayableCommand<'a>> + 'a> {
component
.get_active_keybinds()
.filter(|kc| kc.visibility != CommandVisibility::Hidden)
.map(|kb| kb.as_displayable())
}
/// Get the list of all non-hidden keybinds that the KeyHandler and any
/// child items can contain, regardless of context.
fn get_all_keybinds_as_readable_iter<'a, K: KeyRouter<A>, A: Action + 'static>(
component: &'a K,
) -> Box<dyn Iterator<Item = DisplayableCommand<'a>> + 'a> {
component
.get_active_keybinds()
.map(|kb| kb.as_displayable())
}
/// Get a context-specific list of all keybinds marked global.
// TODO: Put under DisplayableKeyHandler
fn get_context_global_keybinds_as_readable_iter<'a, K: KeyRouter<A>, A: Action + 'static>(
component: &'a K,
) -> impl Iterator<Item = DisplayableCommand<'a>> + 'a {
component
.get_active_keybinds()
.filter(|kc| kc.visibility == CommandVisibility::Global)
.map(|kb| kb.as_displayable())
}
// e.g - for use in help menu.
fn get_all_visible_keybinds<'a, K: KeyRouter<A>, A: Action + 'static>(
component: &'a K,
) -> impl Iterator<Item = &'a KeyCommand<A>> + 'a {
component
.get_all_keybinds()
.filter(|kb| kb.visibility != CommandVisibility::Hidden)
}
// e.g - for use in header.
fn get_routed_global_keybinds<'a, K: KeyRouter<A>, A: Action + 'static>(
component: &'a K,
) -> impl Iterator<Item = &'a KeyCommand<A>> + 'a {
component
.get_active_keybinds()
.filter(|kb| kb.visibility == CommandVisibility::Global)
}
/// A component of the application that handles text entry, currently designed
/// to wrap rat_text::TextInputState.
Expand All @@ -116,7 +123,7 @@ pub trait TextHandler: Component {
Self: Sized;
/// Default behaviour is to only handle an event if is_text_handling() ==
/// true.
fn handle_event(&mut self, event: &Event) -> Option<AsyncTask<Self, Self::Bkend, Self::Md>>
fn try_handle_text(&mut self, event: &Event) -> Option<AsyncTask<Self, Self::Bkend, Self::Md>>
where
Self: Sized,
{
Expand Down
2 changes: 1 addition & 1 deletion youtui/src/app/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ impl YoutuiWindow {
&mut self,
event: crossterm::event::Event,
) -> ComponentEffect<Self> {
if let Some(effect) = self.handle_event(&event) {
if let Some(effect) = self.try_handle_text(&event) {
return effect;
};
match event {
Expand Down
1 change: 0 additions & 1 deletion youtui/src/app/ui/draw.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::{footer, header, WindowContext, YoutuiWindow};
use crate::app::component::actionhandler::KeyDisplayer;
use crate::app::keycommand::{DisplayableCommand, DisplayableMode};
use crate::app::view::draw::draw_panel;
use crate::app::view::{Drawable, DrawableMut};
Expand Down
15 changes: 5 additions & 10 deletions youtui/src/app/ui/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,11 @@ impl Drawable for Logger {
}
}

impl KeyRouter<LoggerAction> for Logger {
// XXX: Duplication of effort here due to trait structure - not the worst.
fn get_active_keybinds<'a>(
&'a self,
) -> Box<dyn Iterator<Item = &'a KeyCommand<LoggerAction>> + 'a> {
Box::new(self.keybinds.iter())
}
fn get_all_keybinds<'a>(
&'a self,
) -> Box<dyn Iterator<Item = &'a KeyCommand<LoggerAction>> + 'a> {
impl KeyRouter<AppAction> for Logger {
fn get_active_keybinds<'a>(&'a self) -> impl Iterator<Item = &'a KeyCommand<AppAction>> + 'a {
self.keybinds.iter()
}
fn get_all_keybinds<'a>(&'a self) -> impl Iterator<Item = &'a KeyCommand<AppAction>> + 'a {
self.get_active_keybinds()
}
}
Expand Down
4 changes: 2 additions & 2 deletions youtui/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::app::component::actionhandler::Action;
use crate::app::keycommand::CommandVisibility;
use crate::app::keycommand::Keybind;
use crate::app::ui::logger::LoggerActio;
use crate::app::ui::logger::LoggerAction;
use crate::app::ui::YoutuiWindow;
use crate::get_config_dir;
use crate::Result;
Expand Down Expand Up @@ -145,7 +145,7 @@ pub enum AppAction {
BrowserArtists(BrowserArtistsAction),
BrowserSearch(BrowserSearchAction),
BrowserSongs(BrowserSongsAction),
Log(LoggerActio),
Log(LoggerAction),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down

0 comments on commit a494305

Please sign in to comment.