Skip to content

Commit

Permalink
fix(tui): send key, mouse, and paste events only to active component
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-ferdinand committed Feb 2, 2024
1 parent 3c9ea1c commit 74e42d3
Showing 1 changed file with 102 additions and 46 deletions.
148 changes: 102 additions & 46 deletions triton-tui/src/triton_tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crossterm::event::KeyEventKind;
use ratatui::prelude::Rect;
use strum::EnumCount;
use tokio::sync::mpsc;
use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::mpsc::UnboundedSender;

use crate::action::*;
Expand Down Expand Up @@ -75,60 +76,104 @@ impl TritonTUI {
component.register_action_handler(action_tx.clone())?;
}

// in case of infinite loop (or similar) before first breakpoint, provide visual feedback
self.render()?;

while !self.should_quit {
if let Some(e) = self.tui.next().await {
match e {
Event::Quit => action_tx.send(Action::Quit)?,
Event::Tick => action_tx.send(Action::Tick)?,
Event::Render => action_tx.send(Action::Render)?,
Event::Key(key) => self.handle_key_sequence(&action_tx, key)?,
Event::Resize(x, y) => action_tx.send(Action::Resize(x, y))?,
_ => {}
}
for component in self.components.iter_mut() {
if let Some(action) = component.handle_event(Some(e.clone()))? {
action_tx.send(action)?;
}
}
self.handle_events_and_actions(&action_tx, &mut action_rx)
.await?;
}

self.tui.exit()
}

async fn handle_events_and_actions(
&mut self,
action_tx: &UnboundedSender<Action>,
action_rx: &mut UnboundedReceiver<Action>,
) -> Result<()> {
self.handle_next_event(action_tx).await?;
self.handle_actions(action_tx, action_rx)?;
self.maybe_suspend(action_tx)?;
Ok(())
}

async fn handle_next_event(&mut self, action_tx: &UnboundedSender<Action>) -> Result<()> {
let Some(event) = self.tui.next().await else {
return Ok(());
};

match event {
Event::Quit => action_tx.send(Action::Quit)?,
Event::Tick => action_tx.send(Action::Tick)?,
Event::Render => action_tx.send(Action::Render)?,
Event::Key(key) => self.handle_key_sequence(action_tx, key)?,
Event::Resize(x, y) => action_tx.send(Action::Resize(x, y))?,
_ => {}
}

match event {
Event::Key(_) | Event::Mouse(_) | Event::Paste(_) => {
self.dispatch_event_to_active_component(event, action_tx)
}
_ => self.dispatch_event_to_all_components(event, action_tx),
}
}

fn dispatch_event_to_active_component(
&mut self,
event: Event,
action_tx: &UnboundedSender<Action>,
) -> Result<()> {
let active_component = &mut self.components[self.mode.id()];
if let Some(action) = active_component.handle_event(Some(event.clone()))? {
action_tx.send(action)?;
}
Ok(())
}

fn dispatch_event_to_all_components(
&mut self,
event: Event,
action_tx: &UnboundedSender<Action>,
) -> Result<()> {
for component in self.components.iter_mut() {
if let Some(action) = component.handle_event(Some(event.clone()))? {
action_tx.send(action)?;
}
}
Ok(())
}

while let Ok(action) = action_rx.try_recv() {
match action {
Action::Tick => self.maybe_clear_recent_key_events(),
Action::Render => self.render()?,
Action::Resize(w, h) => {
self.tui.resize(Rect::new(0, 0, w, h))?;
self.render()?;
}
Action::Mode(mode) => {
self.mode = mode;
self.render()?;
}
Action::Reset => self.reset_state(action_tx.clone())?,
Action::Suspend => self.should_suspend = true,
Action::Resume => self.should_suspend = false,
Action::Quit => self.should_quit = true,
_ => {}
fn handle_actions(
&mut self,
action_tx: &UnboundedSender<Action>,
action_rx: &mut UnboundedReceiver<Action>,
) -> Result<()> {
while let Ok(action) = action_rx.try_recv() {
match action {
Action::Tick => self.maybe_clear_recent_key_events(),
Action::Render => self.render()?,
Action::Resize(w, h) => {
self.tui.resize(Rect::new(0, 0, w, h))?;
self.render()?;
}
self.vm_state.update(action.clone())?;
for component in self.components.iter_mut() {
if let Some(action) = component.update(action.clone())? {
action_tx.send(action)?
};
Action::Mode(mode) => {
self.mode = mode;
self.render()?;
}
Action::Reset => self.reset_state(action_tx.clone())?,
Action::Suspend => self.should_suspend = true,
Action::Resume => self.should_suspend = false,
Action::Quit => self.should_quit = true,
_ => {}
}
if self.should_suspend {
self.tui.suspend()?;
action_tx.send(Action::Resume)?;
self.tui = Self::tui(&self.args)?;
self.tui.resume()?;

self.vm_state.update(action.clone())?;
for component in self.components.iter_mut() {
if let Some(action) = component.update(action.clone())? {
action_tx.send(action)?
};
}
}

self.tui.exit()
Ok(())
}

fn maybe_clear_recent_key_events(&mut self) {
Expand All @@ -153,6 +198,17 @@ impl TritonTUI {
Ok(())
}

fn maybe_suspend(&mut self, action_tx: &UnboundedSender<Action>) -> Result<()> {
if self.should_suspend {
self.tui.suspend()?;
action_tx.send(Action::Resume)?;
self.tui = Self::tui(&self.args)?;
self.tui.resume()?;
}

Ok(())
}

fn tui(args: &TuiArgs) -> Result<Tui> {
let mut tui = Tui::new()?;
tui.apply_args(args);
Expand Down

0 comments on commit 74e42d3

Please sign in to comment.