Partially implement scrollbar
This commit is contained in:
parent
c66a28320a
commit
ac3e7ade96
3 changed files with 124 additions and 54 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
|
@ -865,7 +865,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-text"
|
||||
version = "0.10.0"
|
||||
source = "git+https://github.com/pop-os/cosmic-text?branch=vi-editor#9efcc41a5aca6df16a66da53aae75b1191ba0576"
|
||||
source = "git+https://github.com/pop-os/cosmic-text?branch=vi-editor#e8dd8ec7d1a75219980a653998552a78eb9ec0c0"
|
||||
dependencies = [
|
||||
"fontdb 0.15.0",
|
||||
"libm",
|
||||
|
|
@ -874,7 +874,7 @@ dependencies = [
|
|||
"rangemap",
|
||||
"rustc-hash",
|
||||
"rustybuzz 0.11.0",
|
||||
"self_cell 1.0.1",
|
||||
"self_cell 1.0.2",
|
||||
"swash",
|
||||
"syntect",
|
||||
"sys-locale",
|
||||
|
|
@ -1206,9 +1206,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
|
||||
checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
|
||||
dependencies = [
|
||||
"humantime",
|
||||
"is-terminal",
|
||||
|
|
@ -2744,7 +2744,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "modit"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/modit.git#0bfedf9b11412b2f3612bdc5ffebcf882f88eb01"
|
||||
source = "git+https://github.com/pop-os/modit.git#6e8bcf69b7c2790e70c328374811699237520ba1"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
|
@ -3954,9 +3954,9 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
|
|||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c309e515543e67811222dbc9e3dd7e1056279b782e1dacffe4242b718734fb6"
|
||||
checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
|
@ -4081,9 +4081,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.1"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
|
||||
use cosmic::{
|
||||
app::{message, Command, Core, Settings},
|
||||
cosmic_config::{self, CosmicConfigEntry},
|
||||
|
|
@ -15,9 +17,7 @@ use cosmic::{
|
|||
};
|
||||
use cosmic_text::{Cursor, Edit, Family, FontSystem, SwashCache, SyntaxSystem, ViMode};
|
||||
use std::{
|
||||
env,
|
||||
fmt::Write,
|
||||
fs,
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
sync::Mutex,
|
||||
|
|
@ -927,8 +927,7 @@ impl cosmic::Application for App {
|
|||
}
|
||||
}
|
||||
};
|
||||
tab_column =
|
||||
tab_column.push(text_box(&tab.editor, self.config.metrics()).padding(8));
|
||||
tab_column = tab_column.push(text_box(&tab.editor, self.config.metrics()));
|
||||
tab_column = tab_column.push(text(status).font(cosmic::font::Font::MONOSPACE));
|
||||
}
|
||||
None => {
|
||||
|
|
|
|||
151
src/text_box.rs
151
src/text_box.rs
|
|
@ -5,13 +5,13 @@ use cosmic::{
|
|||
event::{Event, Status},
|
||||
keyboard::{Event as KeyEvent, KeyCode, Modifiers},
|
||||
mouse::{self, Button, Event as MouseEvent, ScrollDelta},
|
||||
Color, Element, Length, Padding, Rectangle, Size,
|
||||
Color, Element, Length, Padding, Point, Rectangle, Size, Vector,
|
||||
},
|
||||
iced_core::{
|
||||
clipboard::Clipboard,
|
||||
image,
|
||||
layout::{self, Layout},
|
||||
renderer,
|
||||
renderer::{self, Quad},
|
||||
widget::{self, tree, Widget},
|
||||
Shell,
|
||||
},
|
||||
|
|
@ -195,17 +195,32 @@ where
|
|||
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
_tree: &widget::Tree,
|
||||
tree: &widget::Tree,
|
||||
layout: Layout<'_>,
|
||||
cursor_position: mouse::Cursor,
|
||||
_viewport: &Rectangle,
|
||||
_renderer: &Renderer,
|
||||
) -> mouse::Interaction {
|
||||
if cursor_position.is_over(layout.bounds()) {
|
||||
mouse::Interaction::Text
|
||||
} else {
|
||||
mouse::Interaction::Idle
|
||||
let state = tree.state.downcast_ref::<State>();
|
||||
|
||||
match &state.dragging {
|
||||
Some(Dragging::Scrollbar { .. }) => return mouse::Interaction::Idle,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(p) = cursor_position.position_in(layout.bounds()) {
|
||||
let scale_factor = state.scale_factor.get();
|
||||
let editor = self.editor.lock().unwrap();
|
||||
let buffer_size = editor.buffer().size();
|
||||
|
||||
let x = (p.x - self.padding.left) * scale_factor;
|
||||
let y = (p.y - self.padding.top) * scale_factor;
|
||||
if x >= 0.0 && x < buffer_size.0 && y >= 0.0 && y < buffer_size.1 {
|
||||
return mouse::Interaction::Text;
|
||||
}
|
||||
}
|
||||
|
||||
mouse::Interaction::Idle
|
||||
}
|
||||
|
||||
fn draw(
|
||||
|
|
@ -250,10 +265,12 @@ where
|
|||
let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32)
|
||||
- self.padding.vertical() as i32;
|
||||
|
||||
let scale_factor = style.scale_factor;
|
||||
let scale_factor = style.scale_factor as f32;
|
||||
|
||||
let image_w = (view_w as f64 * scale_factor) as i32;
|
||||
let image_h = (view_h as f64 * scale_factor) as i32;
|
||||
let image_w = (view_w as f32 * scale_factor) as i32;
|
||||
let image_h = (view_h as f32 * scale_factor) as i32;
|
||||
|
||||
//TODO: make this configurable and do not repeat
|
||||
let scrollbar_w = (8.0 * scale_factor) as i32;
|
||||
|
||||
if image_w <= scrollbar_w || image_h <= 0 {
|
||||
|
|
@ -261,12 +278,15 @@ where
|
|||
return;
|
||||
}
|
||||
|
||||
// Adjust image width by scrollbar width
|
||||
let image_w = image_w - scrollbar_w;
|
||||
|
||||
let mut font_system = FONT_SYSTEM.lock().unwrap();
|
||||
let mut editor = editor.borrow_with(&mut font_system);
|
||||
|
||||
// Set metrics and size
|
||||
editor.buffer_mut().set_metrics_and_size(
|
||||
self.metrics.scale(scale_factor as f32),
|
||||
self.metrics.scale(scale_factor),
|
||||
image_w as f32,
|
||||
image_h as f32,
|
||||
);
|
||||
|
|
@ -293,7 +313,7 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
// Draw scrollbar
|
||||
// Calculate scrollbar
|
||||
{
|
||||
let mut start_line_opt = None;
|
||||
let mut end_line = 0;
|
||||
|
|
@ -308,16 +328,15 @@ where
|
|||
let lines = editor.buffer().lines.len();
|
||||
let start_y = (start_line * image_h as usize) / lines;
|
||||
let end_y = ((end_line * image_h as usize) / lines).max(start_y + 1);
|
||||
draw_rect(
|
||||
buffer,
|
||||
image_w,
|
||||
image_h,
|
||||
image_w - scrollbar_w,
|
||||
start_y as i32,
|
||||
scrollbar_w,
|
||||
end_y as i32 - start_y as i32,
|
||||
0x40FFFFFF,
|
||||
|
||||
let rect = Rectangle::new(
|
||||
[image_w as f32 / scale_factor, start_y as f32 / scale_factor].into(),
|
||||
Size::new(
|
||||
scrollbar_w as f32 / scale_factor,
|
||||
(end_y as f32 - start_y as f32) / scale_factor,
|
||||
),
|
||||
);
|
||||
state.scrollbar_rect.set(rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -330,16 +349,35 @@ where
|
|||
}
|
||||
|
||||
let handle = state.handle.lock().unwrap().clone();
|
||||
let image_position =
|
||||
layout.position() + [self.padding.left as f32, self.padding.top as f32].into();
|
||||
let image_size = image::Renderer::dimensions(renderer, &handle);
|
||||
image::Renderer::draw(
|
||||
renderer,
|
||||
handle,
|
||||
Rectangle::new(
|
||||
layout.position() + [self.padding.left as f32, self.padding.top as f32].into(),
|
||||
Size::new(view_w as f32, view_h as f32),
|
||||
image_position,
|
||||
Size::new(image_size.width as f32, image_size.height as f32),
|
||||
),
|
||||
[0.0; 4],
|
||||
);
|
||||
|
||||
// Draw scrollbar
|
||||
let scrollbar_alpha = match &state.dragging {
|
||||
Some(Dragging::Scrollbar { .. }) => 0.5,
|
||||
_ => 0.25,
|
||||
};
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: state.scrollbar_rect.get()
|
||||
+ Vector::new(image_position.x, image_position.y),
|
||||
border_radius: 0.0.into(),
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
},
|
||||
Color::new(1.0, 1.0, 1.0, scrollbar_alpha),
|
||||
);
|
||||
|
||||
let duration = instant.elapsed();
|
||||
log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration);
|
||||
}
|
||||
|
|
@ -356,8 +394,10 @@ where
|
|||
_viewport: &Rectangle<f32>,
|
||||
) -> Status {
|
||||
let state = tree.state.downcast_mut::<State>();
|
||||
let scale_factor = state.scale_factor.get() as f32;
|
||||
let scale_factor = state.scale_factor.get();
|
||||
let scrollbar_rect = state.scrollbar_rect.get();
|
||||
let mut editor = self.editor.lock().unwrap();
|
||||
let buffer_size = editor.buffer().size();
|
||||
let mut font_system = FONT_SYSTEM.lock().unwrap();
|
||||
let mut editor = editor.borrow_with(&mut font_system);
|
||||
|
||||
|
|
@ -439,27 +479,51 @@ where
|
|||
}
|
||||
Event::Mouse(MouseEvent::ButtonPressed(Button::Left)) => {
|
||||
if let Some(p) = cursor_position.position_in(layout.bounds()) {
|
||||
editor.action(Action::Click {
|
||||
x: ((p.x - self.padding.left) * scale_factor) as i32,
|
||||
y: ((p.y - self.padding.top) * scale_factor) as i32,
|
||||
});
|
||||
state.is_dragging = true;
|
||||
let x = (p.x - self.padding.left) * scale_factor;
|
||||
let y = (p.y - self.padding.top) * scale_factor;
|
||||
if x >= 0.0 && x < buffer_size.0 && y >= 0.0 && y < buffer_size.1 {
|
||||
editor.action(Action::Click {
|
||||
x: x as i32,
|
||||
y: y as i32,
|
||||
});
|
||||
state.dragging = Some(Dragging::Buffer);
|
||||
} else if scrollbar_rect.contains(Point::new(x, y)) {
|
||||
state.dragging = Some(Dragging::Scrollbar {
|
||||
start_y: y,
|
||||
start_scroll: editor.buffer().scroll(),
|
||||
});
|
||||
}
|
||||
//TODO: support clicking below or above scrollbar
|
||||
status = Status::Captured;
|
||||
}
|
||||
}
|
||||
Event::Mouse(MouseEvent::ButtonReleased(Button::Left)) => {
|
||||
state.is_dragging = false;
|
||||
state.dragging = None;
|
||||
status = Status::Captured;
|
||||
}
|
||||
Event::Mouse(MouseEvent::CursorMoved { .. }) => {
|
||||
if state.is_dragging {
|
||||
if let Some(dragging) = &state.dragging {
|
||||
if let Some(p) = cursor_position.position() {
|
||||
editor.action(Action::Drag {
|
||||
x: (((p.x - layout.bounds().x) - self.padding.left) * scale_factor)
|
||||
as i32,
|
||||
y: (((p.y - layout.bounds().y) - self.padding.top) * scale_factor)
|
||||
as i32,
|
||||
});
|
||||
let x = ((p.x - layout.bounds().x) - self.padding.left) * scale_factor;
|
||||
let y = ((p.y - layout.bounds().y) - self.padding.top) * scale_factor;
|
||||
match dragging {
|
||||
Dragging::Buffer => {
|
||||
editor.action(Action::Drag {
|
||||
x: x as i32,
|
||||
y: y as i32,
|
||||
});
|
||||
}
|
||||
Dragging::Scrollbar {
|
||||
start_y,
|
||||
start_scroll,
|
||||
} => {
|
||||
let mut buffer = editor.buffer_mut();
|
||||
let scroll_offset = (((y - start_y) / buffer.size().1)
|
||||
* buffer.lines.len() as f32)
|
||||
as i32;
|
||||
buffer.set_scroll(start_scroll + scroll_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
status = Status::Captured;
|
||||
}
|
||||
|
|
@ -490,10 +554,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
enum Dragging {
|
||||
Buffer,
|
||||
Scrollbar { start_y: f32, start_scroll: i32 },
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
modifiers: Modifiers,
|
||||
is_dragging: bool,
|
||||
scale_factor: Cell<f64>,
|
||||
dragging: Option<Dragging>,
|
||||
scale_factor: Cell<f32>,
|
||||
scrollbar_rect: Cell<Rectangle<f32>>,
|
||||
handle: Mutex<image::Handle>,
|
||||
}
|
||||
|
||||
|
|
@ -502,8 +572,9 @@ impl State {
|
|||
pub fn new() -> State {
|
||||
State {
|
||||
modifiers: Modifiers::empty(),
|
||||
is_dragging: false,
|
||||
dragging: None,
|
||||
scale_factor: Cell::new(1.0),
|
||||
scrollbar_rect: Cell::new(Rectangle::default()),
|
||||
//TODO: make option!
|
||||
handle: Mutex::new(image::Handle::from_pixels(1, 1, vec![0, 0, 0, 0])),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue