Skip to content
This repository has been archived by the owner on Jul 25, 2024. It is now read-only.

Commit

Permalink
feat(mouse): add PopupState::handle_mouse_event() (#29)
Browse files Browse the repository at this point in the history
Converts a crossterm mouse event into mouse movement. Requires the
`crossterm` feature to be enabled.

```rust
if let Event::Mouse(event) = event::read()? {
    popup_state.handle_mouse_event(event);
}
```
  • Loading branch information
joshka authored Jul 7, 2024
1 parent 3433aec commit 3a7fd10
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 31 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rust-analyzer.cargo.features": ["crossterm"]
}
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@ edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[package.metadata.docs.rs]
all-features = true
# see https://doc.rust-lang.org/nightly/rustdoc/scraped-examples.html
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = []

## Enables processing crossterm mouse events using [`PopupState::handle_mouse_event`]
crossterm = ["ratatui/crossterm"]

[dependencies]
document-features = "0.2.0"
derive-getters = "0.4.0"
derive_setters = "0.1.6"
ratatui = { version = "0.27.0", features = ["unstable-widget-ref"] }
Expand All @@ -24,3 +37,8 @@ pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
unwrap_used = "warn"
expect_used = "warn"

[[example]]
name = "state"
required-features = ["crossterm"]
doc-scrape-examples = true # applies to all examples, not just this one
46 changes: 35 additions & 11 deletions bacon.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,50 @@ command = ["cargo", "check", "--all-targets", "--color", "always"]
need_stdout = false

[jobs.clippy]
command = [
"cargo", "clippy",
"--all-targets",
"--color", "always",
]
command = ["cargo", "clippy", "--all-targets", "--color", "always"]
need_stdout = false

[jobs.test]
command = [
"cargo", "test", "--color", "always",
"--", "--color", "always", # see https://github.com/Canop/bacon/issues/124
"cargo",
"test",
"--color",
"always",
"--",
"--color",
"always", # see https://github.com/Canop/bacon/issues/124
]
need_stdout = true

[jobs.doc]
command = ["cargo", "doc", "--color", "always", "--no-deps"]
command = [
"cargo",
"+nightly",
"doc",
"-Zunstable-options",
"-Zrustdoc-scrape-examples",
"--all-features",
"--color",
"always",
"--no-deps",
]
need_stdout = false

# If the doc compiles, then it opens in your browser and bacon switches
# to the previous job
[jobs.doc-open]
command = ["cargo", "doc", "--color", "always", "--no-deps", "--open"]
command = [
"cargo",
"+nightly",
"doc",
"-Zunstable-options",
"-Zrustdoc-scrape-examples",
"--all-features",
"--color",
"always",
"--no-deps",
"--open",
]
need_stdout = false
on_success = "back" # so that we don't open the browser at each change

Expand All @@ -47,8 +69,10 @@ on_success = "back" # so that we don't open the browser at each change
# properly parsed.
[jobs.run]
command = [
"cargo", "run",
"--color", "always",
"cargo",
"run",
"--color",
"always",
# put launch parameters for your program behind a `--` separator
]
need_stdout = true
Expand Down
17 changes: 2 additions & 15 deletions examples/state.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use color_eyre::Result;
use lipsum::lipsum;
use ratatui::{
crossterm::event::{
self, Event, KeyCode, KeyEvent, KeyEventKind, MouseButton, MouseEvent, MouseEventKind,
},
crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind},
prelude::{Constraint, Frame, Layout, Rect, Style, Stylize, Text},
widgets::{Paragraph, Wrap},
};
Expand Down Expand Up @@ -78,7 +76,7 @@ impl App {
fn handle_events(&mut self) -> Result<()> {
match event::read()? {
Event::Key(event) => self.handle_key_event(event),
Event::Mouse(event) => self.handle_mouse_event(event),
Event::Mouse(event) => self.popup.handle_mouse_event(event),
_ => (),
};
Ok(())
Expand All @@ -99,15 +97,4 @@ impl App {
_ => {}
}
}

fn handle_mouse_event(&mut self, event: MouseEvent) {
let popup = &mut self.popup;
// TODO: move mouse event handling to PopupState
match event.kind {
MouseEventKind::Down(MouseButton::Left) => popup.mouse_down(event.column, event.row),
MouseEventKind::Up(MouseButton::Left) => popup.mouse_up(event.column, event.row),
MouseEventKind::Drag(MouseButton::Left) => popup.mouse_drag(event.column, event.row),
_ => {}
};
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
//! ```
//!
//! ![demo](https://vhs.charm.sh/vhs-q5Kz0QP3zmrBlQ6dofjMh.gif)
//!
//! # Feature flags
#![doc = document_features::document_features!()]

mod popup;
mod state;
Expand Down
5 changes: 2 additions & 3 deletions src/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ use ratatui::{

/// Configuration for a popup.
///
/// This struct is used to configure a [`PopupWidget`]. It can be created using
/// [`Popup::new`](Popup::new). Convert it into a Ratatui widget using
/// [`Popup::to_widget`](Popup::to_widget).
/// This struct is used to configure a [`Popup`]. It can be created using
/// [`Popup::new`](Popup::new).
///
/// # Example
///
Expand Down
17 changes: 15 additions & 2 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use derive_getters::Getters;
use ratatui::prelude::*;
use ratatui::prelude::Rect;

#[cfg(feature = "crossterm")]
use ratatui::crossterm::event::{MouseButton, MouseEvent, MouseEventKind};

#[derive(Clone, Debug, Default, Getters)]
pub struct PopupState {
Expand Down Expand Up @@ -45,7 +48,7 @@ impl PopupState {
/// Set the state to dragging if the mouse click is in the popup title
pub fn mouse_down(&mut self, col: u16, row: u16) {
if let Some(area) = self.area {
if area.y == row && area.x <= col && col <= area.right() {
if area.contains((col, row).into()) {
self.mouse_state = MouseState::Dragging {
col_offset: col.saturating_sub(area.x),
row_offset: row.saturating_sub(area.y),
Expand Down Expand Up @@ -73,4 +76,14 @@ impl PopupState {
}
}
}

#[cfg(feature = "crossterm")]
pub fn handle_mouse_event(&mut self, event: MouseEvent) {
match event.kind {
MouseEventKind::Down(MouseButton::Left) => self.mouse_down(event.column, event.row),
MouseEventKind::Up(MouseButton::Left) => self.mouse_up(event.column, event.row),
MouseEventKind::Drag(MouseButton::Left) => self.mouse_drag(event.column, event.row),
_ => {}
}
}
}

0 comments on commit 3a7fd10

Please sign in to comment.