Skip to content

Commit

Permalink
Add double and triple click selection (#295)
Browse files Browse the repository at this point in the history
* refactor: move selection things out of the renderer into its own struct

* refactor+feat: Move even more out of the renderer and add basic double and triple clicking

This is still realy broken

* fix: moved the logic to get the text behind an condition and could therefore remove some complexity

* fmt and adding selection for summarys

* fmt and adding selection for summarys
chore: removed an debug message

* Add must

This is added so we don't forget to redraw the window

Co-authored-by: CosmicHorror <CosmicHorrorDev@pm.me>

* Remove leftover comments

* Use more fitting types for durations

* Removed useless check

* fix: add check so double clicking whitespace doesn't select it and an check for the case cursor.index.. would retrun more than desired

* fmt

---------

Co-authored-by: CosmicHorror <CosmicHorrorDev@pm.me>
  • Loading branch information
kokoISnoTarget and CosmicHorrorDev authored Apr 13, 2024
1 parent 3cef713 commit c0541d7
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 133 deletions.
46 changes: 18 additions & 28 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub mod opts;
mod panic_hook;
pub mod positioner;
pub mod renderer;
pub mod selection;
pub mod table;
pub mod test_utils;
pub mod text;
Expand Down Expand Up @@ -56,6 +57,7 @@ use tracing_subscriber::util::SubscriberInitExt;
use utils::{ImageCache, Point, Rect, Size};

use crate::opts::{Commands, ConfigCmd, MetricsExporter};
use crate::selection::Selection;
use anyhow::Context;
use clap::Parser;
use taffy::Taffy;
Expand Down Expand Up @@ -147,6 +149,7 @@ pub struct Inlyne {
keycombos: KeyCombos,
need_repositioning: bool,
watcher: Watcher,
selection: Selection,
}

impl Inlyne {
Expand Down Expand Up @@ -221,6 +224,7 @@ impl Inlyne {
keycombos,
need_repositioning: false,
watcher,
selection: Selection::new(),
})
}

Expand Down Expand Up @@ -280,9 +284,7 @@ impl Inlyne {
let mut scrollbar_held = None;
let mut mouse_down = false;
let mut modifiers = ModifiersState::empty();
let mut last_loc = (0.0, 0.0);
let mut selection_cache = String::new();
let mut selecting = false;
let mut mouse_position: Point = Point::default();

let event_loop = self.event_loop.take().unwrap();
let event_loop_proxy = event_loop.create_proxy();
Expand Down Expand Up @@ -330,12 +332,9 @@ impl Inlyne {
);
self.renderer.set_scroll_y(self.renderer.scroll_y);
self.renderer
.redraw(&mut self.elements)
.redraw(&mut self.elements, &mut self.selection)
.context("Renderer failed to redraw the screen")
.unwrap();
if selecting {
selection_cache.clone_from(&self.renderer.selection_text);
}

histogram!(HistTag::Redraw).record(redraw_start.elapsed());
}
Expand Down Expand Up @@ -426,34 +425,24 @@ impl Inlyne {
* self.renderer.positioner.reserved_height;
self.renderer.set_scroll_y(target_scroll);
self.window.request_redraw();
} else if let Some(selection) = &mut self.renderer.selection {
if mouse_down {
selection.1 = loc;
selecting = true;
self.window.request_redraw();
}
} else if mouse_down && self.selection.handle_drag(loc) {
self.window.request_redraw();
}
last_loc = loc;
mouse_position = loc;
}
WindowEvent::MouseInput {
state,
button: MouseButton::Left,
..
} => match state {
ElementState::Pressed => {
// Reset selection
if self.renderer.selection.is_some() {
self.renderer.selection = None;
self.window.request_redraw();
}

// Try to click a link
let screen_size = self.renderer.screen_size();
if let Some(hoverable) = Self::find_hoverable(
&mut self.renderer.text_system,
&mut self.renderer.positioner.taffy,
&self.elements,
last_loc,
mouse_position,
screen_size,
self.renderer.zoom,
) {
Expand Down Expand Up @@ -504,20 +493,21 @@ impl Inlyne {
event_loop_proxy
.send_event(InlyneEvent::Reposition)
.unwrap();
self.renderer.selection = Some((last_loc, last_loc))
self.selection.add_position(mouse_position);
},
_ => self.renderer.selection = Some((last_loc, last_loc)),
_ => {
self.selection.add_position(mouse_position);
self.window.request_redraw();
}
};
} else if self.renderer.selection.is_none() {
self.renderer.selection = Some((last_loc, last_loc));
} else {
self.selection.add_position(mouse_position);
}

mouse_down = true;
}
ElementState::Released => {
scrollbar_held = None;
mouse_down = false;
selecting = false;
}
},
WindowEvent::ModifiersChanged(new_state) => modifiers = new_state,
Expand Down Expand Up @@ -587,7 +577,7 @@ impl Inlyne {
self.window.request_redraw();
}
Action::Copy => clipboard
.set_contents(selection_cache.trim().to_owned()),
.set_contents(self.selection.text.trim().to_owned()),
Action::Quit => *control_flow = ControlFlow::Exit,
Action::History(hist_dir) => {
let changed_path = match hist_dir {
Expand Down
80 changes: 37 additions & 43 deletions src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use crate::image::ImageRenderer;
use crate::metrics::{histogram, HistTag};
use crate::opts::FontOptions;
use crate::positioner::{Positioned, Positioner, DEFAULT_MARGIN};
use crate::selection::Selection;
use crate::table::TABLE_ROW_GAP;
use crate::text::{CachedTextArea, TextCache, TextSystem};
use crate::utils::{Point, Rect, Selection, Size};
use crate::utils::{Point, Rect, Size};
use crate::Element;

use anyhow::{Context, Ok};
Expand Down Expand Up @@ -45,8 +46,6 @@ pub struct Renderer {
pub page_width: f32,
pub image_renderer: ImageRenderer,
pub theme: Theme,
pub selection: Option<Selection>,
pub selection_text: String,
pub zoom: f32,
pub positioner: Positioner,
}
Expand Down Expand Up @@ -186,8 +185,6 @@ impl Renderer {
zoom: 1.,
image_renderer,
theme,
selection: None,
selection_text: String::new(),
positioner,
})
}
Expand All @@ -211,6 +208,7 @@ impl Renderer {
fn render_elements(
&mut self,
elements: &[Positioned<Element>],
selection: &mut Selection,
) -> anyhow::Result<Vec<CachedTextArea>> {
let mut text_areas: Vec<CachedTextArea> = Vec::new();
let screen_size = self.screen_size();
Expand Down Expand Up @@ -337,16 +335,13 @@ impl Renderer {
let max = (line.max.0, line.max.1 + 2. * self.hidpi_scale * self.zoom);
self.draw_rectangle(Rect::from_min_max(min, max), line.color)?;
}
if let Some(selection) = self.selection {
let (selection_rects, selection_text) = text_box.render_selection(
&mut self.text_system,
pos,
bounds,
self.zoom,
selection,
);
self.selection_text.push_str(&selection_text);
self.selection_text.push('\n');
if let Some(selection_rects) = text_box.render_selection(
&mut self.text_system,
pos,
bounds,
self.zoom,
selection,
) {
for rect in selection_rects {
self.draw_rectangle(
Rect::from_min_max(
Expand Down Expand Up @@ -379,16 +374,13 @@ impl Renderer {
self.zoom,
self.scroll_y,
));
if let Some(selection) = self.selection {
let (selection_rects, selection_text) = text_box.render_selection(
&mut self.text_system,
(pos.0 + node.location.x, pos.1 + node.location.y),
(node.size.width, node.size.height),
self.zoom,
selection,
);
self.selection_text.push_str(&selection_text);
self.selection_text.push('\n');
if let Some(selection_rects) = text_box.render_selection(
&mut self.text_system,
(pos.0 + node.location.x, pos.1 + node.location.y),
(node.size.width, node.size.height),
self.zoom,
selection,
) {
for rect in selection_rects {
self.draw_rectangle(
Rect::from_min_max(
Expand Down Expand Up @@ -442,17 +434,13 @@ impl Renderer {
self.scroll_y,
));

if let Some(selection) = self.selection {
let (selection_rects, selection_text) = text_box
.render_selection(
&mut self.text_system,
(pos.0 + node.location.x, pos.1 + node.location.y),
(node.size.width, node.size.height),
self.zoom,
selection,
);
self.selection_text.push_str(&selection_text);
self.selection_text.push('\n');
if let Some(selection_rects) = text_box.render_selection(
&mut self.text_system,
(pos.0 + node.location.x, pos.1 + node.location.y),
(node.size.width, node.size.height),
self.zoom,
selection,
) {
for rect in selection_rects {
self.draw_rectangle(
Rect::from_min_max(
Expand Down Expand Up @@ -512,7 +500,9 @@ impl Renderer {
)?;
}
}
Element::Row(row) => text_areas.append(&mut self.render_elements(&row.elements)?),
Element::Row(row) => {
text_areas.append(&mut self.render_elements(&row.elements, selection)?)
}
Element::Section(section) => {
if let Some(ref summary) = *section.summary {
let bounds = summary.bounds.as_ref().unwrap();
Expand All @@ -525,15 +515,16 @@ impl Renderer {
native_color(self.theme.text_color, &self.surface_format),
*section.hidden.borrow(),
)?;
text_areas.append(&mut self.render_elements(std::slice::from_ref(summary))?)
text_areas.append(
&mut self.render_elements(std::slice::from_ref(summary), selection)?,
)
}
if !*section.hidden.borrow() {
text_areas.append(&mut self.render_elements(&section.elements)?)
text_areas.append(&mut self.render_elements(&section.elements, selection)?)
}
}
}
}

self.draw_scrollbar()?;
Ok(text_areas)
}
Expand Down Expand Up @@ -721,7 +712,11 @@ impl Renderer {
bind_groups
}

pub fn redraw(&mut self, elements: &mut [Positioned<Element>]) -> anyhow::Result<()> {
pub fn redraw(
&mut self,
elements: &mut [Positioned<Element>],
selection: &mut Selection,
) -> anyhow::Result<()> {
let frame = self
.surface
.get_current_texture()
Expand All @@ -736,8 +731,7 @@ impl Renderer {
// Prepare and render elements that use lyon
self.lyon_buffer.indices.clear();
self.lyon_buffer.vertices.clear();
self.selection_text = String::new();
let cached_text_areas = self.render_elements(elements)?;
let cached_text_areas = self.render_elements(elements, selection)?;
let vertex_buf = self
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
Expand Down
Loading

0 comments on commit c0541d7

Please sign in to comment.