Add context menu for opening links
This commit is contained in:
parent
8c409f5be3
commit
e7e47d5bac
6 changed files with 154 additions and 41 deletions
|
|
@ -44,8 +44,8 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Action, Terminal, TerminalScroll, key_bind::key_binds, mouse_reporter::MouseReporter,
|
||||
terminal::Metadata,
|
||||
Action, Terminal, TerminalScroll, key_bind::key_binds, menu::MenuState,
|
||||
mouse_reporter::MouseReporter, terminal::Metadata,
|
||||
};
|
||||
|
||||
pub struct TerminalBox<'a, Message> {
|
||||
|
|
@ -56,7 +56,7 @@ pub struct TerminalBox<'a, Message> {
|
|||
show_headerbar: bool,
|
||||
click_timing: Duration,
|
||||
context_menu: Option<Point>,
|
||||
on_context_menu: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_context_menu: Option<Box<dyn Fn(MenuState) -> Message + 'a>>,
|
||||
on_mouse_enter: Option<Box<dyn Fn() -> Message + 'a>>,
|
||||
opacity: Option<f32>,
|
||||
mouse_inside_boundary: Option<bool>,
|
||||
|
|
@ -124,10 +124,7 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
pub fn on_context_menu(
|
||||
mut self,
|
||||
on_context_menu: impl Fn(Option<Point>) -> Message + 'a,
|
||||
) -> Self {
|
||||
pub fn on_context_menu(mut self, on_context_menu: impl Fn(MenuState) -> Message + 'a) -> Self {
|
||||
self.on_context_menu = Some(Box::new(on_context_menu));
|
||||
self
|
||||
}
|
||||
|
|
@ -927,7 +924,7 @@ where
|
|||
} else {
|
||||
None
|
||||
};
|
||||
update_active_regex_match(&mut terminal, location, &state.modifiers);
|
||||
update_active_regex_match(&mut terminal, location, Some(&state.modifiers));
|
||||
}
|
||||
}
|
||||
Event::Keyboard(KeyEvent::KeyPressed {
|
||||
|
|
@ -1101,10 +1098,37 @@ where
|
|||
// Update context menu state
|
||||
if let Some(on_context_menu) = &self.on_context_menu {
|
||||
shell.publish((on_context_menu)(match self.context_menu {
|
||||
Some(_) => None,
|
||||
Some(_) => MenuState {
|
||||
position: None,
|
||||
link: None,
|
||||
},
|
||||
None => match button {
|
||||
Button::Right => Some(p),
|
||||
_ => None,
|
||||
Button::Right => {
|
||||
let x = p.x - self.padding.left;
|
||||
let y = p.y - self.padding.top;
|
||||
//TODO: better calculation of position
|
||||
let col = x / terminal.size().cell_width;
|
||||
let row = y / terminal.size().cell_height;
|
||||
|
||||
let location = terminal.viewport_to_point(TermPoint::new(
|
||||
row as usize,
|
||||
TermColumn(col as usize),
|
||||
));
|
||||
update_active_regex_match(
|
||||
&mut terminal,
|
||||
Some(location),
|
||||
None,
|
||||
);
|
||||
let link = get_hyperlink(&terminal, location);
|
||||
MenuState {
|
||||
position: Some(p),
|
||||
link,
|
||||
}
|
||||
}
|
||||
_ => MenuState {
|
||||
position: None,
|
||||
link: None,
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
|
@ -1125,14 +1149,7 @@ where
|
|||
.viewport_to_point(TermPoint::new(row as usize, TermColumn(col as usize)));
|
||||
if state.modifiers.control() {
|
||||
if let Some(on_open_hyperlink) = &self.on_open_hyperlink {
|
||||
if let Some(match_) = terminal
|
||||
.regex_matches
|
||||
.iter()
|
||||
.find(|bounds| bounds.contains(&location))
|
||||
{
|
||||
let term = terminal.term.lock();
|
||||
let hyperlink =
|
||||
term.bounds_to_string(*match_.start(), *match_.end());
|
||||
if let Some(hyperlink) = get_hyperlink(&terminal, location) {
|
||||
shell.publish(on_open_hyperlink(hyperlink));
|
||||
status = Status::Captured;
|
||||
}
|
||||
|
|
@ -1182,7 +1199,11 @@ where
|
|||
let row = y / terminal.size().cell_height;
|
||||
let location = terminal
|
||||
.viewport_to_point(TermPoint::new(row as usize, TermColumn(col as usize)));
|
||||
update_active_regex_match(&mut terminal, Some(location), &state.modifiers);
|
||||
update_active_regex_match(
|
||||
&mut terminal,
|
||||
Some(location),
|
||||
Some(&state.modifiers),
|
||||
);
|
||||
|
||||
if is_mouse_mode {
|
||||
terminal.report_mouse(event, &state.modifiers, col as u32, row as u32);
|
||||
|
|
@ -1283,7 +1304,11 @@ where
|
|||
row as usize,
|
||||
TermColumn(col as usize),
|
||||
));
|
||||
update_active_regex_match(&mut terminal, Some(location), &state.modifiers);
|
||||
update_active_regex_match(
|
||||
&mut terminal,
|
||||
Some(location),
|
||||
Some(&state.modifiers),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1294,17 +1319,35 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn get_hyperlink(
|
||||
terminal: &std::sync::MutexGuard<'_, Terminal>,
|
||||
location: TermPoint,
|
||||
) -> Option<String> {
|
||||
if let Some(match_) = terminal
|
||||
.regex_matches
|
||||
.iter()
|
||||
.find(|bounds| bounds.contains(&location))
|
||||
{
|
||||
let term = terminal.term.lock();
|
||||
Some(term.bounds_to_string(*match_.start(), *match_.end()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn update_active_regex_match(
|
||||
terminal: &mut std::sync::MutexGuard<'_, Terminal>,
|
||||
location: Option<TermPoint>,
|
||||
modifiers: &Modifiers,
|
||||
modifiers: Option<&Modifiers>,
|
||||
) {
|
||||
if !modifiers.contains(Modifiers::CTRL) {
|
||||
if terminal.active_regex_match.is_some() {
|
||||
terminal.active_regex_match = None;
|
||||
terminal.needs_update = true;
|
||||
if let Some(modifiers) = modifiers {
|
||||
if !modifiers.contains(Modifiers::CTRL) {
|
||||
if terminal.active_regex_match.is_some() {
|
||||
terminal.active_regex_match = None;
|
||||
terminal.needs_update = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
let Some(location) = location else {
|
||||
if terminal.active_regex_match.is_some() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue