respond to mouse events
This commit is contained in:
+2
-2
@@ -285,7 +285,7 @@ impl Buffer {
|
|||||||
self.clamp_screen_to_primary_cursor(window_size);
|
self.clamp_screen_to_primary_cursor(window_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&mut self, window_size: WindowSize) {
|
pub fn scroll_down(&mut self, window_size: WindowSize) {
|
||||||
if self.contents.len() <= 5 * BYTES_PER_LINE { return; }
|
if self.contents.len() <= 5 * BYTES_PER_LINE { return; }
|
||||||
|
|
||||||
self.scroll_position = min(
|
self.scroll_position = min(
|
||||||
@@ -297,7 +297,7 @@ impl Buffer {
|
|||||||
self.combine_cursors_if_overlapping();
|
self.combine_cursors_if_overlapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&mut self, window_size: WindowSize) {
|
pub fn scroll_up(&mut self, window_size: WindowSize) {
|
||||||
self.scroll_position = self.scroll_position.saturating_sub(BYTES_PER_LINE);
|
self.scroll_position = self.scroll_position.saturating_sub(BYTES_PER_LINE);
|
||||||
self.primary_cursor.clamp(self.scroll_position, window_size.visible_byte_count());
|
self.primary_cursor.clamp(self.scroll_position, window_size.visible_byte_count());
|
||||||
self.combine_cursors_if_overlapping();
|
self.combine_cursors_if_overlapping();
|
||||||
|
|||||||
+74
-16
@@ -1,7 +1,7 @@
|
|||||||
use std::{env, process::exit};
|
use std::{env, process::exit};
|
||||||
use crossterm::{event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, terminal::window_size};
|
use crossterm::{ExecutableCommand, event::{self, DisableMouseCapture, Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}, terminal::window_size};
|
||||||
use ratatui::{style::Stylize, text::Span};
|
use ratatui::{DefaultTerminal, style::Stylize, text::Span};
|
||||||
use crate::{BYTES_PER_LINE, action::AppAction, buffer::Buffer, config::Config};
|
use crate::{BYTES_PER_LINE, action::AppAction, buffer::Buffer, config::Config, cursor::Cursor};
|
||||||
|
|
||||||
mod widget;
|
mod widget;
|
||||||
|
|
||||||
@@ -35,41 +35,43 @@ impl App {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let window_size = WindowSize {
|
||||||
|
rows: window_size().unwrap().rows as usize,
|
||||||
|
covered_rows: if buffers.len() > 1 {
|
||||||
|
2 // status line and tab bar
|
||||||
|
} else {
|
||||||
|
1 // status line
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config: Config::default(),
|
config: Config::default(),
|
||||||
|
|
||||||
buffers,
|
buffers,
|
||||||
current_buffer_index: 0,
|
current_buffer_index: 0,
|
||||||
|
|
||||||
window_size: WindowSize {
|
window_size,
|
||||||
rows: window_size().unwrap().rows as usize,
|
|
||||||
// 1 because of the status line
|
|
||||||
covered_rows: 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
should_quit: false,
|
should_quit: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
pub fn handle_events(&mut self, terminal: &mut DefaultTerminal) {
|
||||||
pub fn handle_events(&mut self) {
|
|
||||||
#[allow(clippy::collapsible_match)]
|
|
||||||
match event::read().unwrap() {
|
match event::read().unwrap() {
|
||||||
Event::Resize(_, height) => {
|
Event::Resize(_, height) => {
|
||||||
self.window_size.rows = height as usize;
|
self.window_size.rows = height as usize;
|
||||||
}
|
}
|
||||||
Event::Key(key_event) => self.handle_key(key_event),
|
Event::Key(key_event) => self.handle_key(key_event, terminal),
|
||||||
// Event::Mouse(mouse_event) => {
|
Event::Mouse(mouse_event) => self.handle_mouse(mouse_event),
|
||||||
// mouse_event.kind
|
|
||||||
// },
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_key(&mut self, key_event: KeyEvent) {
|
fn handle_key(&mut self, key_event: KeyEvent, terminal: &mut DefaultTerminal) {
|
||||||
if key_event.modifiers == KeyModifiers::CONTROL &&
|
if key_event.modifiers == KeyModifiers::CONTROL &&
|
||||||
key_event.code == KeyCode::Char('c')
|
key_event.code == KeyCode::Char('c')
|
||||||
{
|
{
|
||||||
|
terminal.backend_mut().execute(DisableMouseCapture).unwrap();
|
||||||
crossterm::terminal::disable_raw_mode().unwrap();
|
crossterm::terminal::disable_raw_mode().unwrap();
|
||||||
ratatui::restore();
|
ratatui::restore();
|
||||||
exit(130);
|
exit(130);
|
||||||
@@ -92,6 +94,62 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mouse(&mut self, mouse_event: MouseEvent) {
|
||||||
|
let tab_bar_rows = usize::from(self.buffers.len() > 1);
|
||||||
|
let current_buffer = &mut self.buffers[self.current_buffer_index];
|
||||||
|
|
||||||
|
match mouse_event.kind {
|
||||||
|
MouseEventKind::Down(_) => {
|
||||||
|
let byte_column = match mouse_event.column {
|
||||||
|
10..=11 => Some(0),
|
||||||
|
13..=14 => Some(1),
|
||||||
|
16..=17 => Some(2),
|
||||||
|
19..=20 => Some(3),
|
||||||
|
|
||||||
|
23..=24 => Some(4),
|
||||||
|
26..=27 => Some(5),
|
||||||
|
29..=30 => Some(6),
|
||||||
|
32..=33 => Some(7),
|
||||||
|
|
||||||
|
36..=37 => Some(8),
|
||||||
|
39..=40 => Some(9),
|
||||||
|
42..=43 => Some(10),
|
||||||
|
45..=46 => Some(11),
|
||||||
|
|
||||||
|
49..=50 => Some(12),
|
||||||
|
52..=53 => Some(13),
|
||||||
|
55..=56 => Some(14),
|
||||||
|
58..=59 => Some(15),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if let Some(byte_column) = byte_column &&
|
||||||
|
mouse_event.row as usize - tab_bar_rows < self.window_size.hex_rows()
|
||||||
|
{
|
||||||
|
current_buffer.primary_cursor = Cursor::at(
|
||||||
|
current_buffer.scroll_position +
|
||||||
|
(mouse_event.row as usize - tab_bar_rows) * BYTES_PER_LINE +
|
||||||
|
byte_column
|
||||||
|
);
|
||||||
|
current_buffer.cursors.clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MouseEventKind::ScrollDown => {
|
||||||
|
for _ in 0..3 {
|
||||||
|
current_buffer.scroll_down(self.window_size);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MouseEventKind::ScrollUp => {
|
||||||
|
for _ in 0..3 {
|
||||||
|
current_buffer.scroll_up(self.window_size);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn quit_if_saved(&mut self) {
|
fn quit_if_saved(&mut self) {
|
||||||
if self.buffers.iter().all(Buffer::all_changes_saved) {
|
if self.buffers.iter().all(Buffer::all_changes_saved) {
|
||||||
self.quit();
|
self.quit();
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ impl Buffer {
|
|||||||
primary_cursor: Cursor::default(),
|
primary_cursor: Cursor::default(),
|
||||||
cursors: Vec::new(),
|
cursors: Vec::new(),
|
||||||
|
|
||||||
marks: HashSet::from([0, 4, 12, 15, 16, 17]),
|
marks: HashSet::new(),
|
||||||
|
|
||||||
mode: Mode::Normal,
|
mode: Mode::Normal,
|
||||||
partial_action: None,
|
partial_action: None,
|
||||||
|
|||||||
+5
-2
@@ -5,6 +5,7 @@
|
|||||||
#![feature(hash_set_entry)]
|
#![feature(hash_set_entry)]
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
|
use crossterm::{QueueableCommand, event::{DisableMouseCapture, EnableMouseCapture}};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
@@ -22,9 +23,9 @@ const BYTES_PER_CHUNK: usize = 4;
|
|||||||
const CHUNKS_PER_LINE: usize = BYTES_PER_LINE / BYTES_PER_CHUNK;
|
const CHUNKS_PER_LINE: usize = BYTES_PER_LINE / BYTES_PER_CHUNK;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - m mark offset
|
|
||||||
// - search
|
// - search
|
||||||
// - s/A-k/A-K
|
// - s/A-k/A-K
|
||||||
|
// - C-a/C-x
|
||||||
// - modifications
|
// - modifications
|
||||||
// - insert/append
|
// - insert/append
|
||||||
// - mode
|
// - mode
|
||||||
@@ -56,15 +57,17 @@ fn main() {
|
|||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let mut terminal = ratatui::init();
|
let mut terminal = ratatui::init();
|
||||||
crossterm::terminal::enable_raw_mode().unwrap();
|
crossterm::terminal::enable_raw_mode().unwrap();
|
||||||
|
terminal.backend_mut().queue(EnableMouseCapture).unwrap();
|
||||||
|
|
||||||
while !app.should_quit {
|
while !app.should_quit {
|
||||||
terminal.draw(|frame| {
|
terminal.draw(|frame| {
|
||||||
frame.render_widget(&app, frame.area());
|
frame.render_widget(&app, frame.area());
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
app.handle_events();
|
app.handle_events(&mut terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal.backend_mut().queue(DisableMouseCapture).unwrap();
|
||||||
crossterm::terminal::disable_raw_mode().unwrap();
|
crossterm::terminal::disable_raw_mode().unwrap();
|
||||||
ratatui::restore();
|
ratatui::restore();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user