mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-22 05:12:27 +00:00
feat: add mouse scrolling
This commit is contained in:
parent
79eb752552
commit
ee090dd31f
|
@ -32,7 +32,7 @@ setupBluetooth() {
|
||||||
# Function to display the main menu
|
# Function to display the main menu
|
||||||
main_menu() {
|
main_menu() {
|
||||||
while true; do
|
while true; do
|
||||||
clear
|
|
||||||
printf "%b\n" "${YELLOW}Bluetooth Manager${RC}"
|
printf "%b\n" "${YELLOW}Bluetooth Manager${RC}"
|
||||||
printf "%b\n" "${YELLOW}=================${RC}"
|
printf "%b\n" "${YELLOW}=================${RC}"
|
||||||
printf "%b\n" "1. Scan for devices"
|
printf "%b\n" "1. Scan for devices"
|
||||||
|
@ -58,7 +58,7 @@ main_menu() {
|
||||||
|
|
||||||
# Function to scan for devices
|
# Function to scan for devices
|
||||||
scan_devices() {
|
scan_devices() {
|
||||||
clear
|
|
||||||
printf "%b\n" "${YELLOW}Scanning for devices...${RC}"
|
printf "%b\n" "${YELLOW}Scanning for devices...${RC}"
|
||||||
bluetoothctl --timeout 10 scan on
|
bluetoothctl --timeout 10 scan on
|
||||||
devices=$(bluetoothctl devices)
|
devices=$(bluetoothctl devices)
|
||||||
|
@ -81,7 +81,7 @@ prompt_for_mac() {
|
||||||
failure_msg=$5
|
failure_msg=$5
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
clear
|
|
||||||
devices=$(bluetoothctl devices)
|
devices=$(bluetoothctl devices)
|
||||||
if [ -z "$devices" ]; then
|
if [ -z "$devices" ]; then
|
||||||
printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}"
|
printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}"
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::{float::FloatContent, hint::Shortcut};
|
use crate::{float::FloatContent, hint::Shortcut};
|
||||||
|
|
||||||
use crossterm::event::{KeyCode, KeyEvent};
|
use crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::Alignment,
|
layout::Alignment,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
@ -84,6 +84,21 @@ impl FloatContent for ConfirmPrompt {
|
||||||
frame.render_widget(List::new(paths_text), inner_area);
|
frame.render_widget(List::new(paths_text), inner_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
|
||||||
|
match event.kind {
|
||||||
|
MouseEventKind::ScrollDown => {
|
||||||
|
self.scroll_down();
|
||||||
|
ConfirmStatus::None
|
||||||
|
}
|
||||||
|
MouseEventKind::ScrollUp => {
|
||||||
|
self.scroll_up();
|
||||||
|
ConfirmStatus::None
|
||||||
|
}
|
||||||
|
_ => ConfirmStatus::None,
|
||||||
|
};
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
||||||
use KeyCode::*;
|
use KeyCode::*;
|
||||||
self.status = match key.code {
|
self.status = match key.code {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crossterm::event::{KeyCode, KeyEvent};
|
use crossterm::event::{KeyCode, KeyEvent, MouseEvent};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
Frame,
|
Frame,
|
||||||
|
@ -9,6 +9,7 @@ use crate::hint::Shortcut;
|
||||||
pub trait FloatContent {
|
pub trait FloatContent {
|
||||||
fn draw(&mut self, frame: &mut Frame, area: Rect);
|
fn draw(&mut self, frame: &mut Frame, area: Rect);
|
||||||
fn handle_key_event(&mut self, key: &KeyEvent) -> bool;
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool;
|
||||||
|
fn handle_mouse_event(&mut self, key: &MouseEvent) -> bool;
|
||||||
fn is_finished(&self) -> bool;
|
fn is_finished(&self) -> bool;
|
||||||
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>);
|
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,10 @@ impl<Content: FloatContent + ?Sized> Float<Content> {
|
||||||
self.content.draw(frame, popup_area);
|
self.content.draw(frame, popup_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_mouse_event(&mut self, event: &MouseEvent) {
|
||||||
|
self.content.handle_mouse_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if the floating window is finished.
|
// Returns true if the floating window is finished.
|
||||||
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
||||||
match key.code {
|
match key.code {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{float::FloatContent, hint::Shortcut};
|
||||||
|
|
||||||
use linutil_core::Command;
|
use linutil_core::Command;
|
||||||
|
|
||||||
use crossterm::event::{KeyCode, KeyEvent};
|
use crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind};
|
||||||
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::Rect,
|
layout::Rect,
|
||||||
|
@ -260,6 +260,15 @@ impl FloatContent for FloatingText {
|
||||||
frame.render_widget(list, inner_area);
|
frame.render_widget(list, inner_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
|
||||||
|
match event.kind {
|
||||||
|
MouseEventKind::ScrollDown => self.scroll_down(),
|
||||||
|
MouseEventKind::ScrollUp => self.scroll_up(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
||||||
use KeyCode::*;
|
use KeyCode::*;
|
||||||
match key.code {
|
match key.code {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::{
|
||||||
use crate::theme::Theme;
|
use crate::theme::Theme;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{self, DisableMouseCapture, Event, KeyEventKind},
|
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyEventKind},
|
||||||
style::ResetColor,
|
style::ResetColor,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
ExecutableCommand,
|
ExecutableCommand,
|
||||||
|
@ -41,6 +41,8 @@ fn main() -> io::Result<()> {
|
||||||
let mut state = AppState::new(args.theme, args.override_validation);
|
let mut state = AppState::new(args.theme, args.override_validation);
|
||||||
|
|
||||||
stdout().execute(EnterAlternateScreen)?;
|
stdout().execute(EnterAlternateScreen)?;
|
||||||
|
stdout().execute(EnableMouseCapture)?;
|
||||||
|
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
|
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
|
||||||
terminal.clear()?;
|
terminal.clear()?;
|
||||||
|
@ -70,15 +72,23 @@ fn run(
|
||||||
|
|
||||||
// It's guaranteed that the `read()` won't block when the `poll()`
|
// It's guaranteed that the `read()` won't block when the `poll()`
|
||||||
// function returns `true`
|
// function returns `true`
|
||||||
if let Event::Key(key) = event::read()? {
|
match event::read()? {
|
||||||
// We are only interested in Press and Repeat events
|
Event::Key(key) => {
|
||||||
if key.kind != KeyEventKind::Press && key.kind != KeyEventKind::Repeat {
|
if key.kind != KeyEventKind::Press && key.kind != KeyEventKind::Repeat {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !state.handle_key(&key) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::Mouse(mouse_event) => {
|
||||||
|
if !state.handle_mouse(&mouse_event) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
if !state.handle_key(&key) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{float::FloatContent, hint::Shortcut};
|
use crate::{float::FloatContent, hint::Shortcut};
|
||||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind};
|
||||||
use linutil_core::Command;
|
use linutil_core::Command;
|
||||||
use oneshot::{channel, Receiver};
|
use oneshot::{channel, Receiver};
|
||||||
use portable_pty::{
|
use portable_pty::{
|
||||||
|
@ -91,6 +91,18 @@ impl FloatContent for RunningCommand {
|
||||||
frame.render_widget(pseudo_term, area);
|
frame.render_widget(pseudo_term, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
|
||||||
|
match event.kind {
|
||||||
|
MouseEventKind::ScrollUp => {
|
||||||
|
self.scroll_offset = self.scroll_offset.saturating_add(1);
|
||||||
|
}
|
||||||
|
MouseEventKind::ScrollDown => {
|
||||||
|
self.scroll_offset = self.scroll_offset.saturating_sub(1);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
/// Handle key events of the running command "window". Returns true when the "window" should be
|
/// Handle key events of the running command "window". Returns true when the "window" should be
|
||||||
/// closed
|
/// closed
|
||||||
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
running_command::RunningCommand,
|
running_command::RunningCommand,
|
||||||
theme::Theme,
|
theme::Theme,
|
||||||
};
|
};
|
||||||
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind};
|
||||||
use ego_tree::NodeId;
|
use ego_tree::NodeId;
|
||||||
use linutil_core::{ListNode, Tab};
|
use linutil_core::{ListNode, Tab};
|
||||||
#[cfg(feature = "tips")]
|
#[cfg(feature = "tips")]
|
||||||
|
@ -406,6 +406,39 @@ impl AppState {
|
||||||
frame.render_widget(keybind_para, vertical[1]);
|
frame.render_widget(keybind_para, vertical[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_mouse(&mut self, event: &MouseEvent) -> bool {
|
||||||
|
if !self.drawable {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut self.focus {
|
||||||
|
Focus::TabList => match event.kind {
|
||||||
|
MouseEventKind::ScrollDown => {
|
||||||
|
self.current_tab.select_next();
|
||||||
|
self.refresh_tab();
|
||||||
|
}
|
||||||
|
MouseEventKind::ScrollUp => {
|
||||||
|
self.current_tab.select_next();
|
||||||
|
self.refresh_tab();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Focus::List => match event.kind {
|
||||||
|
MouseEventKind::ScrollDown => self.selection.select_next(),
|
||||||
|
MouseEventKind::ScrollUp => self.selection.select_previous(),
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Focus::FloatingWindow(float) => {
|
||||||
|
float.content.handle_mouse_event(event);
|
||||||
|
}
|
||||||
|
Focus::ConfirmationPrompt(confirm) => {
|
||||||
|
confirm.content.handle_mouse_event(event);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
|
pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
|
||||||
// This should be defined first to allow closing
|
// This should be defined first to allow closing
|
||||||
// the application even when not drawable ( If terminal is small )
|
// the application even when not drawable ( If terminal is small )
|
||||||
|
|
Loading…
Reference in New Issue
Block a user